@aztec/simulator 0.0.1-commit.2f68f620 → 0.0.1-commit.321f6a9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dest/client.d.ts +1 -3
  2. package/dest/client.d.ts.map +1 -1
  3. package/dest/client.js +0 -2
  4. package/dest/private/circuit_recording/circuit_recorder.d.ts +36 -23
  5. package/dest/private/circuit_recording/circuit_recorder.d.ts.map +1 -1
  6. package/dest/private/circuit_recording/circuit_recorder.js +65 -69
  7. package/dest/private/circuit_recording/file_circuit_recorder.d.ts +7 -19
  8. package/dest/private/circuit_recording/file_circuit_recorder.d.ts.map +1 -1
  9. package/dest/private/circuit_recording/file_circuit_recorder.js +38 -42
  10. package/dest/private/circuit_recording/simulator_recorder_wrapper.d.ts +1 -1
  11. package/dest/private/circuit_recording/simulator_recorder_wrapper.d.ts.map +1 -1
  12. package/dest/private/circuit_recording/simulator_recorder_wrapper.js +11 -14
  13. package/dest/public/avm/testing/base_avm_simulation_tester.js +1 -1
  14. package/dest/public/avm/testing/utils.js +1 -1
  15. package/dest/public/avm_simulator.d.ts +28 -0
  16. package/dest/public/avm_simulator.d.ts.map +1 -0
  17. package/dest/public/avm_simulator.js +4 -0
  18. package/dest/public/avm_simulator_pool.d.ts +45 -0
  19. package/dest/public/avm_simulator_pool.d.ts.map +1 -0
  20. package/dest/public/avm_simulator_pool.js +197 -0
  21. package/dest/public/cdb/generated/api_types.d.ts +171 -0
  22. package/dest/public/cdb/generated/api_types.d.ts.map +1 -0
  23. package/dest/public/cdb/generated/api_types.js +314 -0
  24. package/dest/public/cdb/generated/server.d.ts +26 -0
  25. package/dest/public/cdb/generated/server.d.ts.map +1 -0
  26. package/dest/public/cdb/generated/server.js +135 -0
  27. package/dest/public/cdb_ipc_server.d.ts +33 -0
  28. package/dest/public/cdb_ipc_server.d.ts.map +1 -0
  29. package/dest/public/cdb_ipc_server.js +153 -0
  30. package/dest/public/fixtures/amm_test.js +2 -2
  31. package/dest/public/fixtures/bulk_test.js +2 -2
  32. package/dest/public/fixtures/custom_bytecode_tester.d.ts +1 -1
  33. package/dest/public/fixtures/custom_bytecode_tester.d.ts.map +1 -1
  34. package/dest/public/fixtures/custom_bytecode_tester.js +2 -2
  35. package/dest/public/fixtures/index.d.ts +2 -1
  36. package/dest/public/fixtures/index.d.ts.map +1 -1
  37. package/dest/public/fixtures/index.js +1 -0
  38. package/dest/public/fixtures/public_processor_test_env.d.ts +30 -0
  39. package/dest/public/fixtures/public_processor_test_env.d.ts.map +1 -0
  40. package/dest/public/fixtures/public_processor_test_env.js +73 -0
  41. package/dest/public/fixtures/public_tx_simulation_tester.d.ts +9 -5
  42. package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
  43. package/dest/public/fixtures/public_tx_simulation_tester.js +29 -11
  44. package/dest/public/fixtures/token_test.js +3 -3
  45. package/dest/public/fixtures/utils.d.ts +1 -1
  46. package/dest/public/fixtures/utils.d.ts.map +1 -1
  47. package/dest/public/fixtures/utils.js +5 -3
  48. package/dest/public/fuzzing/avm_fuzzer_simulator.d.ts +7 -2
  49. package/dest/public/fuzzing/avm_fuzzer_simulator.d.ts.map +1 -1
  50. package/dest/public/fuzzing/avm_fuzzer_simulator.js +15 -6
  51. package/dest/public/index.d.ts +5 -2
  52. package/dest/public/index.d.ts.map +1 -1
  53. package/dest/public/index.js +2 -1
  54. package/dest/public/public_db_sources.d.ts +2 -2
  55. package/dest/public/public_db_sources.d.ts.map +1 -1
  56. package/dest/public/public_db_sources.js +1 -1
  57. package/dest/public/public_processor/public_processor.d.ts +8 -4
  58. package/dest/public/public_processor/public_processor.d.ts.map +1 -1
  59. package/dest/public/public_processor/public_processor.js +17 -13
  60. package/dest/public/public_tx_simulator/dumping_public_tx_simulator.d.ts +6 -12
  61. package/dest/public/public_tx_simulator/dumping_public_tx_simulator.d.ts.map +1 -1
  62. package/dest/public/public_tx_simulator/dumping_public_tx_simulator.js +8 -21
  63. package/dest/public/public_tx_simulator/factories.d.ts +5 -5
  64. package/dest/public/public_tx_simulator/factories.d.ts.map +1 -1
  65. package/dest/public/public_tx_simulator/factories.js +5 -5
  66. package/dest/public/public_tx_simulator/index.d.ts +3 -3
  67. package/dest/public/public_tx_simulator/index.d.ts.map +1 -1
  68. package/dest/public/public_tx_simulator/index.js +1 -1
  69. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +16 -16
  70. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
  71. package/dest/public/public_tx_simulator/public_tx_simulator.js +59 -58
  72. package/dest/public/public_tx_simulator/public_tx_simulator_base.d.ts +10 -8
  73. package/dest/public/public_tx_simulator/public_tx_simulator_base.d.ts.map +1 -1
  74. package/dest/public/public_tx_simulator/public_tx_simulator_base.js +11 -8
  75. package/dest/public/public_tx_simulator/public_tx_simulator_interface.d.ts +5 -5
  76. package/package.json +21 -17
  77. package/src/client.ts +0 -2
  78. package/src/private/circuit_recording/circuit_recorder.ts +84 -78
  79. package/src/private/circuit_recording/file_circuit_recorder.ts +38 -48
  80. package/src/private/circuit_recording/simulator_recorder_wrapper.ts +9 -15
  81. package/src/public/avm/testing/base_avm_simulation_tester.ts +1 -1
  82. package/src/public/avm/testing/utils.ts +1 -1
  83. package/src/public/avm_simulator.ts +29 -0
  84. package/src/public/avm_simulator_pool.ts +226 -0
  85. package/src/public/cdb/generated/api_types.ts +457 -0
  86. package/src/public/cdb/generated/server.ts +109 -0
  87. package/src/public/cdb_ipc_server.ts +197 -0
  88. package/src/public/fixtures/amm_test.ts +2 -2
  89. package/src/public/fixtures/bulk_test.ts +2 -2
  90. package/src/public/fixtures/custom_bytecode_tester.ts +2 -2
  91. package/src/public/fixtures/index.ts +1 -0
  92. package/src/public/fixtures/public_processor_test_env.ts +88 -0
  93. package/src/public/fixtures/public_tx_simulation_tester.ts +37 -25
  94. package/src/public/fixtures/token_test.ts +3 -3
  95. package/src/public/fixtures/utils.ts +6 -11
  96. package/src/public/fuzzing/avm_fuzzer_simulator.ts +28 -10
  97. package/src/public/index.ts +4 -0
  98. package/src/public/public_db_sources.ts +1 -1
  99. package/src/public/public_processor/public_processor.ts +22 -15
  100. package/src/public/public_tx_simulator/dumping_public_tx_simulator.ts +13 -29
  101. package/src/public/public_tx_simulator/factories.ts +24 -7
  102. package/src/public/public_tx_simulator/index.ts +5 -2
  103. package/src/public/public_tx_simulator/public_tx_simulator.ts +70 -81
  104. package/src/public/public_tx_simulator/public_tx_simulator_base.ts +8 -6
  105. package/src/public/public_tx_simulator/public_tx_simulator_interface.ts +5 -5
  106. package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts +0 -19
  107. package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts.map +0 -1
  108. package/dest/public/public_tx_simulator/contract_provider_for_cpp.js +0 -99
  109. package/src/public/public_tx_simulator/contract_provider_for_cpp.ts +0 -125
