From 9b99126bb97b1beb1d922a3c404aecdaed0bee69 Mon Sep 17 00:00:00 2001 From: Gregorio Juliana Date: Sat, 11 Jan 2025 11:55:55 +0100 Subject: [PATCH] feat: simulator split (#11144) - Modularises `@aztec/simulator` to provide `/client` and `/server`bundles. - Makes both `bb-prover` and `pxe` take a `SimulatorProvider` as an argument, so web bundles can initialise a single wasm version on a common entrypoint. - Uses said simulator provider for everything! - Unifies aztec-packages to always use `acvm_js` to execute circuits, instead of sometimes `noir_js`(for protocol circuits). This forces some code repetiton ATM, but again, unifies codepaths and used dependencies. All of this allows us to again simplify the the web bundles and avoid the need for weird wasm initialization hacks. Async loading is also now properly supported, which allows us to display meaningful content on a webapp near instantly. --- boxes/boxes/vite/package.json | 4 +- boxes/boxes/vite/src/App.tsx | 24 +------- boxes/boxes/vite/src/config.ts | 41 ++++++------- boxes/boxes/vite/vite.config.ts | 5 +- boxes/yarn.lock | 22 +++---- .../aztec-node/src/aztec-node/server.ts | 2 +- .../prover/bb_native_private_kernel_prover.ts | 14 ++++- .../src/prover/bb_private_kernel_prover.ts | 14 +++-- .../bb-prover/src/prover/bb_prover.ts | 4 +- yarn-project/bb-prover/src/test/test_avm.ts | 2 +- .../bb-prover/src/test/test_circuit_prover.ts | 7 ++- .../src/wasm/bb_wasm_private_kernel_prover.ts | 4 +- yarn-project/bb-prover/src/wasm/bundle.ts | 5 +- yarn-project/bb-prover/src/wasm/lazy.ts | 5 +- .../end-to-end/src/e2e_block_building.test.ts | 7 ++- .../src/e2e_crowdfunding_and_claim.test.ts | 2 +- .../prover-client/src/mocks/fixtures.ts | 2 +- .../prover-client/src/mocks/test_context.ts | 2 +- .../orchestrator/block-building-helpers.ts | 2 +- .../orchestrator_failures.test.ts | 2 +- .../src/prover-client/prover-client.ts | 2 +- .../src/job/epoch-proving-job.test.ts | 2 +- .../prover-node/src/job/epoch-proving-job.ts | 2 +- .../prover-node/src/prover-node.test.ts | 2 +- yarn-project/prover-node/src/prover-node.ts | 2 +- yarn-project/pxe/src/database/note_dao.ts | 2 +- .../pxe/src/pxe_service/error_enriching.ts | 2 +- .../pxe/src/pxe_service/pxe_service.ts | 5 +- .../src/pxe_service/test/pxe_service.test.ts | 21 ++++++- yarn-project/pxe/src/simulator/index.ts | 6 +- .../pxe/src/simulator_oracle/index.ts | 12 +++- .../simulator_oracle/simulator_oracle.test.ts | 6 +- .../pxe/src/utils/create_pxe_service.ts | 13 ++-- .../src/client/sequencer-client.ts | 2 +- .../src/sequencer/sequencer.test.ts | 2 +- .../src/sequencer/sequencer.ts | 2 +- .../sequencer-client/src/test/index.ts | 2 +- .../src/tx_validator/gas_validator.ts | 2 +- .../src/tx_validator/phases_validator.ts | 2 +- .../src/tx_validator/tx_validator_factory.ts | 2 +- yarn-project/simulator/package.json | 5 +- yarn-project/simulator/src/acvm/acvm.ts | 2 +- yarn-project/simulator/src/acvm/index.ts | 2 +- .../simulator/src/acvm/oracle/typed_oracle.ts | 16 +---- .../simulator/src/avm/fixtures/index.ts | 3 +- .../src/avm/journal/nullifiers.test.ts | 2 +- .../simulator/src/avm/journal/nullifiers.ts | 2 +- .../src/avm/journal/public_storage.test.ts | 2 +- .../src/avm/journal/public_storage.ts | 2 +- .../src/client/client_execution_context.ts | 4 ++ yarn-project/simulator/src/client/index.ts | 14 ++++- .../src/client/private_execution.test.ts | 8 ++- .../simulator/src/client/private_execution.ts | 30 ++++++---- .../simulator/src/client/simulator.test.ts | 5 +- .../simulator/src/client/simulator.ts | 6 +- .../client/unconstrained_execution.test.ts | 5 +- .../src/client/unconstrained_execution.ts | 30 ++++++---- yarn-project/simulator/src/common.ts | 1 + .../src/common/message_load_oracle_inputs.ts | 15 +++++ .../src/common/simulation_provider.ts | 45 ++++++++++++++ .../simulator/src/providers/acvm_native.ts | 14 ++++- .../simulator/src/providers/acvm_wasm.ts | 45 +++++++++++--- .../src/providers/acvm_wasm_with_blobs.ts | 43 ++++++++++--- .../simulator/src/providers/factory.ts | 2 +- yarn-project/simulator/src/providers/index.ts | 2 +- .../src/providers/simulation_provider.ts | 10 ---- .../simulator/src/public/db_interfaces.ts | 2 +- .../simulator/src/public/fixtures/index.ts | 11 ++-- .../simulator/src/public/public_db_sources.ts | 9 +-- .../simulator/src/{index.ts => server.ts} | 2 - yarn-project/txe/src/oracle/txe_oracle.ts | 60 +++++++++++-------- .../txe/src/txe_service/txe_service.ts | 3 +- .../txe/src/util/txe_world_state_db.ts | 2 +- 73 files changed, 408 insertions(+), 257 deletions(-) create mode 100644 yarn-project/simulator/src/common.ts create mode 100644 yarn-project/simulator/src/common/message_load_oracle_inputs.ts create mode 100644 yarn-project/simulator/src/common/simulation_provider.ts delete mode 100644 yarn-project/simulator/src/providers/simulation_provider.ts rename yarn-project/simulator/src/{index.ts => server.ts} (71%) diff --git a/boxes/boxes/vite/package.json b/boxes/boxes/vite/package.json index c3301be3c0d..e05608b11c9 100644 --- a/boxes/boxes/vite/package.json +++ b/boxes/boxes/vite/package.json @@ -21,9 +21,7 @@ "@aztec/key-store": "link:../../../yarn-project/key-store", "@aztec/kv-store": "portal:../../../yarn-project/kv-store", "@aztec/pxe": "link:../../../yarn-project/pxe", - "@noir-lang/acvm_js": "link:../../../noir/packages/acvm_js", - "@noir-lang/noirc_abi": "link:../../../noir/packages/noirc_abi", - "buffer": "^6.0.3", + "@aztec/simulator": "link:../../../yarn-project/simulator", "react": "^18.3.1", "react-dom": "^18.3.1", "react-toastify": "^10.0.6" diff --git a/boxes/boxes/vite/src/App.tsx b/boxes/boxes/vite/src/App.tsx index daf6f6d9d8d..3633028ec16 100644 --- a/boxes/boxes/vite/src/App.tsx +++ b/boxes/boxes/vite/src/App.tsx @@ -2,33 +2,13 @@ import { ToastContainer } from "react-toastify"; import "react-toastify/dist/ReactToastify.css"; import "./App.css"; import { Home } from "./pages/home"; -import { useEffect, useState } from "react"; -import initACVM from "@noir-lang/acvm_js/web/acvm_js"; -import initABI from "@noir-lang/noirc_abi/web/noirc_abi_wasm"; -import acvmURL from "@noir-lang/acvm_js/web/acvm_js_bg.wasm?url"; -import abiURL from "@noir-lang/noirc_abi/web/noirc_abi_wasm_bg.wasm?url"; - -const InitWasm = ({ children }: any) => { - const [init, setInit] = useState(false); - useEffect(() => { - (async () => { - await Promise.all([ - initACVM(new URL(acvmURL, import.meta.url).toString()), - initABI(new URL(abiURL, import.meta.url).toString()), - ]); - setInit(true); - })(); - }, []); - - return
{init && children}
; -}; function App() { return ( - + <> - + ); } diff --git a/boxes/boxes/vite/src/config.ts b/boxes/boxes/vite/src/config.ts index 2413b3f5ff8..dbd86001d89 100644 --- a/boxes/boxes/vite/src/config.ts +++ b/boxes/boxes/vite/src/config.ts @@ -1,5 +1,4 @@ import { - AztecNode, Fr, createLogger, deriveMasterIncomingViewingSecretKey, @@ -12,10 +11,10 @@ import { PXEService } from "@aztec/pxe/service"; import { PXEServiceConfig, getPXEServiceConfig } from "@aztec/pxe/config"; import { KVPxeDatabase } from "@aztec/pxe/database"; import { KeyStore } from "@aztec/key-store"; -import { PrivateKernelProver } from "@aztec/circuit-types"; import { L2TipsStore } from "@aztec/kv-store/stores"; import { createStore } from "@aztec/kv-store/indexeddb"; import { BBWASMLazyPrivateKernelProver } from "@aztec/bb-prover/wasm/lazy"; +import { WASMSimulator } from "@aztec/simulator/client"; process.env = Object.keys(import.meta.env).reduce((acc, key) => { acc[key.replace("VITE_", "")] = import.meta.env[key]; @@ -39,25 +38,11 @@ export class PrivateEnv { config.dataDirectory = "pxe"; config.proverEnabled = true; const aztecNode = await createAztecNodeClient(this.nodeURL); - const proofCreator = new BBWASMLazyPrivateKernelProver(16); - this.pxe = await this.createPXEService(aztecNode, config, proofCreator); - const encryptionPrivateKey = deriveMasterIncomingViewingSecretKey( - this.secretKey, + const simulationProvider = new WASMSimulator(); + const proofCreator = new BBWASMLazyPrivateKernelProver( + simulationProvider, + 16, ); - this.accountContract = new SchnorrAccountContract(encryptionPrivateKey); - this.account = new AccountManager( - this.pxe, - this.secretKey, - this.accountContract, - ); - await this.account.deploy().wait(); - } - - async createPXEService( - aztecNode: AztecNode, - config: PXEServiceConfig, - proofCreator?: PrivateKernelProver, - ) { const l1Contracts = await aztecNode.getL1ContractAddresses(); const configWithContracts = { ...config, @@ -75,16 +60,26 @@ export class PrivateEnv { const db = await KVPxeDatabase.create(store); const tips = new L2TipsStore(store, "pxe"); - const pxe = new PXEService( + this.pxe = new PXEService( keyStore, aztecNode, db, tips, proofCreator, + simulationProvider, config, ); - await pxe.init(); - return pxe; + await this.pxe.init(); + const encryptionPrivateKey = deriveMasterIncomingViewingSecretKey( + this.secretKey, + ); + this.accountContract = new SchnorrAccountContract(encryptionPrivateKey); + this.account = new AccountManager( + this.pxe, + this.secretKey, + this.accountContract, + ); + await this.account.deploy().wait(); } async getWallet() { diff --git a/boxes/boxes/vite/vite.config.ts b/boxes/boxes/vite/vite.config.ts index 309b5eabdee..602fc1c226f 100644 --- a/boxes/boxes/vite/vite.config.ts +++ b/boxes/boxes/vite/vite.config.ts @@ -32,6 +32,8 @@ export default defineConfig({ allow: [ searchForWorkspaceRoot(process.cwd()), "../../../yarn-project/noir-protocol-circuits-types/artifacts", + "../../../noir/packages/noirc_abi/web", + "../../../noir/packages/acvm_js/web", ], }, }, @@ -51,7 +53,4 @@ export default defineConfig({ }, }, }, - optimizeDeps: { - exclude: ["@noir-lang/acvm_js", "@noir-lang/noirc_abi", "@aztec/bb-prover"], - }, }); diff --git a/boxes/yarn.lock b/boxes/yarn.lock index 79699d7e7f0..6f430a0fd08 100644 --- a/boxes/yarn.lock +++ b/boxes/yarn.lock @@ -139,6 +139,12 @@ __metadata: languageName: unknown linkType: soft +"@aztec/simulator@link:../../../yarn-project/simulator::locator=vite%40workspace%3Aboxes%2Fvite": + version: 0.0.0-use.local + resolution: "@aztec/simulator@link:../../../yarn-project/simulator::locator=vite%40workspace%3Aboxes%2Fvite" + languageName: node + linkType: soft + "@aztec/types@link:../yarn-project/types::locator=aztec-app%40workspace%3A.": version: 0.0.0-use.local resolution: "@aztec/types@link:../yarn-project/types::locator=aztec-app%40workspace%3A." @@ -1664,18 +1670,6 @@ __metadata: languageName: node linkType: hard -"@noir-lang/acvm_js@link:../../../noir/packages/acvm_js::locator=vite%40workspace%3Aboxes%2Fvite": - version: 0.0.0-use.local - resolution: "@noir-lang/acvm_js@link:../../../noir/packages/acvm_js::locator=vite%40workspace%3Aboxes%2Fvite" - languageName: node - linkType: soft - -"@noir-lang/noirc_abi@link:../../../noir/packages/noirc_abi::locator=vite%40workspace%3Aboxes%2Fvite": - version: 0.0.0-use.local - resolution: "@noir-lang/noirc_abi@link:../../../noir/packages/noirc_abi::locator=vite%40workspace%3Aboxes%2Fvite" - languageName: node - linkType: soft - "@nolyfill/is-core-module@npm:1.0.39": version: 1.0.39 resolution: "@nolyfill/is-core-module@npm:1.0.39" @@ -12162,13 +12156,11 @@ __metadata: "@aztec/key-store": "link:../../../yarn-project/key-store" "@aztec/kv-store": "portal:../../../yarn-project/kv-store" "@aztec/pxe": "link:../../../yarn-project/pxe" + "@aztec/simulator": "link:../../../yarn-project/simulator" "@eslint/js": "npm:^9.13.0" - "@noir-lang/acvm_js": "link:../../../noir/packages/acvm_js" - "@noir-lang/noirc_abi": "link:../../../noir/packages/noirc_abi" "@types/react": "npm:^18.3.12" "@types/react-dom": "npm:^18.3.1" "@vitejs/plugin-react-swc": "npm:^3.7.2" - buffer: "npm:^6.0.3" eslint: "npm:^9.13.0" eslint-plugin-react-hooks: "npm:^5.1.0" eslint-plugin-react-refresh: "npm:^0.4.16" diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 67e96b8e77c..647cf72f49d 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -73,7 +73,7 @@ import { createValidatorForAcceptingTxs, getDefaultAllowedSetupFunctions, } from '@aztec/sequencer-client'; -import { PublicProcessorFactory } from '@aztec/simulator'; +import { PublicProcessorFactory } from '@aztec/simulator/server'; import { Attributes, type TelemetryClient, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { createValidatorClient } from '@aztec/validator-client'; diff --git a/yarn-project/bb-prover/src/prover/bb_native_private_kernel_prover.ts b/yarn-project/bb-prover/src/prover/bb_native_private_kernel_prover.ts index cdb000404ec..87f9978db98 100644 --- a/yarn-project/bb-prover/src/prover/bb_native_private_kernel_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_native_private_kernel_prover.ts @@ -2,6 +2,7 @@ import { type ClientIvcProof } from '@aztec/circuits.js'; import { runInDirectory } from '@aztec/foundation/fs'; import { type Logger, createLogger } from '@aztec/foundation/log'; import { BundleArtifactProvider } from '@aztec/noir-protocol-circuits-types/client/bundle'; +import { type SimulationProvider } from '@aztec/simulator/server'; import { encode } from '@msgpack/msgpack'; import { serializeWitness } from '@noir-lang/noirc_abi'; @@ -22,14 +23,21 @@ export class BBNativePrivateKernelProver extends BBPrivateKernelProver { private bbBinaryPath: string, private bbWorkingDirectory: string, private skipCleanup: boolean, + protected override simulationProvider: SimulationProvider, protected override log = createLogger('bb-prover:native'), ) { - super(new BundleArtifactProvider(), log); + super(new BundleArtifactProvider(), simulationProvider, log); } - public static async new(config: BBConfig, log?: Logger) { + public static async new(config: BBConfig, simulationProvider: SimulationProvider, log?: Logger) { await fs.mkdir(config.bbWorkingDirectory, { recursive: true }); - return new BBNativePrivateKernelProver(config.bbBinaryPath, config.bbWorkingDirectory, !!config.bbSkipCleanup, log); + return new BBNativePrivateKernelProver( + config.bbBinaryPath, + config.bbWorkingDirectory, + !!config.bbSkipCleanup, + simulationProvider, + log, + ); } private async _createClientIvcProof( diff --git a/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts index 74dd829b09c..e8d530d7043 100644 --- a/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts @@ -27,7 +27,7 @@ import { } from '@aztec/noir-protocol-circuits-types/client'; import { type ArtifactProvider, type ClientProtocolArtifact } from '@aztec/noir-protocol-circuits-types/types'; import { ClientCircuitVks } from '@aztec/noir-protocol-circuits-types/vks'; -import { WASMSimulator } from '@aztec/simulator/client'; +import { type SimulationProvider } from '@aztec/simulator/client'; import { type NoirCompiledCircuit } from '@aztec/types/noir'; import { type Abi, type WitnessMap } from '@noir-lang/types'; @@ -35,9 +35,11 @@ import { type Abi, type WitnessMap } from '@noir-lang/types'; import { mapProtocolArtifactNameToCircuitName } from '../stats.js'; export abstract class BBPrivateKernelProver implements PrivateKernelProver { - protected simulator = new WASMSimulator(); - - constructor(protected artifactProvider: ArtifactProvider, protected log = createLogger('bb-prover')) {} + constructor( + protected artifactProvider: ArtifactProvider, + protected simulationProvider: SimulationProvider, + protected log = createLogger('bb-prover'), + ) {} public async generateInitOutput( inputs: PrivateKernelInitCircuitPrivateInputs, @@ -164,7 +166,7 @@ export abstract class BBPrivateKernelProver implements PrivateKernelProver { const witnessMap = convertInputs(inputs, compiledCircuit.abi); const timer = new Timer(); - const outputWitness = await this.simulator.simulateCircuit(witnessMap, compiledCircuit); + const outputWitness = await this.simulationProvider.executeProtocolCircuit(witnessMap, compiledCircuit); const output = convertOutputs(outputWitness, compiledCircuit.abi); this.log.debug(`Simulated ${circuitType}`, { @@ -194,7 +196,7 @@ export abstract class BBPrivateKernelProver implements PrivateKernelProver { const witnessMap = convertInputs(inputs, compiledCircuit.abi); const timer = new Timer(); - const outputWitness = await this.simulator.simulateCircuit(witnessMap, compiledCircuit); + const outputWitness = await this.simulationProvider.executeProtocolCircuit(witnessMap, compiledCircuit); const output = convertOutputs(outputWitness, compiledCircuit.abi); this.log.debug(`Generated witness for ${circuitType}`, { diff --git a/yarn-project/bb-prover/src/prover/bb_prover.ts b/yarn-project/bb-prover/src/prover/bb_prover.ts index 28e7b7e3636..c702d668aa2 100644 --- a/yarn-project/bb-prover/src/prover/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/bb_prover.ts @@ -69,7 +69,7 @@ import { convertSingleTxBlockRootRollupInputsToWitnessMap, convertSingleTxBlockRootRollupOutputsFromWitnessMap, } from '@aztec/noir-protocol-circuits-types/server'; -import { NativeACVMSimulator } from '@aztec/simulator'; +import { NativeACVMSimulator } from '@aztec/simulator/server'; import { Attributes, type TelemetryClient, trackSpan } from '@aztec/telemetry-client'; import { type WitnessMap } from '@noir-lang/types'; @@ -427,7 +427,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { const inputWitness = convertInput(input); const timer = new Timer(); - const outputWitness = await simulator.simulateCircuit(inputWitness, artifact); + const outputWitness = await simulator.executeProtocolCircuit(inputWitness, artifact); const output = convertOutput(outputWitness); const circuitName = mapProtocolArtifactNameToCircuitName(circuitType); diff --git a/yarn-project/bb-prover/src/test/test_avm.ts b/yarn-project/bb-prover/src/test/test_avm.ts index 7dd0954dfe6..b94488520cd 100644 --- a/yarn-project/bb-prover/src/test/test_avm.ts +++ b/yarn-project/bb-prover/src/test/test_avm.ts @@ -28,7 +28,7 @@ import { } from '@aztec/circuits.js'; import { computeVarArgsHash } from '@aztec/circuits.js/hash'; import { padArrayEnd } from '@aztec/foundation/collection'; -import { type PublicFunctionCallResult } from '@aztec/simulator'; +import { type PublicFunctionCallResult } from '@aztec/simulator/server'; // TODO: pub somewhere more usable - copied from abstract phase manager export function getPublicInputs(result: PublicFunctionCallResult): PublicCircuitPublicInputs { diff --git a/yarn-project/bb-prover/src/test/test_circuit_prover.ts b/yarn-project/bb-prover/src/test/test_circuit_prover.ts index 3cfbc0f5e74..756ef24ff9b 100644 --- a/yarn-project/bb-prover/src/test/test_circuit_prover.ts +++ b/yarn-project/bb-prover/src/test/test_circuit_prover.ts @@ -63,7 +63,7 @@ import { convertSimulatedSingleTxBlockRootRollupOutputsFromWitnessMap, } from '@aztec/noir-protocol-circuits-types/server'; import { ProtocolCircuitVks } from '@aztec/noir-protocol-circuits-types/vks'; -import { type SimulationProvider, WASMSimulatorWithBlobs, emitCircuitSimulationStats } from '@aztec/simulator'; +import { type SimulationProvider, WASMSimulatorWithBlobs, emitCircuitSimulationStats } from '@aztec/simulator/server'; import { type TelemetryClient, trackSpan } from '@aztec/telemetry-client'; import { type WitnessMap } from '@noir-lang/types'; @@ -324,7 +324,10 @@ export class TestCircuitProver implements ServerCircuitProver { // the blob operations with an oracle. Appears to be no way to provide nativeACVM with a foreign call hander. simulationProvider = this.wasmSimulator; } - const witness = await simulationProvider.simulateCircuit(witnessMap, SimulatedServerCircuitArtifacts[artifactName]); + const witness = await simulationProvider.executeProtocolCircuit( + witnessMap, + SimulatedServerCircuitArtifacts[artifactName], + ); const result = convertOutput(witness); diff --git a/yarn-project/bb-prover/src/wasm/bb_wasm_private_kernel_prover.ts b/yarn-project/bb-prover/src/wasm/bb_wasm_private_kernel_prover.ts index afcac61ea93..c5f8eb5aeeb 100644 --- a/yarn-project/bb-prover/src/wasm/bb_wasm_private_kernel_prover.ts +++ b/yarn-project/bb-prover/src/wasm/bb_wasm_private_kernel_prover.ts @@ -3,6 +3,7 @@ import { ClientIvcProof } from '@aztec/circuits.js'; import { createLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; import { type ArtifactProvider } from '@aztec/noir-protocol-circuits-types/types'; +import { type SimulationProvider } from '@aztec/simulator/client'; import { serializeWitness } from '@noir-lang/noirc_abi'; import { type WitnessMap } from '@noir-lang/types'; @@ -13,10 +14,11 @@ import { BBPrivateKernelProver } from '../prover/bb_private_kernel_prover.js'; export abstract class BBWASMPrivateKernelProver extends BBPrivateKernelProver { constructor( protected override artifactProvider: ArtifactProvider, + protected override simulationProvider: SimulationProvider, private threads: number = 1, protected override log = createLogger('bb-prover:wasm'), ) { - super(artifactProvider, log); + super(artifactProvider, simulationProvider, log); } public override async createClientIvcProof(acirs: Buffer[], witnessStack: WitnessMap[]): Promise { diff --git a/yarn-project/bb-prover/src/wasm/bundle.ts b/yarn-project/bb-prover/src/wasm/bundle.ts index ae448752d63..8bb327b7f45 100644 --- a/yarn-project/bb-prover/src/wasm/bundle.ts +++ b/yarn-project/bb-prover/src/wasm/bundle.ts @@ -1,10 +1,11 @@ import { createLogger } from '@aztec/foundation/log'; import { BundleArtifactProvider } from '@aztec/noir-protocol-circuits-types/client/bundle'; +import { type SimulationProvider } from '@aztec/simulator/client'; import { BBWASMPrivateKernelProver } from './bb_wasm_private_kernel_prover.js'; export class BBWASMBundlePrivateKernelProver extends BBWASMPrivateKernelProver { - constructor(threads = 1, log = createLogger('bb-prover:wasm:bundle')) { - super(new BundleArtifactProvider(), threads, log); + constructor(simulationProvider: SimulationProvider, threads = 1, log = createLogger('bb-prover:wasm:bundle')) { + super(new BundleArtifactProvider(), simulationProvider, threads, log); } } diff --git a/yarn-project/bb-prover/src/wasm/lazy.ts b/yarn-project/bb-prover/src/wasm/lazy.ts index 16fc1c04c90..625b90e2ca6 100644 --- a/yarn-project/bb-prover/src/wasm/lazy.ts +++ b/yarn-project/bb-prover/src/wasm/lazy.ts @@ -1,10 +1,11 @@ import { createLogger } from '@aztec/foundation/log'; import { LazyArtifactProvider } from '@aztec/noir-protocol-circuits-types/client/lazy'; +import { type SimulationProvider } from '@aztec/simulator/client'; import { BBWASMPrivateKernelProver } from './bb_wasm_private_kernel_prover.js'; export class BBWASMLazyPrivateKernelProver extends BBWASMPrivateKernelProver { - constructor(threads = 1, log = createLogger('bb-prover:wasm:lazy')) { - super(new LazyArtifactProvider(), threads, log); + constructor(simulationProvider: SimulationProvider, threads = 1, log = createLogger('bb-prover:wasm:lazy')) { + super(new LazyArtifactProvider(), simulationProvider, threads, log); } } diff --git a/yarn-project/end-to-end/src/e2e_block_building.test.ts b/yarn-project/end-to-end/src/e2e_block_building.test.ts index 148b090eab8..97e0e550f6f 100644 --- a/yarn-project/end-to-end/src/e2e_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_block_building.test.ts @@ -31,7 +31,12 @@ import { TestContract } from '@aztec/noir-contracts.js/Test'; import { TokenContract } from '@aztec/noir-contracts.js/Token'; import { type SequencerClient, SequencerState } from '@aztec/sequencer-client'; import { type TestSequencerClient } from '@aztec/sequencer-client/test'; -import { PublicProcessorFactory, type PublicTxResult, PublicTxSimulator, type WorldStateDB } from '@aztec/simulator'; +import { + PublicProcessorFactory, + type PublicTxResult, + PublicTxSimulator, + type WorldStateDB, +} from '@aztec/simulator/server'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; diff --git a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts index 03b54a2ff26..a56390821d8 100644 --- a/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts +++ b/yarn-project/end-to-end/src/e2e_crowdfunding_and_claim.test.ts @@ -355,7 +355,7 @@ describe('e2e_crowdfunding_and_claim', () => { donorWallets[1].setScopes([donorWallets[1].getAddress(), crowdfundingContract.address]); await expect(donorWallets[1].simulateTx(request, true, operatorWallet.getAddress())).rejects.toThrow( - 'Assertion failed', + 'Circuit execution failed: Users cannot set msg_sender in first call', ); }); diff --git a/yarn-project/prover-client/src/mocks/fixtures.ts b/yarn-project/prover-client/src/mocks/fixtures.ts index a59340bd7d2..69c5084f65f 100644 --- a/yarn-project/prover-client/src/mocks/fixtures.ts +++ b/yarn-project/prover-client/src/mocks/fixtures.ts @@ -13,7 +13,7 @@ import { padArrayEnd } from '@aztec/foundation/collection'; import { randomBytes } from '@aztec/foundation/crypto'; import { type Logger } from '@aztec/foundation/log'; import { fileURLToPath } from '@aztec/foundation/url'; -import { NativeACVMSimulator, type SimulationProvider, WASMSimulatorWithBlobs } from '@aztec/simulator'; +import { NativeACVMSimulator, type SimulationProvider, WASMSimulatorWithBlobs } from '@aztec/simulator/server'; import { promises as fs } from 'fs'; import path from 'path'; diff --git a/yarn-project/prover-client/src/mocks/test_context.ts b/yarn-project/prover-client/src/mocks/test_context.ts index 41847b26e66..a00642bb55f 100644 --- a/yarn-project/prover-client/src/mocks/test_context.ts +++ b/yarn-project/prover-client/src/mocks/test_context.ts @@ -26,7 +26,7 @@ import { type SimulationProvider, WASMSimulatorWithBlobs, type WorldStateDB, -} from '@aztec/simulator'; +} from '@aztec/simulator/server'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type MerkleTreeAdminDatabase } from '@aztec/world-state'; import { NativeWorldStateService } from '@aztec/world-state/native'; diff --git a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts index ed16c5bb7be..9b7a68ab4a8 100644 --- a/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts +++ b/yarn-project/prover-client/src/orchestrator/block-building-helpers.ts @@ -52,7 +52,7 @@ import { type Tuple, assertLength, serializeToBuffer, toFriendlyJSON } from '@az import { computeUnbalancedMerkleRoot } from '@aztec/foundation/trees'; import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vks'; import { protocolContractTreeRoot } from '@aztec/protocol-contracts'; -import { computeFeePayerBalanceLeafSlot } from '@aztec/simulator'; +import { computeFeePayerBalanceLeafSlot } from '@aztec/simulator/server'; import { type MerkleTreeReadOperations } from '@aztec/world-state'; import { inspect } from 'util'; diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts index c5c88dd8ed0..7d09489a01f 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts @@ -2,7 +2,7 @@ import { TestCircuitProver } from '@aztec/bb-prover'; import { type ServerCircuitProver } from '@aztec/circuit-types'; import { timesAsync } from '@aztec/foundation/collection'; import { createLogger } from '@aztec/foundation/log'; -import { WASMSimulatorWithBlobs } from '@aztec/simulator'; +import { WASMSimulatorWithBlobs } from '@aztec/simulator/server'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { jest } from '@jest/globals'; diff --git a/yarn-project/prover-client/src/prover-client/prover-client.ts b/yarn-project/prover-client/src/prover-client/prover-client.ts index a7d7f645949..f179ba758d0 100644 --- a/yarn-project/prover-client/src/prover-client/prover-client.ts +++ b/yarn-project/prover-client/src/prover-client/prover-client.ts @@ -12,7 +12,7 @@ import { import { Fr } from '@aztec/circuits.js'; import { times } from '@aztec/foundation/collection'; import { createLogger } from '@aztec/foundation/log'; -import { NativeACVMSimulator } from '@aztec/simulator'; +import { NativeACVMSimulator } from '@aztec/simulator/server'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { type ProverClientConfig } from '../config.js'; diff --git a/yarn-project/prover-node/src/job/epoch-proving-job.test.ts b/yarn-project/prover-node/src/job/epoch-proving-job.test.ts index 4576c377f2b..80240ae2b5a 100644 --- a/yarn-project/prover-node/src/job/epoch-proving-job.test.ts +++ b/yarn-project/prover-node/src/job/epoch-proving-job.test.ts @@ -13,7 +13,7 @@ import { RootRollupPublicInputs } from '@aztec/circuits.js/rollup'; import { times } from '@aztec/foundation/collection'; import { sleep } from '@aztec/foundation/sleep'; import { type L1Publisher } from '@aztec/sequencer-client'; -import { type PublicProcessor, type PublicProcessorFactory } from '@aztec/simulator'; +import { type PublicProcessor, type PublicProcessorFactory } from '@aztec/simulator/server'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type MockProxy, mock } from 'jest-mock-extended'; diff --git a/yarn-project/prover-node/src/job/epoch-proving-job.ts b/yarn-project/prover-node/src/job/epoch-proving-job.ts index d22787f85c0..d060ebac229 100644 --- a/yarn-project/prover-node/src/job/epoch-proving-job.ts +++ b/yarn-project/prover-node/src/job/epoch-proving-job.ts @@ -14,7 +14,7 @@ import { createLogger } from '@aztec/foundation/log'; import { promiseWithResolvers } from '@aztec/foundation/promise'; import { Timer } from '@aztec/foundation/timer'; import { type L1Publisher } from '@aztec/sequencer-client'; -import { type PublicProcessor, type PublicProcessorFactory } from '@aztec/simulator'; +import { type PublicProcessor, type PublicProcessorFactory } from '@aztec/simulator/server'; import { Attributes, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client'; import * as crypto from 'node:crypto'; diff --git a/yarn-project/prover-node/src/prover-node.test.ts b/yarn-project/prover-node/src/prover-node.test.ts index d784fbea92d..0d555b8efe7 100644 --- a/yarn-project/prover-node/src/prover-node.test.ts +++ b/yarn-project/prover-node/src/prover-node.test.ts @@ -25,7 +25,7 @@ import { openTmpStore } from '@aztec/kv-store/lmdb'; import { type BootstrapNode, InMemoryTxPool, MemoryEpochProofQuotePool, P2PClient } from '@aztec/p2p'; import { createBootstrapNode, createTestLibP2PService } from '@aztec/p2p/mocks'; import { type L1Publisher } from '@aztec/sequencer-client'; -import { type PublicProcessorFactory } from '@aztec/simulator'; +import { type PublicProcessorFactory } from '@aztec/simulator/server'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { jest } from '@jest/globals'; diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index 3fc7e9a07ee..a5692dead4b 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -27,7 +27,7 @@ import { DateProvider } from '@aztec/foundation/timer'; import { type Maybe } from '@aztec/foundation/types'; import { type P2P } from '@aztec/p2p'; import { type L1Publisher } from '@aztec/sequencer-client'; -import { PublicProcessorFactory } from '@aztec/simulator'; +import { PublicProcessorFactory } from '@aztec/simulator/server'; import { Attributes, type TelemetryClient, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client'; import { type BondManager } from './bond/bond-manager.js'; diff --git a/yarn-project/pxe/src/database/note_dao.ts b/yarn-project/pxe/src/database/note_dao.ts index b4cb311fd46..af8357a7e33 100644 --- a/yarn-project/pxe/src/database/note_dao.ts +++ b/yarn-project/pxe/src/database/note_dao.ts @@ -3,7 +3,7 @@ import { AztecAddress, Fr, Point, type PublicKey } from '@aztec/circuits.js'; import { NoteSelector } from '@aztec/foundation/abi'; import { toBigIntBE } from '@aztec/foundation/bigint-buffer'; import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize'; -import { type NoteData } from '@aztec/simulator/acvm'; +import { type NoteData } from '@aztec/simulator/client'; import { type NoteInfo } from '../note_decryption_utils/index.js'; diff --git a/yarn-project/pxe/src/pxe_service/error_enriching.ts b/yarn-project/pxe/src/pxe_service/error_enriching.ts index f8ff9663206..928c4b14ca4 100644 --- a/yarn-project/pxe/src/pxe_service/error_enriching.ts +++ b/yarn-project/pxe/src/pxe_service/error_enriching.ts @@ -4,7 +4,7 @@ import { FunctionSelector } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; import { type Logger } from '@aztec/foundation/log'; -import { resolveAssertionMessageFromRevertData, resolveOpcodeLocations } from '@aztec/simulator/errors'; +import { resolveAssertionMessageFromRevertData, resolveOpcodeLocations } from '@aztec/simulator/client'; import { type ContractDataOracle, type PxeDatabase } from '../index.js'; diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index b6b4eba6cd6..8b2e8348b78 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -65,7 +65,7 @@ import { type KeyStore } from '@aztec/key-store'; import { type L2TipsStore } from '@aztec/kv-store/stores'; import { ProtocolContractAddress, protocolContractNames } from '@aztec/protocol-contracts'; import { getCanonicalProtocolContract } from '@aztec/protocol-contracts/bundle'; -import { type AcirSimulator } from '@aztec/simulator/client'; +import { type AcirSimulator, type SimulationProvider } from '@aztec/simulator/client'; import { inspect } from 'util'; @@ -97,13 +97,14 @@ export class PXEService implements PXE { private db: PxeDatabase, tipsStore: L2TipsStore, private proofCreator: PrivateKernelProver, + private simulationProvider: SimulationProvider, config: PXEServiceConfig, logSuffix?: string, ) { this.log = createLogger(logSuffix ? `pxe:service:${logSuffix}` : `pxe:service`); this.synchronizer = new Synchronizer(node, db, tipsStore, config, logSuffix); this.contractDataOracle = new ContractDataOracle(db); - this.simulator = getAcirSimulator(db, node, keyStore, this.contractDataOracle); + this.simulator = getAcirSimulator(db, node, keyStore, this.simulationProvider, this.contractDataOracle); this.packageVersion = getPackageInfo().version; this.proverEnabled = !!config.proverEnabled; } diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts index b442f4a2d40..3bfeb2973b6 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts @@ -1,11 +1,19 @@ import { BBWASMBundlePrivateKernelProver } from '@aztec/bb-prover/wasm/bundle'; -import { type AztecNode, type PXE, TxEffect, mockTx, randomInBlock } from '@aztec/circuit-types'; +import { + type AztecNode, + type PXE, + type PrivateKernelProver, + TxEffect, + mockTx, + randomInBlock, +} from '@aztec/circuit-types'; import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants'; import { type L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses'; import { EthAddress } from '@aztec/foundation/eth-address'; import { KeyStore } from '@aztec/key-store'; import { openTmpStore } from '@aztec/kv-store/lmdb'; import { L2TipsStore } from '@aztec/kv-store/stores'; +import { type SimulationProvider, WASMSimulator } from '@aztec/simulator/client'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -20,6 +28,8 @@ async function createPXEService(): Promise { const keyStore = new KeyStore(kvStore); const node = mock(); const db = await KVPxeDatabase.create(kvStore); + const simulationProvider = new WASMSimulator(); + const kernelProver = new BBWASMBundlePrivateKernelProver(simulationProvider); const tips = new L2TipsStore(kvStore, 'pxe'); const config: PXEServiceConfig = { l2StartingBlock: INITIAL_L2_BLOCK_NUM, @@ -48,7 +58,7 @@ async function createPXEService(): Promise { }; node.getL1ContractAddresses.mockResolvedValue(mockedContracts); - return Promise.resolve(new PXEService(keyStore, node, db, tips, new BBWASMBundlePrivateKernelProver(), config)); + return Promise.resolve(new PXEService(keyStore, node, db, tips, kernelProver, simulationProvider, config)); } pxeTestSuite('PXEService', createPXEService); @@ -57,6 +67,8 @@ describe('PXEService', () => { let keyStore: KeyStore; let node: MockProxy; let db: PxeDatabase; + let simulationProvider: SimulationProvider; + let kernelProver: PrivateKernelProver; let config: PXEServiceConfig; let tips: L2TipsStore; @@ -66,6 +78,9 @@ describe('PXEService', () => { node = mock(); tips = new L2TipsStore(kvStore, 'pxe'); db = await KVPxeDatabase.create(kvStore); + simulationProvider = new WASMSimulator(); + kernelProver = new BBWASMBundlePrivateKernelProver(simulationProvider); + config = { l2StartingBlock: INITIAL_L2_BLOCK_NUM, proverEnabled: false, @@ -81,7 +96,7 @@ describe('PXEService', () => { node.getTxEffect.mockResolvedValue(randomInBlock(settledTx)); - const pxe = new PXEService(keyStore, node, db, tips, new BBWASMBundlePrivateKernelProver(), config); + const pxe = new PXEService(keyStore, node, db, tips, kernelProver, simulationProvider, config); await expect(pxe.sendTx(duplicateTx)).rejects.toThrow(/A settled tx with equal hash/); }); }); diff --git a/yarn-project/pxe/src/simulator/index.ts b/yarn-project/pxe/src/simulator/index.ts index 8f41547a15e..e1ee9ab457b 100644 --- a/yarn-project/pxe/src/simulator/index.ts +++ b/yarn-project/pxe/src/simulator/index.ts @@ -1,6 +1,6 @@ import { type AztecNode } from '@aztec/circuit-types'; import { type KeyStore } from '@aztec/key-store'; -import { AcirSimulator } from '@aztec/simulator/client'; +import { AcirSimulator, type SimulationProvider } from '@aztec/simulator/client'; import { ContractDataOracle } from '../contract_data_oracle/index.js'; import { type PxeDatabase } from '../database/pxe_database.js'; @@ -13,6 +13,7 @@ export function getAcirSimulator( db: PxeDatabase, aztecNode: AztecNode, keyStore: KeyStore, + simulationProvider: SimulationProvider, contractDataOracle?: ContractDataOracle, ) { const simulatorOracle = new SimulatorOracle( @@ -20,6 +21,7 @@ export function getAcirSimulator( db, keyStore, aztecNode, + simulationProvider, ); - return new AcirSimulator(simulatorOracle, aztecNode); + return new AcirSimulator(simulatorOracle, aztecNode, simulationProvider); } diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index 019ca15c7fc..e7331879869 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -30,8 +30,12 @@ import { type FunctionArtifact, getFunctionArtifact } from '@aztec/foundation/ab import { poseidon2Hash } from '@aztec/foundation/crypto'; import { createLogger } from '@aztec/foundation/log'; import { type KeyStore } from '@aztec/key-store'; -import { MessageLoadOracleInputs } from '@aztec/simulator/acvm'; -import { type AcirSimulator, type DBOracle } from '@aztec/simulator/client'; +import { + type AcirSimulator, + type DBOracle, + MessageLoadOracleInputs, + type SimulationProvider, +} from '@aztec/simulator/client'; import { type ContractDataOracle } from '../contract_data_oracle/index.js'; import { type PxeDatabase } from '../database/index.js'; @@ -49,6 +53,7 @@ export class SimulatorOracle implements DBOracle { private db: PxeDatabase, private keyStore: KeyStore, private aztecNode: AztecNode, + private simulationProvider: SimulationProvider, private log = createLogger('pxe:simulator_oracle'), ) {} @@ -605,7 +610,8 @@ export class SimulatorOracle implements DBOracle { // I don't like this at all, but we need a simulator to run `computeNoteHashAndOptionallyANullifier`. This generates // a chicken-and-egg problem due to this oracle requiring a simulator, which in turn requires this oracle. Furthermore, since jest doesn't allow // mocking ESM exports, we have to pollute the method even more by providing a simulator parameter so tests can inject a fake one. - simulator ?? getAcirSimulator(this.db, this.aztecNode, this.keyStore, this.contractDataOracle), + simulator ?? + getAcirSimulator(this.db, this.aztecNode, this.keyStore, this.simulationProvider, this.contractDataOracle), this.db, notePayload ? recipient.toAddressPoint() : undefined, payload!, diff --git a/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts b/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts index 11e9a6aaaf4..6d7037a7de8 100644 --- a/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts +++ b/yarn-project/pxe/src/simulator_oracle/simulator_oracle.test.ts @@ -26,7 +26,7 @@ import { import { pedersenHash, poseidon2Hash } from '@aztec/foundation/crypto'; import { KeyStore } from '@aztec/key-store'; import { openTmpStore } from '@aztec/kv-store/lmdb'; -import { type AcirSimulator } from '@aztec/simulator/client'; +import { type AcirSimulator, type SimulationProvider, WASMSimulator } from '@aztec/simulator/client'; import { jest } from '@jest/globals'; import { type MockProxy, mock } from 'jest-mock-extended'; @@ -118,6 +118,7 @@ describe('Simulator oracle', () => { let contractDataOracle: ContractDataOracle; let simulatorOracle: SimulatorOracle; let keyStore: KeyStore; + let simulationProvider: SimulationProvider; let recipient: CompleteAddress; let contractAddress: AztecAddress; @@ -129,7 +130,8 @@ describe('Simulator oracle', () => { contractDataOracle = new ContractDataOracle(database); jest.spyOn(contractDataOracle, 'getDebugContractName').mockImplementation(() => Promise.resolve('TestContract')); keyStore = new KeyStore(db); - simulatorOracle = new SimulatorOracle(contractDataOracle, database, keyStore, aztecNode); + simulationProvider = new WASMSimulator(); + simulatorOracle = new SimulatorOracle(contractDataOracle, database, keyStore, aztecNode, simulationProvider); // Set up contract address contractAddress = AztecAddress.random(); // Set up recipient account diff --git a/yarn-project/pxe/src/utils/create_pxe_service.ts b/yarn-project/pxe/src/utils/create_pxe_service.ts index 1e288dd3fd9..4a093f17d56 100644 --- a/yarn-project/pxe/src/utils/create_pxe_service.ts +++ b/yarn-project/pxe/src/utils/create_pxe_service.ts @@ -6,6 +6,7 @@ import { createLogger } from '@aztec/foundation/log'; import { KeyStore } from '@aztec/key-store'; import { createStore } from '@aztec/kv-store/lmdb'; import { L2TipsStore } from '@aztec/kv-store/stores'; +import { type SimulationProvider, WASMSimulator } from '@aztec/simulator/client'; import { type PXEServiceConfig } from '../config/index.js'; import { KVPxeDatabase } from '../database/kv_pxe_database.js'; @@ -45,20 +46,20 @@ export async function createPXEService( const db = await KVPxeDatabase.create(store); const tips = new L2TipsStore(store, 'pxe'); - - const prover = proofCreator ?? (await createProver(config, logSuffix)); - const pxe = new PXEService(keyStore, aztecNode, db, tips, prover, config, logSuffix); + const simulationProvider = new WASMSimulator(); + const prover = proofCreator ?? (await createProver(config, simulationProvider, logSuffix)); + const pxe = new PXEService(keyStore, aztecNode, db, tips, prover, simulationProvider, config, logSuffix); await pxe.init(); return pxe; } -function createProver(config: PXEServiceConfig, logSuffix?: string) { +function createProver(config: PXEServiceConfig, simulationProvider: SimulationProvider, logSuffix?: string) { if (!config.bbBinaryPath || !config.bbWorkingDirectory) { - return new BBWASMBundlePrivateKernelProver(16); + return new BBWASMBundlePrivateKernelProver(simulationProvider, 16); } else { const bbConfig = config as Required> & PXEServiceConfig; const log = createLogger('pxe:bb-native-prover' + (logSuffix ? `:${logSuffix}` : '')); - return BBNativePrivateKernelProver.new({ bbSkipCleanup: false, ...bbConfig }, log); + return BBNativePrivateKernelProver.new({ bbSkipCleanup: false, ...bbConfig }, simulationProvider, log); } } diff --git a/yarn-project/sequencer-client/src/client/sequencer-client.ts b/yarn-project/sequencer-client/src/client/sequencer-client.ts index 10119d98057..7bc7a5ad786 100644 --- a/yarn-project/sequencer-client/src/client/sequencer-client.ts +++ b/yarn-project/sequencer-client/src/client/sequencer-client.ts @@ -6,7 +6,7 @@ import { type EthAddress } from '@aztec/foundation/eth-address'; import { type DateProvider } from '@aztec/foundation/timer'; import { type P2P } from '@aztec/p2p'; import { LightweightBlockBuilderFactory } from '@aztec/prover-client/block-builder'; -import { PublicProcessorFactory } from '@aztec/simulator'; +import { PublicProcessorFactory } from '@aztec/simulator/server'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { type ValidatorClient } from '@aztec/validator-client'; diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 7a9c96e898e..76d19334f51 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -38,7 +38,7 @@ import { type Logger, createLogger } from '@aztec/foundation/log'; import { TestDateProvider } from '@aztec/foundation/timer'; import { type P2P, P2PClientState } from '@aztec/p2p'; import { type BlockBuilderFactory } from '@aztec/prover-client/block-builder'; -import { type PublicProcessor, type PublicProcessorFactory } from '@aztec/simulator'; +import { type PublicProcessor, type PublicProcessorFactory } from '@aztec/simulator/server'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { type ValidatorClient } from '@aztec/validator-client'; diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 8991a6e3f01..68f634ea878 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -32,7 +32,7 @@ import { pickFromSchema } from '@aztec/foundation/schemas'; import { type DateProvider, Timer, elapsed } from '@aztec/foundation/timer'; import { type P2P } from '@aztec/p2p'; import { type BlockBuilderFactory } from '@aztec/prover-client/block-builder'; -import { type PublicProcessorFactory } from '@aztec/simulator'; +import { type PublicProcessorFactory } from '@aztec/simulator/server'; import { Attributes, type TelemetryClient, type Tracer, trackSpan } from '@aztec/telemetry-client'; import { type ValidatorClient } from '@aztec/validator-client'; diff --git a/yarn-project/sequencer-client/src/test/index.ts b/yarn-project/sequencer-client/src/test/index.ts index a7f466b485b..7a1304461ae 100644 --- a/yarn-project/sequencer-client/src/test/index.ts +++ b/yarn-project/sequencer-client/src/test/index.ts @@ -1,4 +1,4 @@ -import { type PublicProcessorFactory } from '@aztec/simulator'; +import { type PublicProcessorFactory } from '@aztec/simulator/server'; import { SequencerClient } from '../client/sequencer-client.js'; import { type L1Publisher } from '../publisher/l1-publisher.js'; diff --git a/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts b/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts index b5ee24df54c..4f5bc03692b 100644 --- a/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts +++ b/yarn-project/sequencer-client/src/tx_validator/gas_validator.ts @@ -1,7 +1,7 @@ import { type Tx, TxExecutionPhase, type TxValidationResult, type TxValidator } from '@aztec/circuit-types'; import { type AztecAddress, type Fr, FunctionSelector, type GasFees } from '@aztec/circuits.js'; import { createLogger } from '@aztec/foundation/log'; -import { computeFeePayerBalanceStorageSlot, getExecutionRequestsByPhase } from '@aztec/simulator'; +import { computeFeePayerBalanceStorageSlot, getExecutionRequestsByPhase } from '@aztec/simulator/server'; /** Provides a view into public contract state */ export interface PublicStateSource { diff --git a/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts b/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts index 2d885f68ce6..38112a20ccf 100644 --- a/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts +++ b/yarn-project/sequencer-client/src/tx_validator/phases_validator.ts @@ -8,7 +8,7 @@ import { } from '@aztec/circuit-types'; import { type ContractDataSource } from '@aztec/circuits.js'; import { createLogger } from '@aztec/foundation/log'; -import { ContractsDataSourcePublicDB, getExecutionRequestsByPhase } from '@aztec/simulator'; +import { ContractsDataSourcePublicDB, getExecutionRequestsByPhase } from '@aztec/simulator/server'; export class PhasesTxValidator implements TxValidator { #log = createLogger('sequencer:tx_validator:tx_phases'); diff --git a/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts b/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts index 6e752d9971f..0c0e48f6c9c 100644 --- a/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts +++ b/yarn-project/sequencer-client/src/tx_validator/tx_validator_factory.ts @@ -16,7 +16,7 @@ import { TxProofValidator, } from '@aztec/p2p'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; -import { readPublicState } from '@aztec/simulator'; +import { readPublicState } from '@aztec/simulator/server'; import { ArchiveCache } from './archive_cache.js'; import { GasTxValidator, type PublicStateSource } from './gas_validator.js'; diff --git a/yarn-project/simulator/package.json b/yarn-project/simulator/package.json index a0bde2ce857..c3a54db4863 100644 --- a/yarn-project/simulator/package.json +++ b/yarn-project/simulator/package.json @@ -3,10 +3,9 @@ "version": "0.1.0", "type": "module", "exports": { - ".": "./dest/index.js", + "./common": "./dest/common.js", + "./server": "./dest/server.js", "./client": "./dest/client/index.js", - "./acvm": "./dest/acvm/index.js", - "./errors": "./dest/common/errors.js", "./public/fixtures": "./dest/public/fixtures/index.js" }, "typedocOptions": { diff --git a/yarn-project/simulator/src/acvm/acvm.ts b/yarn-project/simulator/src/acvm/acvm.ts index 7e0c18395cd..66298190bed 100644 --- a/yarn-project/simulator/src/acvm/acvm.ts +++ b/yarn-project/simulator/src/acvm/acvm.ts @@ -16,7 +16,7 @@ import { type ORACLE_NAMES } from './oracle/index.js'; /** * The callback interface for the ACIR. */ -type ACIRCallback = Record< +export type ACIRCallback = Record< ORACLE_NAMES, ( ...args: ForeignCallInput[] diff --git a/yarn-project/simulator/src/acvm/index.ts b/yarn-project/simulator/src/acvm/index.ts index 23067f6094b..b3c6a274ff2 100644 --- a/yarn-project/simulator/src/acvm/index.ts +++ b/yarn-project/simulator/src/acvm/index.ts @@ -1,4 +1,4 @@ -export * from './acvm.js'; +export { extractCallStack, type ACIRCallback, type ACIRExecutionResult } from './acvm.js'; export * from './acvm_types.js'; export * from './deserialize.js'; export * from './oracle/index.js'; diff --git a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts index cd529fdd3ac..d228db9776f 100644 --- a/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts +++ b/yarn-project/simulator/src/acvm/oracle/typed_oracle.ts @@ -5,7 +5,6 @@ import { type NoteStatus, type NullifierMembershipWitness, type PublicDataWitness, - type SiblingPath, type UnencryptedL2Log, } from '@aztec/circuit-types'; import { @@ -19,6 +18,8 @@ import { type FunctionSelector, type NoteSelector } from '@aztec/foundation/abi' import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; +import { type MessageLoadOracleInputs } from '../../common/message_load_oracle_inputs.js'; + /** * Information about a note needed during execution. */ @@ -39,19 +40,6 @@ export interface NoteData { index?: bigint; } -export class MessageLoadOracleInputs { - constructor( - /** The index of the message commitment in the merkle tree. */ - public index: bigint, - /** The path in the merkle tree to the message. */ - public siblingPath: SiblingPath, - ) {} - - toFields(): Fr[] { - return [new Fr(this.index), ...this.siblingPath.toFields()]; - } -} - class OracleMethodNotAvailableError extends Error { constructor(methodName: string) { super(`Oracle method ${methodName} is not available.`); diff --git a/yarn-project/simulator/src/avm/fixtures/index.ts b/yarn-project/simulator/src/avm/fixtures/index.ts index 494a500f412..9ad3778127a 100644 --- a/yarn-project/simulator/src/avm/fixtures/index.ts +++ b/yarn-project/simulator/src/avm/fixtures/index.ts @@ -10,8 +10,9 @@ import { strict as assert } from 'assert'; import { mock } from 'jest-mock-extended'; import merge from 'lodash.merge'; -import { type WorldStateDB, resolveAssertionMessageFromRevertData, traverseCauseChain } from '../../index.js'; +import { resolveAssertionMessageFromRevertData, traverseCauseChain } from '../../common.js'; import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; +import { type WorldStateDB } from '../../server.js'; import { AvmContext } from '../avm_context.js'; import { AvmExecutionEnvironment } from '../avm_execution_environment.js'; import { AvmMachineState } from '../avm_machine_state.js'; diff --git a/yarn-project/simulator/src/avm/journal/nullifiers.test.ts b/yarn-project/simulator/src/avm/journal/nullifiers.test.ts index 02fc2a04495..a2975fd7db4 100644 --- a/yarn-project/simulator/src/avm/journal/nullifiers.test.ts +++ b/yarn-project/simulator/src/avm/journal/nullifiers.test.ts @@ -2,7 +2,7 @@ import { Fr } from '@aztec/foundation/fields'; import { type MockProxy, mock } from 'jest-mock-extended'; -import { type CommitmentsDB } from '../../index.js'; +import { type CommitmentsDB } from '../../server.js'; import { NullifierManager } from './nullifiers.js'; describe('avm nullifier caching', () => { diff --git a/yarn-project/simulator/src/avm/journal/nullifiers.ts b/yarn-project/simulator/src/avm/journal/nullifiers.ts index 8e482108990..a3b60c8aaf6 100644 --- a/yarn-project/simulator/src/avm/journal/nullifiers.ts +++ b/yarn-project/simulator/src/avm/journal/nullifiers.ts @@ -1,6 +1,6 @@ import { Fr } from '@aztec/foundation/fields'; -import type { CommitmentsDB } from '../../index.js'; +import type { CommitmentsDB } from '../../server.js'; /** * A class to manage new nullifier staging and existence checks during a contract call's AVM simulation. diff --git a/yarn-project/simulator/src/avm/journal/public_storage.test.ts b/yarn-project/simulator/src/avm/journal/public_storage.test.ts index 6db7f7e7bbf..65fe4587172 100644 --- a/yarn-project/simulator/src/avm/journal/public_storage.test.ts +++ b/yarn-project/simulator/src/avm/journal/public_storage.test.ts @@ -3,7 +3,7 @@ import { Fr } from '@aztec/foundation/fields'; import { type MockProxy, mock } from 'jest-mock-extended'; -import { type PublicStateDB } from '../../index.js'; +import { type PublicStateDB } from '../../server.js'; import { PublicStorage } from './public_storage.js'; describe('avm public storage', () => { diff --git a/yarn-project/simulator/src/avm/journal/public_storage.ts b/yarn-project/simulator/src/avm/journal/public_storage.ts index 64abe824ddb..f0b260dbe0c 100644 --- a/yarn-project/simulator/src/avm/journal/public_storage.ts +++ b/yarn-project/simulator/src/avm/journal/public_storage.ts @@ -1,7 +1,7 @@ import { type AztecAddress } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; -import type { PublicStateDB } from '../../index.js'; +import type { PublicStateDB } from '../../server.js'; type PublicStorageReadResult = { value: Fr; diff --git a/yarn-project/simulator/src/client/client_execution_context.ts b/yarn-project/simulator/src/client/client_execution_context.ts index c4ac6fafc9b..3c2c761f356 100644 --- a/yarn-project/simulator/src/client/client_execution_context.ts +++ b/yarn-project/simulator/src/client/client_execution_context.ts @@ -27,6 +27,7 @@ import { createLogger } from '@aztec/foundation/log'; import { type NoteData, toACVMWitness } from '../acvm/index.js'; import { type PackedValuesCache } from '../common/packed_values_cache.js'; +import { type SimulationProvider } from '../server.js'; import { type DBOracle } from './db_oracle.js'; import { type ExecutionNoteCache } from './execution_note_cache.js'; import { pickNotes } from './pick_notes.js'; @@ -73,6 +74,7 @@ export class ClientExecutionContext extends ViewDataOracle { private readonly noteCache: ExecutionNoteCache, db: DBOracle, private node: AztecNode, + private provider: SimulationProvider, protected sideEffectCounter: number = 0, log = createLogger('simulator:client_execution_context'), scopes?: AztecAddress[], @@ -373,12 +375,14 @@ export class ClientExecutionContext extends ViewDataOracle { this.noteCache, this.db, this.node, + this.provider, sideEffectCounter, this.log, this.scopes, ); const childExecutionResult = await executePrivateFunction( + this.provider, context, targetArtifact, targetContractAddress, diff --git a/yarn-project/simulator/src/client/index.ts b/yarn-project/simulator/src/client/index.ts index 3bff1cb6ec7..608da797f92 100644 --- a/yarn-project/simulator/src/client/index.ts +++ b/yarn-project/simulator/src/client/index.ts @@ -1,6 +1,14 @@ -export * from './simulator.js'; -export * from './db_oracle.js'; +export { AcirSimulator } from './simulator.js'; +export { DBOracle, ContractClassNotFoundError, ContractNotFoundError } from './db_oracle.js'; export * from './pick_notes.js'; -export * from './execution_note_cache.js'; +export { ExecutionNoteCache } from './execution_note_cache.js'; export { extractPrivateCircuitPublicInputs } from './private_execution.js'; +export { witnessMapToFields } from '../acvm/deserialize.js'; +export { toACVMWitness } from '../acvm/serialize.js'; +export { extractCallStack } from '../acvm/acvm.js'; export { WASMSimulator } from '../providers/acvm_wasm.js'; +export { NoteData, TypedOracle } from '../acvm/oracle/typed_oracle.js'; +export { Oracle } from '../acvm/oracle/oracle.js'; +export { type SimulationProvider } from '../common/simulation_provider.js'; +export { MessageLoadOracleInputs } from '../common/message_load_oracle_inputs.js'; +export { resolveAssertionMessageFromRevertData, resolveOpcodeLocations } from '../common/errors.js'; diff --git a/yarn-project/simulator/src/client/private_execution.test.ts b/yarn-project/simulator/src/client/private_execution.test.ts index cc38e3ad1fa..57d751c6151 100644 --- a/yarn-project/simulator/src/client/private_execution.test.ts +++ b/yarn-project/simulator/src/client/private_execution.test.ts @@ -66,7 +66,8 @@ import { jest } from '@jest/globals'; import { type MockProxy, mock } from 'jest-mock-extended'; import { toFunctionSelector } from 'viem'; -import { MessageLoadOracleInputs } from '../acvm/index.js'; +import { MessageLoadOracleInputs } from '../common/message_load_oracle_inputs.js'; +import { WASMSimulator } from '../providers/acvm_wasm.js'; import { buildL1ToL2Message } from '../test/utils.js'; import { type DBOracle } from './db_oracle.js'; import { AcirSimulator } from './simulator.js'; @@ -74,9 +75,10 @@ import { AcirSimulator } from './simulator.js'; jest.setTimeout(60_000); describe('Private Execution test suite', () => { + const simulationProvider = new WASMSimulator(); + let oracle: MockProxy; let node: MockProxy; - let acirSimulator: AcirSimulator; let header = BlockHeader.empty(); @@ -245,7 +247,7 @@ describe('Private Execution test suite', () => { }, ); - acirSimulator = new AcirSimulator(oracle, node); + acirSimulator = new AcirSimulator(oracle, node, simulationProvider); }); describe('no constructor', () => { diff --git a/yarn-project/simulator/src/client/private_execution.ts b/yarn-project/simulator/src/client/private_execution.ts index 199d395696b..2e7a6cbef7d 100644 --- a/yarn-project/simulator/src/client/private_execution.ts +++ b/yarn-project/simulator/src/client/private_execution.ts @@ -12,14 +12,16 @@ import { createLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; import { fromACVMField, witnessMapToFields } from '../acvm/deserialize.js'; -import { type ACVMWitness, Oracle, acvm, extractCallStack } from '../acvm/index.js'; +import { type ACVMWitness, Oracle, extractCallStack } from '../acvm/index.js'; import { ExecutionError, resolveAssertionMessageFromError } from '../common/errors.js'; +import { type SimulationProvider } from '../server.js'; import { type ClientExecutionContext } from './client_execution_context.js'; /** * Execute a private function and return the execution result. */ export async function executePrivateFunction( + simulator: SimulationProvider, context: ClientExecutionContext, artifact: FunctionArtifact, contractAddress: AztecAddress, @@ -32,18 +34,20 @@ export async function executePrivateFunction( const initialWitness = context.getInitialWitness(artifact); const acvmCallback = new Oracle(context); const timer = new Timer(); - const acirExecutionResult = await acvm(acir, initialWitness, acvmCallback).catch((err: Error) => { - err.message = resolveAssertionMessageFromError(err, artifact); - throw new ExecutionError( - err.message, - { - contractAddress, - functionSelector, - }, - extractCallStack(err, artifact.debug), - { cause: err }, - ); - }); + const acirExecutionResult = await simulator + .executeUserCircuit(acir, initialWitness, acvmCallback) + .catch((err: Error) => { + err.message = resolveAssertionMessageFromError(err, artifact); + throw new ExecutionError( + err.message, + { + contractAddress, + functionSelector, + }, + extractCallStack(err, artifact.debug), + { cause: err }, + ); + }); const duration = timer.ms(); const partialWitness = acirExecutionResult.partialWitness; const publicInputs = extractPrivateCircuitPublicInputs(artifact, partialWitness); diff --git a/yarn-project/simulator/src/client/simulator.test.ts b/yarn-project/simulator/src/client/simulator.test.ts index bf67b300f06..2e243f400ac 100644 --- a/yarn-project/simulator/src/client/simulator.test.ts +++ b/yarn-project/simulator/src/client/simulator.test.ts @@ -7,10 +7,13 @@ import { TokenBlacklistContractArtifact } from '@aztec/noir-contracts.js/TokenBl import { type MockProxy, mock } from 'jest-mock-extended'; +import { WASMSimulator } from '../providers/acvm_wasm.js'; import { type DBOracle } from './db_oracle.js'; import { AcirSimulator } from './simulator.js'; describe('Simulator', () => { + const simulationProvider = new WASMSimulator(); + let oracle: MockProxy; let node: MockProxy; @@ -40,7 +43,7 @@ describe('Simulator', () => { ); oracle.getCompleteAddress.mockResolvedValue(ownerCompleteAddress); - simulator = new AcirSimulator(oracle, node); + simulator = new AcirSimulator(oracle, node, simulationProvider); }); describe('computeNoteHashAndOptionallyANullifier', () => { diff --git a/yarn-project/simulator/src/client/simulator.ts b/yarn-project/simulator/src/client/simulator.ts index 9bcdc07bd7d..bc0bb302540 100644 --- a/yarn-project/simulator/src/client/simulator.ts +++ b/yarn-project/simulator/src/client/simulator.ts @@ -14,6 +14,7 @@ import { type Logger, createLogger } from '@aztec/foundation/log'; import { createSimulationError } from '../common/errors.js'; import { PackedValuesCache } from '../common/packed_values_cache.js'; +import { type SimulationProvider } from '../common/simulation_provider.js'; import { ClientExecutionContext } from './client_execution_context.js'; import { type DBOracle } from './db_oracle.js'; import { ExecutionNoteCache } from './execution_note_cache.js'; @@ -27,7 +28,7 @@ import { ViewDataOracle } from './view_data_oracle.js'; export class AcirSimulator { private log: Logger; - constructor(private db: DBOracle, private node: AztecNode) { + constructor(private db: DBOracle, private node: AztecNode, private simulationProvider: SimulationProvider) { this.log = createLogger('simulator'); } @@ -81,6 +82,7 @@ export class AcirSimulator { new ExecutionNoteCache(txHash), this.db, this.node, + this.simulationProvider, startSideEffectCounter, undefined, scopes, @@ -88,6 +90,7 @@ export class AcirSimulator { try { const executionResult = await executePrivateFunction( + this.simulationProvider, context, entryPointArtifact, contractAddress, @@ -120,6 +123,7 @@ export class AcirSimulator { try { return await executeUnconstrainedFunction( + this.simulationProvider, context, entryPointArtifact, contractAddress, diff --git a/yarn-project/simulator/src/client/unconstrained_execution.test.ts b/yarn-project/simulator/src/client/unconstrained_execution.test.ts index 498ac7cd886..ad270fc9864 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.test.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.test.ts @@ -7,10 +7,13 @@ import { StatefulTestContractArtifact } from '@aztec/noir-contracts.js/StatefulT import { mock } from 'jest-mock-extended'; +import { WASMSimulator } from '../providers/acvm_wasm.js'; import { type DBOracle } from './db_oracle.js'; import { AcirSimulator } from './simulator.js'; describe('Unconstrained Execution test suite', () => { + const simulationProvider = new WASMSimulator(); + let oracle: ReturnType>; let node: ReturnType>; let acirSimulator: AcirSimulator; @@ -23,7 +26,7 @@ describe('Unconstrained Execution test suite', () => { node.getChainId.mockResolvedValue(1); node.getVersion.mockResolvedValue(1); - acirSimulator = new AcirSimulator(oracle, node); + acirSimulator = new AcirSimulator(oracle, node, simulationProvider); }); describe('private token contract', () => { diff --git a/yarn-project/simulator/src/client/unconstrained_execution.ts b/yarn-project/simulator/src/client/unconstrained_execution.ts index b9066fd0500..f29bf3c311f 100644 --- a/yarn-project/simulator/src/client/unconstrained_execution.ts +++ b/yarn-project/simulator/src/client/unconstrained_execution.ts @@ -4,8 +4,9 @@ import { type Fr } from '@aztec/foundation/fields'; import { createLogger } from '@aztec/foundation/log'; import { witnessMapToFields } from '../acvm/deserialize.js'; -import { Oracle, acvm, extractCallStack, toACVMWitness } from '../acvm/index.js'; +import { Oracle, extractCallStack, toACVMWitness } from '../acvm/index.js'; import { ExecutionError, resolveAssertionMessageFromError } from '../common/errors.js'; +import { type SimulationProvider } from '../server.js'; import { type ViewDataOracle } from './view_data_oracle.js'; // docs:start:execute_unconstrained_function @@ -13,6 +14,7 @@ import { type ViewDataOracle } from './view_data_oracle.js'; * Execute an unconstrained function and return the decoded values. */ export async function executeUnconstrainedFunction( + simulatorProvider: SimulationProvider, oracle: ViewDataOracle, artifact: FunctionArtifact, contractAddress: AztecAddress, @@ -24,18 +26,20 @@ export async function executeUnconstrainedFunction( const acir = artifact.bytecode; const initialWitness = toACVMWitness(0, args); - const acirExecutionResult = await acvm(acir, initialWitness, new Oracle(oracle)).catch((err: Error) => { - err.message = resolveAssertionMessageFromError(err, artifact); - throw new ExecutionError( - err.message, - { - contractAddress, - functionSelector, - }, - extractCallStack(err, artifact.debug), - { cause: err }, - ); - }); + const acirExecutionResult = await simulatorProvider + .executeUserCircuit(acir, initialWitness, new Oracle(oracle)) + .catch((err: Error) => { + err.message = resolveAssertionMessageFromError(err, artifact); + throw new ExecutionError( + err.message, + { + contractAddress, + functionSelector, + }, + extractCallStack(err, artifact.debug), + { cause: err }, + ); + }); const returnWitness = witnessMapToFields(acirExecutionResult.returnWitness); return decodeFromAbi(artifact.returnTypes, returnWitness); diff --git a/yarn-project/simulator/src/common.ts b/yarn-project/simulator/src/common.ts new file mode 100644 index 00000000000..c3b15cc2eaf --- /dev/null +++ b/yarn-project/simulator/src/common.ts @@ -0,0 +1 @@ +export * from './common/index.js'; diff --git a/yarn-project/simulator/src/common/message_load_oracle_inputs.ts b/yarn-project/simulator/src/common/message_load_oracle_inputs.ts new file mode 100644 index 00000000000..d6757f4459b --- /dev/null +++ b/yarn-project/simulator/src/common/message_load_oracle_inputs.ts @@ -0,0 +1,15 @@ +import { type SiblingPath } from '@aztec/circuit-types'; +import { Fr } from '@aztec/circuits.js'; + +export class MessageLoadOracleInputs { + constructor( + /** The index of the message commitment in the merkle tree. */ + public index: bigint, + /** The path in the merkle tree to the message. */ + public siblingPath: SiblingPath, + ) {} + + toFields(): Fr[] { + return [new Fr(this.index), ...this.siblingPath.toFields()]; + } +} diff --git a/yarn-project/simulator/src/common/simulation_provider.ts b/yarn-project/simulator/src/common/simulation_provider.ts new file mode 100644 index 00000000000..f927741af8f --- /dev/null +++ b/yarn-project/simulator/src/common/simulation_provider.ts @@ -0,0 +1,45 @@ +import { type NoirCompiledCircuit } from '@aztec/types/noir'; + +import { type ExecutionError } from '@noir-lang/acvm_js'; +import { abiDecodeError } from '@noir-lang/noirc_abi'; +import { type Abi, type WitnessMap } from '@noir-lang/types'; + +import { type ACIRCallback, type ACIRExecutionResult } from '../acvm/acvm.js'; +import { type ACVMWitness } from '../acvm/acvm_types.js'; + +/** + * Low level simulation interface + */ +export interface SimulationProvider { + executeProtocolCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise; + executeUserCircuit(acir: Buffer, initialWitness: ACVMWitness, callback: ACIRCallback): Promise; +} + +export type ErrorWithPayload = ExecutionError & { decodedAssertionPayload?: any }; + +// Error handling taken from noir/noir-repo/tooling/noir_js/src/witness_generation.ts. +// TODO: import this in isolation without having to import noir_js in its entirety. +export function parseErrorPayload(abi: Abi, originalError: ExecutionError): Error { + const payload = originalError.rawAssertionPayload; + if (!payload) { + return originalError; + } + const enrichedError = originalError as ErrorWithPayload; + + try { + // Decode the payload + const decodedPayload = abiDecodeError(abi, payload); + + if (typeof decodedPayload === 'string') { + // If it's a string, just add it to the error message + enrichedError.message = `Circuit execution failed: ${decodedPayload}`; + } else { + // If not, attach the payload to the original error + enrichedError.decodedAssertionPayload = decodedPayload; + } + } catch (_errorDecoding) { + // Ignore errors decoding the payload + } + + return enrichedError; +} diff --git a/yarn-project/simulator/src/providers/acvm_native.ts b/yarn-project/simulator/src/providers/acvm_native.ts index eba2d06b999..66613be1003 100644 --- a/yarn-project/simulator/src/providers/acvm_native.ts +++ b/yarn-project/simulator/src/providers/acvm_native.ts @@ -7,7 +7,9 @@ import { type WitnessMap } from '@noir-lang/types'; import * as proc from 'child_process'; import { promises as fs } from 'fs'; -import { type SimulationProvider } from './simulation_provider.js'; +import { type ACIRCallback, type ACIRExecutionResult } from '../acvm/acvm.js'; +import { type ACVMWitness } from '../acvm/acvm_types.js'; +import { type SimulationProvider } from '../common/simulation_provider.js'; const logger = createLogger('simulator:acvm-native'); @@ -134,7 +136,7 @@ export async function executeNativeCircuit( export class NativeACVMSimulator implements SimulationProvider { constructor(private workingDirectory: string, private pathToAcvm: string, private witnessFilename?: string) {} - async simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise { + async executeProtocolCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise { // Execute the circuit on those initial witness values const operation = async (directory: string) => { @@ -158,4 +160,12 @@ export class NativeACVMSimulator implements SimulationProvider { return await runInDirectory(this.workingDirectory, operation, false); } + + executeUserCircuit( + _acir: Buffer, + _initialWitness: ACVMWitness, + _callback: ACIRCallback, + ): Promise { + throw new Error('Not implemented'); + } } diff --git a/yarn-project/simulator/src/providers/acvm_wasm.ts b/yarn-project/simulator/src/providers/acvm_wasm.ts index 244e6e168a0..5656db2aa4d 100644 --- a/yarn-project/simulator/src/providers/acvm_wasm.ts +++ b/yarn-project/simulator/src/providers/acvm_wasm.ts @@ -1,25 +1,52 @@ import { foreignCallHandler } from '@aztec/noir-protocol-circuits-types/client'; import { type NoirCompiledCircuit } from '@aztec/types/noir'; -import { executeCircuit } from '@noir-lang/acvm_js'; +import initACVM, { type ExecutionError, executeCircuit } from '@noir-lang/acvm_js'; +import initAbi from '@noir-lang/noirc_abi'; import { type WitnessMap } from '@noir-lang/types'; -import { type SimulationProvider } from './simulation_provider.js'; +import { type ACIRCallback, acvm } from '../acvm/acvm.js'; +import { type ACVMWitness } from '../acvm/acvm_types.js'; +import { type SimulationProvider, parseErrorPayload } from '../common/simulation_provider.js'; export class WASMSimulator implements SimulationProvider { - async simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise { + async init(): Promise { + // If these are available, then we are in the + // web environment. For the node environment, this + // is a no-op. + if (typeof initAbi === 'function') { + /** @ts-expect-error The node bundle doesn't include these default imports, so TS complains */ + await Promise.all([initAbi(), initACVM()]); + } + } + + async executeProtocolCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise { + await this.init(); // Execute the circuit on those initial witness values // // Decode the bytecode from base64 since the acvm does not know about base64 encoding const decodedBytecode = Buffer.from(compiledCircuit.bytecode, 'base64'); // // Execute the circuit - const _witnessMap = await executeCircuit( - decodedBytecode, - input, - foreignCallHandler, // handle calls to debug_log - ); + try { + const _witnessMap = await executeCircuit( + decodedBytecode, + input, + foreignCallHandler, // handle calls to debug_log + ); + + return _witnessMap; + } catch (err) { + // Typescript types catched errors as unknown or any, so we need to narrow its type to check if it has raw assertion payload. + if (typeof err === 'object' && err !== null && 'rawAssertionPayload' in err) { + throw parseErrorPayload(compiledCircuit.abi, err as ExecutionError); + } + throw new Error(`Circuit execution failed: ${err}`); + } + } - return _witnessMap; + async executeUserCircuit(acir: Buffer, initialWitness: ACVMWitness, callback: ACIRCallback) { + await this.init(); + return acvm(acir, initialWitness, callback); } } diff --git a/yarn-project/simulator/src/providers/acvm_wasm_with_blobs.ts b/yarn-project/simulator/src/providers/acvm_wasm_with_blobs.ts index 3940e97b1d2..f85970b6497 100644 --- a/yarn-project/simulator/src/providers/acvm_wasm_with_blobs.ts +++ b/yarn-project/simulator/src/providers/acvm_wasm_with_blobs.ts @@ -1,25 +1,50 @@ import { foreignCallHandler } from '@aztec/noir-protocol-circuits-types/server'; import { type NoirCompiledCircuit } from '@aztec/types/noir'; -import { executeCircuit } from '@noir-lang/acvm_js'; +import { type ExecutionError, executeCircuit } from '@noir-lang/acvm_js'; import { type WitnessMap } from '@noir-lang/types'; -import { type SimulationProvider } from './simulation_provider.js'; +import { type ACIRCallback, type ACIRExecutionResult } from '../acvm/acvm.js'; +import { type ACVMWitness } from '../acvm/acvm_types.js'; +import { type SimulationProvider, parseErrorPayload } from '../common/simulation_provider.js'; +/** + * A simulation provider that uses the WASM simulator with the ability to handle blobs via the foreign call handler. + * This class is temporary while brillig cannot handle the blob math, and it is kept separate + * because the zkg commitment library used in the blob code is not browser compatible. + * + * It is only used in the context of server-side code executing simulated protocol circuits. + */ export class WASMSimulatorWithBlobs implements SimulationProvider { - async simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise { + async executeProtocolCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise { // Execute the circuit on those initial witness values // // Decode the bytecode from base64 since the acvm does not know about base64 encoding const decodedBytecode = Buffer.from(compiledCircuit.bytecode, 'base64'); // // Execute the circuit - const _witnessMap = await executeCircuit( - decodedBytecode, - input, - foreignCallHandler, // handle calls to debug_log and evaluate_blobs mock - ); + try { + const _witnessMap = await executeCircuit( + decodedBytecode, + input, + foreignCallHandler, // handle calls to debug_log and evaluate_blobs mock + ); - return _witnessMap; + return _witnessMap; + } catch (err) { + // Typescript types catched errors as unknown or any, so we need to narrow its type to check if it has raw assertion payload. + if (typeof err === 'object' && err !== null && 'rawAssertionPayload' in err) { + throw parseErrorPayload(compiledCircuit.abi, err as ExecutionError); + } + throw new Error(`Circuit execution failed: ${err}`); + } + } + + executeUserCircuit( + _acir: Buffer, + _initialWitness: ACVMWitness, + _callback: ACIRCallback, + ): Promise { + throw new Error('Not implemented'); } } diff --git a/yarn-project/simulator/src/providers/factory.ts b/yarn-project/simulator/src/providers/factory.ts index 6dedea7495a..cf8f919cb00 100644 --- a/yarn-project/simulator/src/providers/factory.ts +++ b/yarn-project/simulator/src/providers/factory.ts @@ -2,9 +2,9 @@ import { type Logger, createLogger } from '@aztec/foundation/log'; import { promises as fs } from 'fs'; +import { type SimulationProvider } from '../common/simulation_provider.js'; import { NativeACVMSimulator } from './acvm_native.js'; import { WASMSimulator } from './acvm_wasm.js'; -import { type SimulationProvider } from './simulation_provider.js'; export type SimulationProviderConfig = { acvmBinaryPath?: string; diff --git a/yarn-project/simulator/src/providers/index.ts b/yarn-project/simulator/src/providers/index.ts index b4a832329bf..3efa01c9234 100644 --- a/yarn-project/simulator/src/providers/index.ts +++ b/yarn-project/simulator/src/providers/index.ts @@ -1,4 +1,4 @@ export * from './acvm_native.js'; export * from './acvm_wasm_with_blobs.js'; -export * from './simulation_provider.js'; +export * from '../common/simulation_provider.js'; export * from './factory.js'; diff --git a/yarn-project/simulator/src/providers/simulation_provider.ts b/yarn-project/simulator/src/providers/simulation_provider.ts deleted file mode 100644 index e0a087fcc37..00000000000 --- a/yarn-project/simulator/src/providers/simulation_provider.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { type NoirCompiledCircuit } from '@aztec/types/noir'; - -import { type WitnessMap } from '@noir-lang/types'; - -/** - * Low level simulation interface - */ -export interface SimulationProvider { - simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise; -} diff --git a/yarn-project/simulator/src/public/db_interfaces.ts b/yarn-project/simulator/src/public/db_interfaces.ts index b8d022080cc..ef37858d92b 100644 --- a/yarn-project/simulator/src/public/db_interfaces.ts +++ b/yarn-project/simulator/src/public/db_interfaces.ts @@ -7,7 +7,7 @@ import { import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { type Fr } from '@aztec/foundation/fields'; -import { type MessageLoadOracleInputs } from '../acvm/index.js'; +import { type MessageLoadOracleInputs } from '../common/message_load_oracle_inputs.js'; /** * Database interface for providing access to public state. diff --git a/yarn-project/simulator/src/public/fixtures/index.ts b/yarn-project/simulator/src/public/fixtures/index.ts index 17cca0600ce..e7d4ce26b6f 100644 --- a/yarn-project/simulator/src/public/fixtures/index.ts +++ b/yarn-project/simulator/src/public/fixtures/index.ts @@ -32,19 +32,16 @@ import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr, Point } from '@aztec/foundation/fields'; import { openTmpStore } from '@aztec/kv-store/lmdb'; import { AvmTestContractArtifact } from '@aztec/noir-contracts.js/AvmTest'; -import { - AvmEphemeralForest, - AvmSimulator, - PublicEnqueuedCallSideEffectTrace, - PublicTxSimulator, - WorldStateDB, -} from '@aztec/simulator'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { MerkleTrees } from '@aztec/world-state'; import { strict as assert } from 'assert'; import { initContext, initExecutionEnvironment, initPersistableStateManager } from '../../avm/fixtures/index.js'; +import { AvmEphemeralForest, AvmSimulator } from '../../server.js'; +import { PublicEnqueuedCallSideEffectTrace } from '../enqueued_call_side_effect_trace.js'; +import { WorldStateDB } from '../public_db_sources.js'; +import { PublicTxSimulator } from '../public_tx_simulator.js'; const TIMESTAMP = new Fr(99833); diff --git a/yarn-project/simulator/src/public/public_db_sources.ts b/yarn-project/simulator/src/public/public_db_sources.ts index f9c64fe38f7..7a4185ed72a 100644 --- a/yarn-project/simulator/src/public/public_db_sources.ts +++ b/yarn-project/simulator/src/public/public_db_sources.ts @@ -24,12 +24,9 @@ import { createLogger } from '@aztec/foundation/log'; import { Timer } from '@aztec/foundation/timer'; import { ContractClassRegisteredEvent } from '@aztec/protocol-contracts/class-registerer'; import { ContractInstanceDeployedEvent } from '@aztec/protocol-contracts/instance-deployer'; -import { - type CommitmentsDB, - MessageLoadOracleInputs, - type PublicContractsDB, - type PublicStateDB, -} from '@aztec/simulator'; + +import { MessageLoadOracleInputs } from '../common/message_load_oracle_inputs.js'; +import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db_interfaces.js'; /** * Implements the PublicContractsDB using a ContractDataSource. diff --git a/yarn-project/simulator/src/index.ts b/yarn-project/simulator/src/server.ts similarity index 71% rename from yarn-project/simulator/src/index.ts rename to yarn-project/simulator/src/server.ts index f8095f6baf7..07f29d743bc 100644 --- a/yarn-project/simulator/src/index.ts +++ b/yarn-project/simulator/src/server.ts @@ -1,6 +1,4 @@ -export * from './acvm/index.js'; export * from './avm/index.js'; -export * from './client/index.js'; export * from './common/index.js'; export * from './public/index.js'; export * from './providers/index.js'; diff --git a/yarn-project/txe/src/oracle/txe_oracle.ts b/yarn-project/txe/src/oracle/txe_oracle.ts index 07965dbce20..aa25f0b241b 100644 --- a/yarn-project/txe/src/oracle/txe_oracle.ts +++ b/yarn-project/txe/src/oracle/txe_oracle.ts @@ -63,25 +63,27 @@ import { Timer } from '@aztec/foundation/timer'; import { type KeyStore } from '@aztec/key-store'; import { ContractDataOracle, SimulatorOracle, enrichPublicSimulationError } from '@aztec/pxe'; import { - ExecutionError, ExecutionNoteCache, type MessageLoadOracleInputs, type NoteData, Oracle, - type PackedValuesCache, - type PublicTxResult, - PublicTxSimulator, type TypedOracle, - acvm, - createSimulationError, + WASMSimulator, extractCallStack, extractPrivateCircuitPublicInputs, pickNotes, - resolveAssertionMessageFromError, toACVMWitness, witnessMapToFields, -} from '@aztec/simulator'; +} from '@aztec/simulator/client'; import { createTxForPublicCall } from '@aztec/simulator/public/fixtures'; +import { + ExecutionError, + type PackedValuesCache, + type PublicTxResult, + PublicTxSimulator, + createSimulationError, + resolveAssertionMessageFromError, +} from '@aztec/simulator/server'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { MerkleTreeSnapshotOperationsFacade, type MerkleTrees } from '@aztec/world-state'; @@ -116,6 +118,8 @@ export class TXE implements TypedOracle { private node = new TXENode(this.blockNumber); + private simulationProvider = new WASMSimulator(); + debug: LogFn; constructor( @@ -130,7 +134,13 @@ export class TXE implements TypedOracle { this.contractAddress = AztecAddress.random(); // Default msg_sender (for entrypoints) is now Fr.max_value rather than 0 addr (see #7190 & #7404) this.msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE); - this.simulatorOracle = new SimulatorOracle(this.contractDataOracle, txeDatabase, keyStore, this.node); + this.simulatorOracle = new SimulatorOracle( + this.contractDataOracle, + txeDatabase, + keyStore, + this.node, + this.simulationProvider, + ); this.debug = createDebugOnlyLogger('aztec:kv-pxe-database'); } @@ -701,21 +711,23 @@ export class TXE implements TypedOracle { const initialWitness = await this.getInitialWitness(artifact, argsHash, sideEffectCounter, isStaticCall); const acvmCallback = new Oracle(this); const timer = new Timer(); - const acirExecutionResult = await acvm(acir, initialWitness, acvmCallback).catch((err: Error) => { - err.message = resolveAssertionMessageFromError(err, artifact); - - const execError = new ExecutionError( - err.message, - { - contractAddress: targetContractAddress, - functionSelector, - }, - extractCallStack(err, artifact.debug), - { cause: err }, - ); - this.logger.debug(`Error executing private function ${targetContractAddress}:${functionSelector}`); - throw createSimulationError(execError); - }); + const acirExecutionResult = await this.simulationProvider + .executeUserCircuit(acir, initialWitness, acvmCallback) + .catch((err: Error) => { + err.message = resolveAssertionMessageFromError(err, artifact); + + const execError = new ExecutionError( + err.message, + { + contractAddress: targetContractAddress, + functionSelector, + }, + extractCallStack(err, artifact.debug), + { cause: err }, + ); + this.logger.debug(`Error executing private function ${targetContractAddress}:${functionSelector}`); + throw createSimulationError(execError); + }); const duration = timer.ms(); const publicInputs = extractPrivateCircuitPublicInputs(artifact, acirExecutionResult.partialWitness); diff --git a/yarn-project/txe/src/txe_service/txe_service.ts b/yarn-project/txe/src/txe_service/txe_service.ts index e0b46aa45b5..0164be15d6e 100644 --- a/yarn-project/txe/src/txe_service/txe_service.ts +++ b/yarn-project/txe/src/txe_service/txe_service.ts @@ -18,7 +18,8 @@ import { openTmpStore } from '@aztec/kv-store/lmdb'; import { protocolContractNames } from '@aztec/protocol-contracts'; import { getCanonicalProtocolContract } from '@aztec/protocol-contracts/bundle'; import { enrichPublicSimulationError } from '@aztec/pxe'; -import { ExecutionNoteCache, PackedValuesCache, type TypedOracle } from '@aztec/simulator'; +import { ExecutionNoteCache, type TypedOracle } from '@aztec/simulator/client'; +import { PackedValuesCache } from '@aztec/simulator/server'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { MerkleTrees } from '@aztec/world-state'; diff --git a/yarn-project/txe/src/util/txe_world_state_db.ts b/yarn-project/txe/src/util/txe_world_state_db.ts index d1a2b6f1737..d617ee5e72e 100644 --- a/yarn-project/txe/src/util/txe_world_state_db.ts +++ b/yarn-project/txe/src/util/txe_world_state_db.ts @@ -7,7 +7,7 @@ import { type PublicDataTreeLeafPreimage, } from '@aztec/circuits.js'; import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash'; -import { WorldStateDB } from '@aztec/simulator'; +import { WorldStateDB } from '@aztec/simulator/server'; export class TXEWorldStateDB extends WorldStateDB { constructor(private merkleDb: MerkleTreeWriteOperations, dataSource: ContractDataSource) {