Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REFERENCE ONLY] hacks and fixes for cli unbox #1939

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion yarn-project/archiver/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createDebugLogger } from '@aztec/foundation/log';
import { fileURLToPath } from '@aztec/foundation/url';

import { fileURLToPath } from 'url';
import { createPublicClient, http } from 'viem';
import { localhost } from 'viem/chains';

Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec-cli/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { AztecRPC, createAztecRpcClient } from '@aztec/aztec.js';
import { makeFetch } from '@aztec/foundation/json-rpc/client';
import { DebugLogger } from '@aztec/foundation/log';
import { fileURLToPath } from '@aztec/foundation/url';

import { readFileSync } from 'fs';
import { dirname, resolve } from 'path';
import { gtr, ltr, satisfies, valid } from 'semver';
import { fileURLToPath } from 'url';

const retries = [1, 1, 2];

Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec-cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import {
import { StructType } from '@aztec/foundation/abi';
import { JsonStringify } from '@aztec/foundation/json-rpc';
import { DebugLogger, LogFn } from '@aztec/foundation/log';
import { fileURLToPath } from '@aztec/foundation/url';
import { compileContract } from '@aztec/noir-compiler/cli';
import { SchnorrAccountContractAbi } from '@aztec/noir-contracts/artifacts';
import { CompleteAddress, ContractData, L2BlockL2Logs, PrivateKey, TxHash } from '@aztec/types';

import { Command } from 'commander';
import { readFileSync } from 'fs';
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';
import { mnemonicToAccount } from 'viem/accounts';

import { createCompatibleClient } from './client.js';
Expand Down
163 changes: 131 additions & 32 deletions yarn-project/aztec-rpc/src/aztec_rpc_server/aztec_rpc_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,38 @@ import {
collectEncryptedLogs,
collectEnqueuedPublicFunctionCalls,
collectUnencryptedLogs,
processAcvmError,
} from '@aztec/acir-simulator';
import {
AztecAddress,
CompleteAddress,
EthAddress,
FunctionData,
KernelCircuitPublicInputs,
KernelCircuitPublicInputsFinal,
MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX,
PartialAddress,
PrivateKey,
PublicCallRequest,
} from '@aztec/circuits.js';
import { encodeArguments } from '@aztec/foundation/abi';
import { padArrayEnd } from '@aztec/foundation/collection';
import { Fr } from '@aztec/foundation/fields';
import { Fr, Point } from '@aztec/foundation/fields';
import { DebugLogger, createDebugLogger } from '@aztec/foundation/log';
import {
AztecNode,
AztecRPC,
ContractDao,
ContractData,
ContractDataAndBytecode,
DeployedContract,
ExtendedContractData,
FunctionCall,
INITIAL_L2_BLOCK_NUM,
KeyStore,
L2Block,
L2BlockL2Logs,
LogType,
NodeInfo,
SimulationError,
Tx,
TxExecutionRequest,
TxHash,
Expand All @@ -42,7 +45,7 @@ import {
toContractDao,
} from '@aztec/types';

import { RpcServerConfig } from '../config/index.js';
import { RpcServerConfig, getPackageInfo } from '../config/index.js';
import { ContractDataOracle } from '../contract_data_oracle/index.js';
import { Database } from '../database/index.js';
import { KernelOracle } from '../kernel_oracle/index.js';
Expand All @@ -56,6 +59,7 @@ import { Synchroniser } from '../synchroniser/index.js';
export class AztecRPCServer implements AztecRPC {
private synchroniser: Synchroniser;
private log: DebugLogger;
private clientInfo: string;

constructor(
private keyStore: KeyStore,
Expand All @@ -66,6 +70,9 @@ export class AztecRPCServer implements AztecRPC {
) {
this.log = createDebugLogger(logSuffix ? `aztec:rpc_server_${logSuffix}` : `aztec:rpc_server`);
this.synchroniser = new Synchroniser(node, db, logSuffix);

const { version, name } = getPackageInfo();
this.clientInfo = `${name.split('/')[name.split('/').length - 1]}@${version}`;
}

/**
Expand Down Expand Up @@ -144,17 +151,17 @@ export class AztecRPCServer implements AztecRPC {
}

public async addContracts(contracts: DeployedContract[]) {
const contractDaos = contracts.map(c => toContractDao(c.abi, c.address, c.portalContract));
const contractDaos = contracts.map(c => toContractDao(c.abi, c.completeAddress, c.portalContract));
await Promise.all(contractDaos.map(c => this.db.addContract(c)));
for (const contract of contractDaos) {
const portalInfo =
contract.portalContract && !contract.portalContract.isZero() ? ` with portal ${contract.portalContract}` : '';
this.log.info(`Added contract ${contract.name} at ${contract.address}${portalInfo}`);
this.log.info(`Added contract ${contract.name} at ${contract.completeAddress.address}${portalInfo}`);
}
}

public async getContracts(): Promise<AztecAddress[]> {
return (await this.db.getContracts()).map(c => c.address);
return (await this.db.getContracts()).map(c => c.completeAddress.address);
}

public async getPublicStorageAt(contract: AztecAddress, storageSlot: Fr) {
Expand All @@ -172,7 +179,7 @@ export class AztecRPCServer implements AztecRPC {
return await this.node.getBlock(blockNumber);
}

public async simulateTx(txRequest: TxExecutionRequest) {
public async simulateTx(txRequest: TxExecutionRequest, simulatePublic: boolean) {
if (!txRequest.functionData.isPrivate) {
throw new Error(`Public entrypoints are not allowed`);
}
Expand All @@ -186,13 +193,17 @@ export class AztecRPCServer implements AztecRPC {
const newContract = deployedContractAddress ? await this.db.getContract(deployedContractAddress) : undefined;

const tx = await this.#simulateAndProve(txRequest, newContract);
if (simulatePublic) await this.#simulatePublicCalls(tx);
this.log.info(`Executed local simulation for ${await tx.getTxHash()}`);

return tx;
}

public async sendTx(tx: Tx): Promise<TxHash> {
const txHash = await tx.getTxHash();
if (await this.node.getTx(txHash)) {
throw new Error(`A settled tx with equal hash ${txHash.toString()} exists.`);
}
this.log.info(`Sending transaction ${txHash}`);
await this.node.sendTx(tx);
return txHash;
Expand Down Expand Up @@ -235,8 +246,8 @@ export class AztecRPCServer implements AztecRPC {
return await this.node.getBlockNumber();
}

public async getContractDataAndBytecode(contractAddress: AztecAddress): Promise<ContractDataAndBytecode | undefined> {
return await this.node.getContractDataAndBytecode(contractAddress);
public async getExtendedContractData(contractAddress: AztecAddress): Promise<ExtendedContractData | undefined> {
return await this.node.getExtendedContractData(contractAddress);
}

public async getContractData(contractAddress: AztecAddress): Promise<ContractData | undefined> {
Expand Down Expand Up @@ -276,6 +287,7 @@ export class AztecRPCServer implements AztecRPC {
version,
chainId,
rollupAddress,
client: this.clientInfo,
};
}

Expand Down Expand Up @@ -321,10 +333,17 @@ export class AztecRPCServer implements AztecRPC {
const simulator = getAcirSimulator(this.db, this.node, this.node, this.node, this.keyStore, contractDataOracle);

this.log('Executing simulator...');
const result = await simulator.run(txRequest, functionAbi, contractAddress, portalContract);
this.log('Simulation completed!');

return result;
try {
const result = await simulator.run(txRequest, functionAbi, contractAddress, portalContract);
this.log('Simulation completed!');
return result;
} catch (err) {
if (err instanceof SimulationError) {
await this.#enrichSimulationError(err);
this.log(err.toString());
}
throw err;
}
}

/**
Expand All @@ -347,17 +366,63 @@ export class AztecRPCServer implements AztecRPC {
const simulator = getAcirSimulator(this.db, this.node, this.node, this.node, this.keyStore, contractDataOracle);

this.log('Executing unconstrained simulator...');
const result = await simulator.runUnconstrained(
execRequest,
from ?? AztecAddress.ZERO,
functionAbi,
contractAddress,
portalContract,
this.node,
);
this.log('Unconstrained simulation completed!');
try {
const result = await simulator.runUnconstrained(
execRequest,
from ?? AztecAddress.ZERO,
functionAbi,
contractAddress,
portalContract,
this.node,
);
this.log('Unconstrained simulation completed!');

return result;
} catch (err) {
if (err instanceof SimulationError) {
await this.#enrichSimulationError(err);
this.log(err.toString());
}
throw err;
}
}

return result;
/**
* Simulate the public part of a transaction.
* This allows to catch public execution errors before submitting the transaction.
* It can also be used for estimating gas in the future.
* @param tx - The transaction to be simulated.
*/
async #simulatePublicCalls(tx: Tx) {
try {
await this.node.simulatePublicCalls(tx);
} catch (err) {
// Try to fill in the noir call stack since the RPC server may have access to the debug metadata
if (err instanceof SimulationError) {
const callStack = err.getCallStack();
const originalFailingFunction = callStack[callStack.length - 1];
const contractDataOracle = new ContractDataOracle(this.db, this.node);
const debugInfo = await contractDataOracle.getFunctionDebugMetadata(
originalFailingFunction.contractAddress,
originalFailingFunction.functionSelector,
);
if (debugInfo) {
const noirCallStack = processAcvmError(err.message, debugInfo);
if (noirCallStack) {
err.setNoirCallStack(noirCallStack);
err.updateMessage(
`Assertion failed in public execution: '${
noirCallStack[noirCallStack.length - 1]?.locationText ?? 'Unknown'
}'`,
);
}
}
await this.#enrichSimulationError(err);
this.log(err.toString());
}

throw err;
}
}

/**
Expand Down Expand Up @@ -391,17 +456,51 @@ export class AztecRPCServer implements AztecRPC {
const unencryptedLogs = new TxL2Logs(collectUnencryptedLogs(executionResult));
const enqueuedPublicFunctions = collectEnqueuedPublicFunctionCalls(executionResult);

const contractData = new ContractData(newContract?.completeAddress.address ?? AztecAddress.ZERO, EthAddress.ZERO);
const extendedContractData = new ExtendedContractData(
contractData,
newContractPublicFunctions,
newContract?.completeAddress.partialAddress ?? Fr.ZERO,
newContract?.completeAddress.publicKey ?? Point.ZERO,
);

// HACK(#1639): Manually patches the ordering of the public call stack
// TODO(#757): Enforce proper ordering of enqueued public calls
await this.patchPublicCallStackOrdering(publicInputs, enqueuedPublicFunctions);

return new Tx(
publicInputs,
proof,
encryptedLogs,
unencryptedLogs,
newContractPublicFunctions,
enqueuedPublicFunctions,
return new Tx(publicInputs, proof, encryptedLogs, unencryptedLogs, enqueuedPublicFunctions, [extendedContractData]);
}

/**
* Adds contract and function names to a simulation error.
* @param err - The error to enrich.
*/
async #enrichSimulationError(err: SimulationError) {
// Maps contract addresses to the set of functions selectors that were in error.
// Using strings because map and set don't use .equals()
const mentionedFunctions: Map<string, Set<string>> = new Map();

err.getCallStack().forEach(({ contractAddress, functionSelector }) => {
if (!mentionedFunctions.has(contractAddress.toString())) {
mentionedFunctions.set(contractAddress.toString(), new Set());
}
mentionedFunctions.get(contractAddress.toString())!.add(functionSelector.toString());
});

await Promise.all(
[...mentionedFunctions.entries()].map(async ([contractAddress, selectors]) => {
const parsedContractAddress = AztecAddress.fromString(contractAddress);
const contract = await this.db.getContract(parsedContractAddress);
if (contract) {
err.enrichWithContractName(parsedContractAddress, contract.name);
selectors.forEach(selector => {
const functionAbi = contract.functions.find(f => f.selector.toString() === selector);
if (functionAbi) {
err.enrichWithFunctionName(parsedContractAddress, functionAbi.selector, functionAbi.name);
}
});
}
}),
);
}

Expand All @@ -413,7 +512,7 @@ export class AztecRPCServer implements AztecRPC {
// See https://github.com/AztecProtocol/aztec-packages/issues/1615
// TODO(#757): Enforce proper ordering of enqueued public calls
private async patchPublicCallStackOrdering(
publicInputs: KernelCircuitPublicInputs,
publicInputs: KernelCircuitPublicInputsFinal,
enqueuedPublicCalls: PublicCallRequest[],
) {
const callToHash = (call: PublicCallRequest) => call.toPublicCallStackItem().then(item => item.hash());
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/aztec-rpc/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { fileURLToPath } from '@aztec/foundation/url';

import { readFileSync } from 'fs';
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';

/**
* Configuration settings for the RPC Server.
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec-sandbox/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { PrivateKey } from '@aztec/circuits.js';
import { deployL1Contracts } from '@aztec/ethereum';
import { createDebugLogger } from '@aztec/foundation/log';
import { retryUntil } from '@aztec/foundation/retry';
import { fileURLToPath } from '@aztec/foundation/url';

import { readFileSync } from 'fs';
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';
import { HDAccount, createPublicClient, http as httpViemTransport } from 'viem';
import { mnemonicToAccount } from 'viem/accounts';
import { foundry } from 'viem/chains';
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/canary/src/aztec_js_browser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
import * as AztecJs from '@aztec/aztec.js';
import { AztecAddress, PrivateKey } from '@aztec/circuits.js';
import { DebugLogger, createDebugLogger } from '@aztec/foundation/log';
import { fileURLToPath } from '@aztec/foundation/url';
import { PrivateTokenContractAbi } from '@aztec/noir-contracts/artifacts';

import { Server } from 'http';
import Koa from 'koa';
import serve from 'koa-static';
import path, { dirname } from 'path';
import { Browser, Page, launch } from 'puppeteer';
import { fileURLToPath } from 'url';

declare global {
interface Window {
Expand Down
Binary file added yarn-project/circuits.js/aztec3-circuits.wasm
Binary file not shown.
1 change: 0 additions & 1 deletion yarn-project/circuits.js/resources/aztec3-circuits.wasm

This file was deleted.

Binary file not shown.
3 changes: 2 additions & 1 deletion yarn-project/circuits.js/src/cbind/circuits.in.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { fileURLToPath } from '@aztec/foundation/url';

import { writeFileSync } from 'fs';
import { dirname } from 'path';
import { fileURLToPath } from 'url';

import { CircuitsWasm } from '../wasm/circuits_wasm.js';
import { getCbindSchema } from './cbind.js';
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/circuits.js/src/cbind/constants.in.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { fileURLToPath } from '@aztec/foundation/url';

import * as fs from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';

import { CircuitsWasm } from '../wasm/circuits_wasm.js';
import { callCbind } from './cbind.js';
Expand Down
Loading