@@ -0,0 +1,197 @@
1
+ /**
2
+ * UDS server for AVM CDB requests.
3
+ *
4
+ * Transport (socket, framing, per-connection response ordering) is handled by the shared
5
+ * `UdsIpcServer` from `@aztec/ipc-runtime`; message dispatch comes from the generated CDB
6
+ * server. This class only implements the generated handler interface and routes requests to
7
+ * PublicContractsDB instances by fork ID.
8
+ */
9
+ import { Fr } from '@aztec/foundation/curves/bn254';
10
+ import { type Logger, createLogger } from '@aztec/foundation/log';
11
+ import { UdsIpcServer } from '@aztec/ipc-runtime';
12
+ import { FunctionSelector } from '@aztec/stdlib/abi';
13
+ import { AztecAddress } from '@aztec/stdlib/aztec-address';
14
+ import { ContractDeploymentData, type ContractInstanceWithAddress } from '@aztec/stdlib/contract';
15
+
16
+ import { Decoder, Encoder } from 'msgpackr';
17
+ import * as os from 'node:os';
18
+ import * as path from 'node:path';
19
+ import { threadId } from 'node:worker_threads';
20
+
21
+ import type {
22
+ CdbAddContracts,
23
+ CdbAddContractsResponse,
24
+ CdbCommitCheckpoint,
25
+ CdbCommitCheckpointResponse,
26
+ CdbCreateCheckpoint,
27
+ CdbCreateCheckpointResponse,
28
+ CdbGetBytecodeCommitment,
29
+ CdbGetBytecodeCommitmentResponse,
30
+ CdbGetContractClass,
31
+ CdbGetContractClassResponse,
32
+ CdbGetContractInstance,
33
+ CdbGetContractInstanceResponse,
34
+ CdbGetDebugFunctionName,
35
+ CdbGetDebugFunctionNameResponse,
36
+ CdbRevertCheckpoint,
37
+ CdbRevertCheckpointResponse,
38
+ } from './cdb/generated/api_types.js';
39
+ import { type Handler as CdbHandler, handleRequest } from './cdb/generated/server.js';
40
+ import type { PublicContractsDB } from './public_db_sources.js';
41
+
42
+ const encoder = new Encoder({ useRecords: false });
43
+ const decoder = new Decoder({ useRecords: false });
44
+
45
+ let instanceCounter = 0;
46
+
47
+ function toFieldBuffer(field: Fr | AztecAddress): Buffer {
48
+ return field.toBuffer();
49
+ }
50
+
51
+ /** Serializes contract instances to the AVM CDB wire shape. */
52
+ export function serializeContractInstance(instance: ContractInstanceWithAddress): Record<string, unknown> {
53
+ return {
54
+ salt: toFieldBuffer(instance.salt),
55
+ deployer: toFieldBuffer(instance.deployer),
56
+ currentContractClassId: toFieldBuffer(instance.currentContractClassId),
57
+ originalContractClassId: toFieldBuffer(instance.originalContractClassId),
58
+ initializationHash: toFieldBuffer(instance.initializationHash),
59
+ immutablesHash: toFieldBuffer(instance.immutablesHash),
60
+ publicKeys: {
61
+ npkMHash: toFieldBuffer(instance.publicKeys.npkMHash),
62
+ ivpkM: {
63
+ x: toFieldBuffer(instance.publicKeys.ivpkM.x),
64
+ y: toFieldBuffer(instance.publicKeys.ivpkM.y),
65
+ },
66
+ ovpkMHash: toFieldBuffer(instance.publicKeys.ovpkMHash),
67
+ tpkMHash: toFieldBuffer(instance.publicKeys.tpkMHash),
68
+ mspkMHash: toFieldBuffer(instance.publicKeys.mspkMHash),
69
+ fbpkMHash: toFieldBuffer(instance.publicKeys.fbpkMHash),
70
+ },
71
+ };
72
+ }
73
+
74
+ /** Serializes contract classes to the AVM CDB wire shape. */
75
+ function serializeContractClass(contractClass: {
76
+ id: Fr;
77
+ artifactHash: Fr;
78
+ privateFunctionsRoot: Fr;
79
+ packedBytecode: Buffer;
80
+ }): Record<string, unknown> {
81
+ return {
82
+ id: toFieldBuffer(contractClass.id),
83
+ artifactHash: toFieldBuffer(contractClass.artifactHash),
84
+ privateFunctionsRoot: toFieldBuffer(contractClass.privateFunctionsRoot),
85
+ packedBytecode: contractClass.packedBytecode,
86
+ };
87
+ }
88
+
89
+ /** Routes AVM CDB IPC requests to registered PublicContractsDB forks. */
90
+ export class CdbIpcServer implements CdbHandler {
91
+ public readonly ipcPath: string;
92
+ private server: Promise<UdsIpcServer>;
93
+ private log: Logger;
94
+ /** Maps WSDB fork IDs to contracts DB/timestamp pairs for concurrent simulations. */
95
+ private forks = new Map<number, { db: PublicContractsDB; timestamp: bigint }>();
96
+
97
+ constructor() {
98
+ this.log = createLogger('cdb-ipc-server');
99
+ this.ipcPath = path.join(os.tmpdir(), `cdb-ts-${process.pid}-${threadId}-${instanceCounter++}.sock`);
100
+
101
+ // Listen asynchronously; the C++ AVM retries connecting until the socket is up.
102
+ this.server = UdsIpcServer.listen(this.ipcPath, (_clientId, request) => handleRequest(this, request));
103
+ this.server.then(
104
+ () => this.log.debug(`CDB IPC server listening on ${this.ipcPath}`),
105
+ err => this.log.error(`CDB IPC server failed to listen on ${this.ipcPath}`, { err }),
106
+ );
107
+ }
108
+
109
+ /** Register a PublicContractsDB for a given WSDB fork ID. */
110
+ registerFork(forkId: number, contractsDB: PublicContractsDB, timestamp: bigint): void {
111
+ this.forks.set(forkId, { db: contractsDB, timestamp });
112
+ }
113
+
114
+ /** Unregister a fork's contracts DB (call after simulation completes). */
115
+ unregisterFork(forkId: number): void {
116
+ this.forks.delete(forkId);
117
+ }
118
+
119
+ /** Close the server and all active connections. */
120
+ async close(): Promise<void> {
121
+ const server = await this.server.catch(() => undefined);
122
+ await server?.close();
123
+ }
124
+
125
+ async [Symbol.asyncDispose](): Promise<void> {
126
+ await this.close();
127
+ }
128
+
129
+ /** Look up the contracts DB for a given fork ID, throwing if not registered. */
130
+ private getFork(forkId: number): { db: PublicContractsDB; timestamp: bigint } {
131
+ const fork = this.forks.get(forkId);
132
+ if (!fork) {
133
+ const registered = Array.from(this.forks.keys()).sort((a, b) => a - b);
134
+ throw new Error(
135
+ `CDB server: no contracts DB registered for forkId ${forkId} (registered=[${registered.join(',')}])`,
136
+ );
137
+ }
138
+ return fork;
139
+ }
140
+
141
+ async getContractInstance(command: CdbGetContractInstance): Promise<CdbGetContractInstanceResponse> {
142
+ const { db, timestamp } = this.getFork(command.forkId);
143
+ const address = AztecAddress.fromBuffer(Buffer.from(command.address));
144
+ const instance = await db.getContractInstance(address, timestamp);
145
+ return { instance: instance ? encoder.encode(serializeContractInstance(instance)) : null };
146
+ }
147
+
148
+ async getContractClass(command: CdbGetContractClass): Promise<CdbGetContractClassResponse> {
149
+ const { db } = this.getFork(command.forkId);
150
+ const classId = Fr.fromBuffer(Buffer.from(command.classId));
151
+ const contractClass = await db.getContractClass(classId);
152
+ return { contractClass: contractClass ? encoder.encode(serializeContractClass(contractClass)) : null };
153
+ }
154
+
155
+ async getBytecodeCommitment(command: CdbGetBytecodeCommitment): Promise<CdbGetBytecodeCommitmentResponse> {
156
+ const { db } = this.getFork(command.forkId);
157
+ const classId = Fr.fromBuffer(Buffer.from(command.classId));
158
+ const commitment = await db.getBytecodeCommitment(classId);
159
+ return { commitment: commitment ? toFieldBuffer(commitment) : null };
160
+ }
161
+
162
+ async getDebugFunctionName(command: CdbGetDebugFunctionName): Promise<CdbGetDebugFunctionNameResponse> {
163
+ const { db } = this.getFork(command.forkId);
164
+ const address = AztecAddress.fromBuffer(Buffer.from(command.address));
165
+ const selectorField = Fr.fromBuffer(Buffer.from(command.selector));
166
+ const selector = FunctionSelector.fromFieldOrUndefined(selectorField);
167
+ const name = selector ? await db.getDebugFunctionName(address, selector) : undefined;
168
+ return { name: name ?? null };
169
+ }
170
+
171
+ addContracts(command: CdbAddContracts): Promise<CdbAddContractsResponse> {
172
+ const { db } = this.getFork(command.forkId);
173
+ const contractDeploymentData = ContractDeploymentData.fromPlainObject(
174
+ decoder.decode(command.contractDeploymentData),
175
+ );
176
+ db.addContractsFromLogs(contractDeploymentData);
177
+ return Promise.resolve({});
178
+ }
179
+
180
+ createCheckpoint(command: CdbCreateCheckpoint): Promise<CdbCreateCheckpointResponse> {
181
+ const { db } = this.getFork(command.forkId);
182
+ db.createCheckpoint();
183
+ return Promise.resolve({});
184
+ }
185
+
186
+ commitCheckpoint(command: CdbCommitCheckpoint): Promise<CdbCommitCheckpointResponse> {
187
+ const { db } = this.getFork(command.forkId);
188
+ db.commitCheckpoint();
189
+ return Promise.resolve({});
190
+ }
191
+
192
+ revertCheckpoint(command: CdbRevertCheckpoint): Promise<CdbRevertCheckpointResponse> {
193
+ const { db } = this.getFork(command.forkId);
194
+ db.revertCheckpoint();
195
+ return Promise.resolve({});
196
+ }
197
+ }
@@ -25,8 +25,8 @@ export async function ammTest(
25
25
  ) {
26
26
  const timer = new Timer();
27
27
 
28
- const admin = AztecAddress.fromNumber(42);
29
- const sender = AztecAddress.fromNumber(111);
28
+ const admin = AztecAddress.fromNumberUnsafe(42);
29
+ const sender = AztecAddress.fromNumberUnsafe(111);
30
30
 
31
31
  logger.debug(`Deploying tokens`);
32
32
  const token0 = await setUpToken(tester, tokenArtifact, admin, expectToBeTrue, /*seed=*/ 0);
@@ -13,7 +13,7 @@ export async function bulkTest(
13
13
  ) {
14
14
  const timer = new Timer();
15
15
 
16
- const deployer = AztecAddress.fromNumber(42);
16
+ const deployer = AztecAddress.fromNumberUnsafe(42);
17
17
  const avmTestContract = await tester.registerAndDeployContract(
18
18
  /*constructorArgs=*/ [],
19
19
  deployer,
@@ -114,7 +114,7 @@ export async function megaBulkTest(
114
114
  ) {
115
115
  const timer = new Timer();
116
116
 
117
- const deployer = AztecAddress.fromNumber(42);
117
+ const deployer = AztecAddress.fromNumberUnsafe(42);
118
118
  const avmTestContract = await tester.registerAndDeployContract(
119
119
  /*constructorArgs=*/ [],
120
120
  deployer,
@@ -17,7 +17,7 @@ export async function deployCustomBytecode(
17
17
  bytecode: Buffer,
18
18
  tester: PublicTxSimulationTester,
19
19
  contractName: string = 'CustomBytecodeContract',
20
- deployer: AztecAddress = AztecAddress.fromNumber(42),
20
+ deployer: AztecAddress = AztecAddress.fromNumberUnsafe(42),
21
21
  ): Promise<ContractInstanceWithAddress> {
22
22
  const contractArtifact = emptyContractArtifact();
23
23
  contractArtifact.name = contractName;
@@ -75,7 +75,7 @@ export async function deployAndExecuteCustomBytecode(
75
75
  tester: PublicTxSimulationTester,
76
76
  txLabel: string = 'CustomBytecodeTest',
77
77
  contractName: string = 'CustomBytecodeContract',
78
- deployer: AztecAddress = AztecAddress.fromNumber(42),
78
+ deployer: AztecAddress = AztecAddress.fromNumberUnsafe(42),
79
79
  calldata: any[] = [],
80
80
  ): Promise<PublicTxResult> {
81
81
  const testContract = await deployCustomBytecode(bytecode, tester, contractName, deployer);
@@ -1,4 +1,5 @@
1
1
  export * from './public_tx_simulation_tester.js';
2
+ export * from './public_processor_test_env.js';
2
3
  export * from './utils.js';
3
4
  export * from './simple_contract_data_source.js';
4
5
  export { TestExecutorMetrics } from '../test_executor_metrics.js';
@@ -0,0 +1,88 @@
1
+ import { createLogger } from '@aztec/foundation/log';
2
+ import { TestDateProvider } from '@aztec/foundation/timer';
3
+ import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
4
+ import { GasFees } from '@aztec/stdlib/gas';
5
+ import { GlobalVariables } from '@aztec/stdlib/tx';
6
+ import { getTelemetryClient } from '@aztec/telemetry-client';
7
+ import { NativeWorldStateService } from '@aztec/world-state';
8
+
9
+ import { AvmSimulatorPool } from '../avm_simulator_pool.js';
10
+ import { PublicContractsDB } from '../public_db_sources.js';
11
+ import { GuardedMerkleTreeOperations } from '../public_processor/guarded_merkle_tree.js';
12
+ import { PublicProcessor } from '../public_processor/public_processor.js';
13
+ import { PublicTxSimulator } from '../public_tx_simulator/public_tx_simulator.js';
14
+ import { PublicTxSimulationTester } from './public_tx_simulation_tester.js';
15
+ import { SimpleContractDataSource } from './simple_contract_data_source.js';
16
+
17
+ /** Options for {@link PublicProcessorTestEnv.create}. */
18
+ export interface PublicProcessorTestEnvOptions {
19
+ /** Global variables shared by the processor and the tester. Defaults to empty with nonzero gas fees. */
20
+ globals?: GlobalVariables;
21
+ /** Simulator config for the processor's PublicTxSimulator. */
22
+ config?: Partial<PublicSimulatorConfig>;
23
+ }
24
+
25
+ function defaultGlobals(): GlobalVariables {
26
+ const globals = GlobalVariables.empty();
27
+ globals.gasFees = new GasFees(2, 3);
28
+ return globals;
29
+ }
30
+
31
+ const defaultConfig = PublicSimulatorConfig.from({
32
+ skipFeeEnforcement: false,
33
+ collectDebugLogs: true,
34
+ collectHints: false,
35
+ collectStatistics: false,
36
+ collectCallMetadata: true,
37
+ });
38
+
39
+ /**
40
+ * Bundles the real-AVM wiring shared by public-processor app tests: a live WSDB world state, a CDB IPC
41
+ * server, a spawned AVM simulator, a {@link PublicProcessor} backed by all three, and a setup-only
42
+ * {@link PublicTxSimulationTester} sharing the same fork and contract data source for building txs and
43
+ * seeding balances. Own it with `await using`, or call {@link Symbol.asyncDispose} from `afterEach`.
44
+ */
45
+ export class PublicProcessorTestEnv implements AsyncDisposable {
46
+ private constructor(
47
+ public readonly processor: PublicProcessor,
48
+ public readonly tester: PublicTxSimulationTester,
49
+ public readonly contractsDB: PublicContractsDB,
50
+ public readonly globals: GlobalVariables,
51
+ private readonly worldStateService: NativeWorldStateService,
52
+ private readonly avmSimulator: AvmSimulatorPool,
53
+ ) {}
54
+
55
+ static async create(opts: PublicProcessorTestEnvOptions = {}): Promise<PublicProcessorTestEnv> {
56
+ const globals = opts.globals ?? defaultGlobals();
57
+ const config = opts.config ? PublicSimulatorConfig.from({ ...defaultConfig, ...opts.config }) : defaultConfig;
58
+
59
+ const contractDataSource = new SimpleContractDataSource();
60
+ const worldStateService = await NativeWorldStateService.tmp();
61
+ const merkleTrees = await worldStateService.fork();
62
+ const contractsDB = new PublicContractsDB(contractDataSource);
63
+
64
+ const forkId = merkleTrees.getRevision().forkId;
65
+ const avmSimulator = await AvmSimulatorPool.spawn({ wsdbIpcPath: worldStateService.getIpcPath() });
66
+
67
+ const simulator = new PublicTxSimulator(avmSimulator, globals, contractsDB, forkId, config, undefined);
68
+ const processor = new PublicProcessor(
69
+ globals,
70
+ new GuardedMerkleTreeOperations(merkleTrees),
71
+ contractsDB,
72
+ simulator,
73
+ new TestDateProvider(),
74
+ getTelemetryClient(),
75
+ createLogger('simulator:public-processor'),
76
+ );
77
+
78
+ const tester = new PublicTxSimulationTester(merkleTrees, contractDataSource, globals);
79
+
80
+ return new PublicProcessorTestEnv(processor, tester, contractsDB, globals, worldStateService, avmSimulator);
81
+ }
82
+
83
+ async [Symbol.asyncDispose](): Promise<void> {
84
+ await this.avmSimulator[Symbol.asyncDispose]();
85
+ await this.tester.close();
86
+ await this.worldStateService.close();
87
+ }
88
+ }
@@ -5,7 +5,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
5
5
  import { type ContractArtifact, encodeArguments } from '@aztec/stdlib/abi';
6
6
  import { PublicSimulatorConfig, type PublicTxResult } from '@aztec/stdlib/avm';
7
7
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
8
- import { FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT, Gas, GasFees } from '@aztec/stdlib/gas';
8
+ import { Gas, GasFees } from '@aztec/stdlib/gas';
9
9
  import type { MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
10
10
  import { PublicCallRequest } from '@aztec/stdlib/kernel';
11
11
  import { GlobalVariables, PublicCallRequestWithCalldata, type Tx } from '@aztec/stdlib/tx';
@@ -18,6 +18,7 @@ import {
18
18
  getContractFunctionAbi,
19
19
  getFunctionSelector,
20
20
  } from '../avm/testing/utils.js';
21
+ import { AvmSimulatorPool } from '../avm_simulator_pool.js';
21
22
  import { PublicContractsDB } from '../public_db_sources.js';
22
23
  import { MeasuredPublicTxSimulator } from '../public_tx_simulator/public_tx_simulator.js';
23
24
  import type { MeasuredPublicTxSimulatorInterface } from '../public_tx_simulator/public_tx_simulator_interface.js';
@@ -26,6 +27,8 @@ import { SimpleContractDataSource } from './simple_contract_data_source.js';
26
27
  import { type TestPrivateInsertions, createTxForPublicCalls } from './utils.js';
27
28
 
28
29
  const DEFAULT_GAS_FEES = new GasFees(2, 3);
30
+ const TEARDOWN_DA_GAS_LIMIT = 98_304;
31
+ const TEARDOWN_L2_GAS_LIMIT = 817_500;
29
32
 
30
33
  export type TestEnqueuedCall = {
31
34
  sender?: AztecAddress;
@@ -63,8 +66,9 @@ export type MeasuredSimulatorFactory = (
63
66
  */
64
67
  export class PublicTxSimulationTester extends BaseAvmSimulationTester {
65
68
  protected txCount: number = 0;
66
- private simulator: MeasuredPublicTxSimulatorInterface;
69
+ private simulator: MeasuredPublicTxSimulatorInterface | undefined;
67
70
  private metricsPrefix?: string;
71
+ protected avmSimulator?: AvmSimulatorPool;
68
72
 
69
73
  constructor(
70
74
  merkleTree: MerkleTreeWriteOperations,
@@ -80,7 +84,9 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
80
84
  if (simulatorFactory) {
81
85
  this.simulator = simulatorFactory(merkleTree, contractsDB, globals, this.metrics, config);
82
86
  } else {
83
- this.simulator = new MeasuredPublicTxSimulator(merkleTree, contractsDB, globals, this.metrics, config);
87
+ // No simulator this tester can only be used for setup (setFeePayerBalance, createTx, etc.)
88
+ // To simulate, use PublicTxSimulationTester.create() or pass a simulatorFactory.
89
+ this.simulator = undefined;
84
90
  }
85
91
  }
86
92
 
@@ -92,9 +98,21 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
92
98
  ): Promise<PublicTxSimulationTester> {
93
99
  const contractDataSource = new SimpleContractDataSource();
94
100
  const merkleTree = await worldStateService.fork();
101
+
102
+ const avmSimulator = await AvmSimulatorPool.spawn({ wsdbIpcPath: worldStateService.getIpcPath() });
95
103
  const simulatorFactory: MeasuredSimulatorFactory = (mt, cdb, g, m, c) =>
96
- new MeasuredPublicTxSimulator(mt, cdb, g, m, c);
97
- return new PublicTxSimulationTester(merkleTree, contractDataSource, globals, metrics, simulatorFactory, config);
104
+ new MeasuredPublicTxSimulator(avmSimulator, g, cdb, mt.getRevision().forkId, m, c, undefined);
105
+
106
+ const tester = new PublicTxSimulationTester(
107
+ merkleTree,
108
+ contractDataSource,
109
+ globals,
110
+ metrics,
111
+ simulatorFactory,
112
+ config,
113
+ );
114
+ tester.avmSimulator = avmSimulator;
115
+ return tester;
98
116
  }
99
117
 
100
118
  public setMetricsPrefix(prefix: string) {
@@ -129,10 +147,7 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
129
147
  teardownCallRequest,
130
148
  feePayer,
131
149
  /*gasUsedByPrivate*/ teardownCall
132
- ? new Gas(
133
- FALLBACK_TEARDOWN_DA_GAS_LIMIT + TX_DA_GAS_OVERHEAD,
134
- FALLBACK_TEARDOWN_L2_GAS_LIMIT + PUBLIC_TX_L2_GAS_OVERHEAD,
135
- )
150
+ ? new Gas(TEARDOWN_DA_GAS_LIMIT + TX_DA_GAS_OVERHEAD, TEARDOWN_L2_GAS_LIMIT + PUBLIC_TX_L2_GAS_OVERHEAD)
136
151
  : new Gas(TX_DA_GAS_OVERHEAD, PUBLIC_TX_L2_GAS_OVERHEAD),
137
152
  defaultGlobals(),
138
153
  gasLimits,
@@ -193,18 +208,8 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
193
208
  teardownCall?: TestEnqueuedCall,
194
209
  feePayer?: AztecAddress,
195
210
  privateInsertions?: TestPrivateInsertions,
196
- gasLimits?: Gas,
197
211
  ): Promise<PublicTxResult> {
198
- return await this.simulateTx(
199
- sender,
200
- setupCalls,
201
- appCalls,
202
- teardownCall,
203
- feePayer,
204
- privateInsertions,
205
- txLabel,
206
- gasLimits,
207
- );
212
+ return await this.simulateTx(sender, setupCalls, appCalls, teardownCall, feePayer, privateInsertions, txLabel);
208
213
  }
209
214
 
210
215
  /**
@@ -222,7 +227,6 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
222
227
  teardownCall?: TestEnqueuedCall,
223
228
  feePayer?: AztecAddress,
224
229
  privateInsertions?: TestPrivateInsertions,
225
- gasLimits?: Gas,
226
230
  ): Promise<PublicTxResult> {
227
231
  return await this.simulateTxWithLabel(
228
232
  txLabel,
@@ -232,7 +236,6 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
232
236
  teardownCall,
233
237
  feePayer,
234
238
  privateInsertions,
235
- gasLimits,
236
239
  );
237
240
  }
238
241
 
@@ -240,22 +243,31 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
240
243
  this.metrics.prettyPrint();
241
244
  }
242
245
 
246
+ /** Clean up IPC resources (AVM simulator pool and merkle tree fork) created by create(). */
247
+ public async close(): Promise<void> {
248
+ await this.avmSimulator?.[Symbol.asyncDispose]();
249
+ // Close the merkle tree fork to release IPC resources before the wsdb process is killed.
250
+ if (this.merkleTrees?.close) {
251
+ await this.merkleTrees.close().catch(() => {});
252
+ }
253
+ }
254
+
243
255
  /**
244
256
  * Cancel the current simulation if one is in progress.
245
- * This signals the underlying simulator (e.g., C++) to stop at the next safe point.
257
+ * This signals the underlying simulator to stop at the next safe point.
246
258
  * Safe to call even if no simulation is in progress.
247
259
  *
248
260
  * @param waitTimeoutMs - If provided, wait up to this many ms for the simulation to actually stop.
249
261
  */
250
262
  public async cancel(waitTimeoutMs?: number): Promise<void> {
251
- await this.simulator.cancel?.(waitTimeoutMs);
263
+ await this.simulator?.cancel?.(waitTimeoutMs);
252
264
  }
253
265
 
254
266
  /**
255
267
  * Get the underlying simulator for advanced test scenarios.
256
268
  * Use this when you need direct control over simulation (e.g., for testing cancellation).
257
269
  */
258
- public getSimulator(): MeasuredPublicTxSimulatorInterface {
270
+ public getSimulator(): MeasuredPublicTxSimulatorInterface | undefined {
259
271
  return this.simulator;
260
272
  }
261
273
 
@@ -21,9 +21,9 @@ export async function tokenTest(
21
21
  ) {
22
22
  const timer = new Timer();
23
23
 
24
- const admin = AztecAddress.fromNumber(42);
25
- const sender = AztecAddress.fromNumber(111);
26
- const receiver = AztecAddress.fromNumber(222);
24
+ const admin = AztecAddress.fromNumberUnsafe(42);
25
+ const sender = AztecAddress.fromNumberUnsafe(111);
26
+ const receiver = AztecAddress.fromNumberUnsafe(222);
27
27
 
28
28
  const token = await setUpToken(tester, tokenArtifact, admin, expectToBeTrue);
29
29
 
@@ -12,13 +12,7 @@ import { CONTRACT_INSTANCE_PUBLISHED_EVENT_TAG } from '@aztec/protocol-contracts
12
12
  import { bufferAsFields } from '@aztec/stdlib/abi';
13
13
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
14
14
  import type { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
15
- import {
16
- FALLBACK_TEARDOWN_DA_GAS_LIMIT,
17
- FALLBACK_TEARDOWN_L2_GAS_LIMIT,
18
- Gas,
19
- GasFees,
20
- GasSettings,
21
- } from '@aztec/stdlib/gas';
15
+ import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
22
16
  import { siloNullifier } from '@aztec/stdlib/hash';
23
17
  import {
24
18
  LogHash,
@@ -42,6 +36,9 @@ import {
42
36
 
43
37
  import { strict as assert } from 'assert';
44
38
 
39
+ const TEARDOWN_DA_GAS_LIMIT = 98_304;
40
+ const TEARDOWN_L2_GAS_LIMIT = 817_500;
41
+
45
42
  export type TestPrivateInsertions = {
46
43
  revertible?: {
47
44
  nullifiers?: Fr[];
@@ -132,9 +129,7 @@ export async function createTxForPublicCalls(
132
129
  }
133
130
 
134
131
  const maxFeesPerGas = feePayer.isZero() ? GasFees.empty() : new GasFees(10, 10);
135
- const teardownGasLimits = teardownCallRequest
136
- ? new Gas(FALLBACK_TEARDOWN_DA_GAS_LIMIT, FALLBACK_TEARDOWN_L2_GAS_LIMIT)
137
- : Gas.empty();
132
+ const teardownGasLimits = teardownCallRequest ? new Gas(TEARDOWN_DA_GAS_LIMIT, TEARDOWN_L2_GAS_LIMIT) : Gas.empty();
138
133
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, maxFeesPerGas, GasFees.empty());
139
134
  const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
140
135
  const header = BlockHeader.empty({ globalVariables: globals });
@@ -260,7 +255,7 @@ export async function addNewContractInstanceToTx(
260
255
  );
261
256
 
262
257
  const contractAddressNullifier = await siloNullifier(
263
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
258
+ AztecAddress.fromNumberUnsafe(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
264
259
  contractInstance.address.toField(),
265
260
  );
266
261
 
@@ -34,6 +34,7 @@ import {
34
34
  import type { NativeWorldStateService } from '@aztec/world-state';
35
35
 
36
36
  import { BaseAvmSimulationTester } from '../avm/testing/base_avm_simulation_tester.js';
37
+ import { AvmSimulatorPool } from '../avm_simulator_pool.js';
37
38
  import { SimpleContractDataSource } from '../fixtures/simple_contract_data_source.js';
38
39
  import { PublicContractsDB } from '../public_db_sources.js';
39
40
  import { PublicTxSimulator } from '../public_tx_simulator/public_tx_simulator.js';
@@ -199,19 +200,28 @@ export class AvmFuzzerSimulator extends BaseAvmSimulationTester {
199
200
  merkleTrees: MerkleTreeWriteOperations,
200
201
  contractDataSource: SimpleContractDataSource,
201
202
  globals: GlobalVariables,
203
+ private avmSimulator: AvmSimulatorPool,
204
+ contractsDB: PublicContractsDB,
205
+ forkId: number,
202
206
  ) {
203
207
  super(contractDataSource, merkleTrees);
204
- const contractsDb = new PublicContractsDB(contractDataSource);
205
208
  // collectPublicInputs and collectCallMetadata are required so the C++ result carries the end
206
209
  // tree snapshots and app-logic return values that the fuzzer bin reports back to the harness.
207
- this.simulator = new PublicTxSimulator(merkleTrees, contractsDb, globals, {
208
- skipFeeEnforcement: false,
209
- collectDebugLogs: false,
210
- collectHints: false,
211
- collectPublicInputs: true,
212
- collectStatistics: false,
213
- collectCallMetadata: true,
214
- });
210
+ this.simulator = new PublicTxSimulator(
211
+ avmSimulator,
212
+ globals,
213
+ contractsDB,
214
+ forkId,
215
+ {
216
+ skipFeeEnforcement: false,
217
+ collectDebugLogs: false,
218
+ collectHints: false,
219
+ collectPublicInputs: true,
220
+ collectStatistics: false,
221
+ collectCallMetadata: true,
222
+ },
223
+ undefined,
224
+ );
215
225
  }
216
226
 
217
227
  /**
@@ -223,7 +233,15 @@ export class AvmFuzzerSimulator extends BaseAvmSimulationTester {
223
233
  ): Promise<AvmFuzzerSimulator> {
224
234
  const contractDataSource = new SimpleContractDataSource();
225
235
  const merkleTrees = await worldStateService.fork();
226
- return new AvmFuzzerSimulator(merkleTrees, contractDataSource, globals);
236
+ const forkId = merkleTrees.getRevision().forkId;
237
+ const avmSimulator = await AvmSimulatorPool.spawn({ wsdbIpcPath: worldStateService.getIpcPath() });
238
+ const contractsDB = new PublicContractsDB(contractDataSource);
239
+ return new AvmFuzzerSimulator(merkleTrees, contractDataSource, globals, avmSimulator, contractsDB, forkId);
240
+ }
241
+
242
+ /** Tear down the AVM simulator pool (AVM processes and CDB server). */
243
+ public async close(): Promise<void> {
244
+ await this.avmSimulator[Symbol.asyncDispose]();
227
245
  }
228
246
 
229
247
  /**
@@ -1,8 +1,12 @@
1
+ export { AvmSimulatorPool, type AvmSimulatorPoolOptions } from './avm_simulator_pool.js';
2
+ export type { PublicContractsDBInterface } from './db_interfaces.js';
1
3
  export { PublicContractsDB } from './public_db_sources.js';
2
4
  export { GuardedMerkleTreeOperations } from './public_processor/guarded_merkle_tree.js';
3
5
  export { PublicProcessor, PublicProcessorFactory } from './public_processor/public_processor.js';
6
+ export type { AvmContractsDBContext, AvmSimulator } from './avm_simulator.js';
4
7
  export {
5
8
  PublicTxSimulator,
9
+ MeasuredPublicTxSimulator,
6
10
  createPublicTxSimulatorForBlockBuilding,
7
11
  DumpingPublicTxSimulator,
8
12
  type PublicTxSimulatorInterface,
@@ -55,7 +55,7 @@ export class PublicContractsDB implements PublicContractsDBInterface {
55
55
  this.log = createLogger('simulator:contracts-data-source', bindings);
56
56
  }
57
57
 
58
- /** Parses raw log data from the C++/NAPI bridge and inserts the resulting contracts into the current checkpoint. */
58
+ /** Parses raw contract deployment data and inserts the resulting contracts into the current checkpoint. */
59
59
  public addContractsFromLogs(contractDeploymentData: ContractDeploymentData): void {
60
60
  const currentState = this.getCurrentState();
61
61