@aztec/simulator 0.0.1-commit.b9865e97 → 0.0.1-commit.be03c316

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 (113) 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 -38
  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/dest/public/test_executor_metrics.d.ts +1 -6
  77. package/dest/public/test_executor_metrics.d.ts.map +1 -1
  78. package/dest/public/test_executor_metrics.js +0 -22
  79. package/package.json +21 -17
  80. package/src/client.ts +0 -2
  81. package/src/private/circuit_recording/circuit_recorder.ts +84 -78
  82. package/src/private/circuit_recording/file_circuit_recorder.ts +38 -48
  83. package/src/private/circuit_recording/simulator_recorder_wrapper.ts +9 -15
  84. package/src/public/avm/testing/base_avm_simulation_tester.ts +1 -1
  85. package/src/public/avm/testing/utils.ts +1 -1
  86. package/src/public/avm_simulator.ts +29 -0
  87. package/src/public/avm_simulator_pool.ts +226 -0
  88. package/src/public/cdb/generated/api_types.ts +457 -0
  89. package/src/public/cdb/generated/server.ts +109 -0
  90. package/src/public/cdb_ipc_server.ts +197 -0
  91. package/src/public/fixtures/amm_test.ts +2 -2
  92. package/src/public/fixtures/bulk_test.ts +2 -2
  93. package/src/public/fixtures/custom_bytecode_tester.ts +2 -2
  94. package/src/public/fixtures/index.ts +1 -0
  95. package/src/public/fixtures/public_processor_test_env.ts +88 -0
  96. package/src/public/fixtures/public_tx_simulation_tester.ts +37 -48
  97. package/src/public/fixtures/token_test.ts +3 -3
  98. package/src/public/fixtures/utils.ts +6 -11
  99. package/src/public/fuzzing/avm_fuzzer_simulator.ts +28 -10
  100. package/src/public/index.ts +4 -0
  101. package/src/public/public_db_sources.ts +1 -1
  102. package/src/public/public_processor/public_processor.ts +22 -15
  103. package/src/public/public_tx_simulator/dumping_public_tx_simulator.ts +13 -29
  104. package/src/public/public_tx_simulator/factories.ts +24 -7
  105. package/src/public/public_tx_simulator/index.ts +5 -2
  106. package/src/public/public_tx_simulator/public_tx_simulator.ts +70 -81
  107. package/src/public/public_tx_simulator/public_tx_simulator_base.ts +8 -6
  108. package/src/public/public_tx_simulator/public_tx_simulator_interface.ts +5 -5
  109. package/src/public/test_executor_metrics.ts +0 -24
  110. package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts +0 -19
  111. package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts.map +0 -1
  112. package/dest/public/public_tx_simulator/contract_provider_for_cpp.js +0 -99
  113. package/src/public/public_tx_simulator/contract_provider_for_cpp.ts +0 -125
@@ -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
 
@@ -50,6 +50,7 @@ import { ForkCheckpoint } from '@aztec/world-state/native';
50
50
 
51
51
  import { AssertionError } from 'assert';
52
52
 
53
+ import type { AvmSimulator } from '../avm_simulator.js';
53
54
  import { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
54
55
  import {
55
56
  type PublicTxSimulatorConfig,
@@ -66,6 +67,7 @@ export class PublicProcessorFactory {
66
67
  private log: Logger;
67
68
  constructor(
68
69
  private contractDataSource: ContractDataSource,
70
+ private avmSimulator: AvmSimulator,
69
71
  private dateProvider: DateProvider = new DateProvider(),
70
72
  protected telemetryClient: TelemetryClient = getTelemetryClient(),
71
73
  bindings?: LoggerBindings,
@@ -74,7 +76,9 @@ export class PublicProcessorFactory {
74
76
  }
75
77
 
76
78
  /**
77
- * Creates a new instance of a PublicProcessor.
79
+ * Creates a new instance of a PublicProcessor. The simulator it drives reads contract data from the fork's
80
+ * contracts DB, scoped by the fork id so AVM requests route to the right state.
81
+ *
78
82
  * @param globalVariables - The global variables for the block being processed.
79
83
  * @param contractsDB - Optional pre-populated contracts DB; a fresh one is constructed if omitted.
80
84
  * @returns A new instance of a PublicProcessor.
@@ -85,8 +89,10 @@ export class PublicProcessorFactory {
85
89
  config: PublicSimulatorConfig,
86
90
  contractsDB: PublicContractsDB = new PublicContractsDB(this.contractDataSource, this.log.getBindings()),
87
91
  ): PublicProcessor {
92
+ const forkId = merkleTree.getRevision().forkId;
93
+
88
94
  const guardedFork = new GuardedMerkleTreeOperations(merkleTree);
89
- const publicTxSimulator = this.createPublicTxSimulator(guardedFork, contractsDB, globalVariables, config);
95
+ const publicTxSimulator = this.createPublicTxSimulator(forkId, globalVariables, contractsDB, config);
90
96
 
91
97
  return new PublicProcessor(
92
98
  globalVariables,
@@ -100,15 +106,16 @@ export class PublicProcessorFactory {
100
106
  }
101
107
 
102
108
  protected createPublicTxSimulator(
103
- merkleTree: MerkleTreeWriteOperations,
104
- contractsDB: PublicContractsDB,
109
+ forkId: number,
105
110
  globalVariables: GlobalVariables,
111
+ contractsDB: PublicContractsDB,
106
112
  config?: Partial<PublicTxSimulatorConfig>,
107
113
  ): PublicTxSimulatorInterface {
108
114
  return new TelemetryPublicTxSimulator(
109
- merkleTree,
110
- contractsDB,
115
+ this.avmSimulator,
111
116
  globalVariables,
117
+ contractsDB,
118
+ forkId,
112
119
  this.telemetryClient,
113
120
  config,
114
121
  this.log.getBindings(),
@@ -130,10 +137,6 @@ class PublicProcessorAbortError extends Error {
130
137
  }
131
138
  }
132
139
 
133
- function isPublicProcessorInterruptError(err: any) {
134
- return err?.name === 'PublicProcessorTimeoutError' || err?.name === 'PublicProcessorAbortError';
135
- }
136
-
137
140
  /**
138
141
  * Converts Txs lifted from the P2P module into ProcessedTx objects by executing
139
142
  * any public function calls in them. Txs with private calls only are unaffected.
@@ -326,11 +329,15 @@ export class PublicProcessor implements Traceable {
326
329
  // Commit the tx-level contracts checkpoint on success
327
330
  this.contractsDB.commitCheckpoint();
328
331
  } catch (err: any) {
329
- if (isPublicProcessorInterruptError(err)) {
330
- const interruptReason = err.name === 'PublicProcessorTimeoutError' ? 'timeout' : 'abort signal';
331
- this.log.warn(`Stopping tx processing due to ${interruptReason}.`);
332
- // The tx may still be executing on a worker thread (C++ via NAPI).
333
- // Signal cancellation AND WAIT for the simulation to actually stop before touching fork checkpoints.
332
+ if (err?.name === 'PublicProcessorTimeoutError' || err?.name === 'PublicProcessorAbortError') {
333
+ this.log.warn(
334
+ `Stopping tx processing due to ${err.name === 'PublicProcessorTimeoutError' ? 'timeout' : 'abort'}.`,
335
+ );
336
+ // We hit the transaction execution deadline or an external abort signal.
337
+ // There may still be a simulation in progress.
338
+ // Signal cancellation AND WAIT for the simulation to actually stop. Cancellation is
339
+ // cooperative: the simulator may be mid slow-operation and won't observe the flag until it
340
+ // completes, and without waiting we'd revert checkpoints while it's still writing to state.
334
341
  await this.publicTxSimulator.cancel?.();
335
342
 
336
343
  // Now stop the guarded fork to prevent any further TS-side access to the world state.
@@ -4,35 +4,36 @@ import {
4
4
  AvmCircuitPublicInputs,
5
5
  AvmExecutionHints,
6
6
  type PublicSimulatorConfig,
7
- PublicTxResult,
7
+ type PublicTxResult,
8
8
  serializeWithMessagePack,
9
9
  } from '@aztec/stdlib/avm';
10
- import type { MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
11
- import type { GlobalVariables, Tx, TxHash } from '@aztec/stdlib/tx';
10
+ import type { GlobalVariables, Tx } from '@aztec/stdlib/tx';
12
11
 
13
12
  import { strict as assert } from 'assert';
14
13
  import { mkdirSync, writeFileSync } from 'fs';
15
14
  import { join } from 'path';
16
15
 
16
+ import type { AvmSimulator } from '../avm_simulator.js';
17
17
  import type { PublicContractsDB } from '../public_db_sources.js';
18
18
  import { PublicTxSimulator } from './public_tx_simulator.js';
19
19
 
20
20
  /**
21
- * A C++ public tx simulator that dumps AVM circuit inputs to disk after simulation.
22
- * Used during nightly CI runs to collect circuit inputs for benchmarking.
21
+ * A {@link PublicTxSimulator} that dumps AVM circuit inputs to disk after simulation.
22
+ * Used during nightly CI runs to collect circuit inputs for AVM proving benchmarks.
23
23
  */
24
24
  export class DumpingPublicTxSimulator extends PublicTxSimulator {
25
25
  private readonly outputDir: string;
26
26
 
27
27
  constructor(
28
- merkleTree: MerkleTreeWriteOperations,
29
- contractsDB: PublicContractsDB,
28
+ avmSimulator: AvmSimulator,
30
29
  globalVariables: GlobalVariables,
30
+ contractsDB: PublicContractsDB,
31
+ forkId: number,
31
32
  config: Partial<PublicSimulatorConfig>,
32
33
  outputDir: string,
33
34
  bindings?: LoggerBindings,
34
35
  ) {
35
- super(merkleTree, contractsDB, globalVariables, config, bindings);
36
+ super(avmSimulator, globalVariables, contractsDB, forkId, config, bindings);
36
37
  assert(config.collectHints === true, 'collectHints must be enabled to dump AVM circuit inputs');
37
38
  assert(config.collectPublicInputs === true, 'collectPublicInputs must be enabled to dump AVM circuit inputs');
38
39
  this.outputDir = outputDir;
@@ -40,44 +41,27 @@ export class DumpingPublicTxSimulator extends PublicTxSimulator {
40
41
 
41
42
  public override async simulate(tx: Tx): Promise<PublicTxResult> {
42
43
  const result = await super.simulate(tx);
43
-
44
- // Dump the circuit inputs after successful simulation
45
- const txHash = this.computeTxHash(tx);
46
- this.dumpAvmCircuitInputs(result, txHash);
47
-
44
+ this.dumpAvmCircuitInputs(result, tx.getTxHash().toString());
48
45
  return result;
49
46
  }
50
47
 
51
- /**
52
- * Dumps AVM circuit inputs to disk.
53
- *
54
- * @param result - The simulation result containing hints and public inputs
55
- * @param txHash - The transaction hash to use in the filename
56
- */
57
- private dumpAvmCircuitInputs(result: PublicTxResult, txHash: TxHash): void {
48
+ private dumpAvmCircuitInputs(result: PublicTxResult, txHash: string): void {
58
49
  try {
59
- // Ensure the output directory exists
60
50
  mkdirSync(this.outputDir, { recursive: true });
61
51
 
62
- // Generate filename using transaction hash
63
- const filename = `avm-circuit-inputs-tx-${txHash.toString()}.bin`;
52
+ const filename = `avm-circuit-inputs-tx-${txHash}.bin`;
64
53
  const filepath = join(this.outputDir, filename);
65
54
 
66
- // Create circuit inputs from the result
67
55
  const hints = result.hints ?? AvmExecutionHints.empty();
68
56
  const publicInputs = result.publicInputs ?? AvmCircuitPublicInputs.empty();
69
57
  const avmCircuitInputs = new AvmCircuitInputs(hints, publicInputs);
70
58
 
71
- // Serialize the circuit inputs using MessagePack
72
59
  const serialized = serializeWithMessagePack(avmCircuitInputs);
73
-
74
- // Write to disk
75
60
  writeFileSync(filepath, serialized);
76
61
 
77
62
  this.log.debug(`Dumped AVM circuit inputs to ${filepath}`);
78
63
  } catch (error) {
79
- // Non-blocking error handling - log but don't interrupt processing
80
- this.log.warn(`Failed to dump AVM circuit inputs for tx ${txHash.toString()}: ${error}`);
64
+ this.log.warn(`Failed to dump AVM circuit inputs for tx ${txHash}: ${error}`);
81
65
  }
82
66
  }
83
67
  }
@@ -1,22 +1,23 @@
1
1
  import type { LoggerBindings } from '@aztec/foundation/log';
2
2
  import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
3
- import type { MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
4
3
  import type { GlobalVariables } from '@aztec/stdlib/tx';
5
4
  import type { TelemetryClient } from '@aztec/telemetry-client';
6
5
 
6
+ import type { AvmSimulator } from '../avm_simulator.js';
7
7
  import type { PublicContractsDB } from '../public_db_sources.js';
8
8
  import { DumpingPublicTxSimulator } from './dumping_public_tx_simulator.js';
9
9
  import { TelemetryPublicTxSimulator } from './public_tx_simulator.js';
10
10
 
11
11
  /**
12
- * Creates a public tx simulator for block building.
13
- * Uses DumpingPublicTxSimulator if DUMP_AVM_INPUTS_TO_DIR env var is set (for CI/testing avm circuit),
12
+ * Creates an IPC-based public tx simulator for block building.
13
+ * Uses DumpingPublicTxSimulator if DUMP_AVM_INPUTS_TO_DIR env var is set (for CI/testing the AVM circuit),
14
14
  * otherwise uses TelemetryPublicTxSimulator (for production).
15
15
  */
16
16
  export function createPublicTxSimulatorForBlockBuilding(
17
- merkleTree: MerkleTreeWriteOperations,
18
- contractsDB: PublicContractsDB,
17
+ avmSimulator: AvmSimulator,
19
18
  globalVariables: GlobalVariables,
19
+ contractsDB: PublicContractsDB,
20
+ forkId: number,
20
21
  telemetryClient: TelemetryClient,
21
22
  bindings?: LoggerBindings,
22
23
  collectDebugLogs = false,
@@ -38,7 +39,23 @@ export function createPublicTxSimulatorForBlockBuilding(
38
39
  collectHints: true,
39
40
  collectPublicInputs: true,
40
41
  };
41
- return new DumpingPublicTxSimulator(merkleTree, contractsDB, globalVariables, dumpingConfig, dumpDir, bindings);
42
+ return new DumpingPublicTxSimulator(
43
+ avmSimulator,
44
+ globalVariables,
45
+ contractsDB,
46
+ forkId,
47
+ dumpingConfig,
48
+ dumpDir,
49
+ bindings,
50
+ );
42
51
  }
43
- return new TelemetryPublicTxSimulator(merkleTree, contractsDB, globalVariables, telemetryClient, config, bindings);
52
+ return new TelemetryPublicTxSimulator(
53
+ avmSimulator,
54
+ globalVariables,
55
+ contractsDB,
56
+ forkId,
57
+ telemetryClient,
58
+ config,
59
+ bindings,
60
+ );
44
61
  }
@@ -1,5 +1,8 @@
1
- export { PublicTxSimulator, TelemetryPublicTxSimulator } from './public_tx_simulator.js';
1
+ export { PublicTxSimulator, MeasuredPublicTxSimulator, TelemetryPublicTxSimulator } from './public_tx_simulator.js';
2
2
  export { DumpingPublicTxSimulator } from './dumping_public_tx_simulator.js';
3
3
  export { createPublicTxSimulatorForBlockBuilding } from './factories.js';
4
- export type { PublicTxSimulatorInterface } from './public_tx_simulator_interface.js';
4
+ export type {
5
+ PublicTxSimulatorInterface,
6
+ MeasuredPublicTxSimulatorInterface,
7
+ } from './public_tx_simulator_interface.js';
5
8
  export type { PublicTxResult, PublicSimulatorConfig as PublicTxSimulatorConfig } from '@aztec/stdlib/avm';
@@ -1,7 +1,5 @@
1
1
  import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
2
2
  import { sleep } from '@aztec/foundation/sleep';
3
- import { type CancellationToken, avmSimulate, cancelSimulation, createCancellationToken } from '@aztec/native';
4
- import { ProtocolContractsList } from '@aztec/protocol-contracts';
5
3
  import {
6
4
  AvmFastSimulationInputs,
7
5
  AvmTxHint,
@@ -10,14 +8,14 @@ import {
10
8
  deserializeFromMessagePack,
11
9
  } from '@aztec/stdlib/avm';
12
10
  import { SimulationError } from '@aztec/stdlib/errors';
13
- import type { MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
14
11
  import type { GlobalVariables, Tx } from '@aztec/stdlib/tx';
12
+ import { WorldStateRevision } from '@aztec/stdlib/world-state';
15
13
  import { type TelemetryClient, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
16
14
 
15
+ import type { AvmContractsDBContext, AvmSimulator } from '../avm_simulator.js';
17
16
  import { ExecutorMetrics } from '../executor_metrics.js';
18
17
  import type { ExecutorMetricsInterface } from '../executor_metrics_interface.js';
19
18
  import type { PublicContractsDB } from '../public_db_sources.js';
20
- import { ContractProviderForCpp } from './contract_provider_for_cpp.js';
21
19
  import { PublicTxSimulatorBase } from './public_tx_simulator_base.js';
22
20
  import type {
23
21
  MeasuredPublicTxSimulatorInterface,
@@ -25,146 +23,136 @@ import type {
25
23
  } from './public_tx_simulator_interface.js';
26
24
 
27
25
  /**
28
- * Simulates a transaction's public portion using the C++ AVM simulator.
29
- * The C++ simulator accesses the world state directly/natively within C++.
30
- * For contract DB accesses, it makes callbacks through NAPI back to the TS PublicContractsDB cache.
26
+ * Simulates a transaction's public portion by running its public calls through an {@link AvmSimulator}.
27
+ * `forkId` selects the fork whose contract data the simulation reads.
31
28
  */
32
29
  export class PublicTxSimulator extends PublicTxSimulatorBase implements PublicTxSimulatorInterface {
33
30
  protected override log: Logger;
34
- /** Current cancellation token for in-flight simulation. */
35
- private cancellationToken?: CancellationToken;
31
+ /** Aborts the in-flight simulation. */
32
+ private abortController?: AbortController;
36
33
  /** Current simulation promise, used to wait for completion after cancellation. */
37
- private simulationPromise?: Promise<Buffer>;
34
+ private simulationPromise?: Promise<PublicTxResult>;
38
35
 
39
36
  constructor(
40
- merkleTree: MerkleTreeWriteOperations,
41
- contractsDB: PublicContractsDB,
37
+ avmSimulator: AvmSimulator,
42
38
  globalVariables: GlobalVariables,
39
+ contractsDB: PublicContractsDB,
40
+ forkId: number,
43
41
  config?: Partial<PublicSimulatorConfig>,
44
42
  bindings?: LoggerBindings,
45
43
  ) {
46
- super(merkleTree, contractsDB, globalVariables, config, undefined, bindings);
44
+ super(avmSimulator, globalVariables, contractsDB, forkId, config, undefined, bindings);
47
45
  this.log = createLogger(`simulator:public_tx_simulator`, bindings);
48
46
  }
49
47
 
50
48
  /**
51
- * Simulate a transaction's public portion using the C++ avvm simulator.
49
+ * Simulate a transaction's public portion.
52
50
  *
53
51
  * @param tx - The transaction to simulate.
54
52
  * @returns The result of the transaction's public execution.
55
53
  */
56
54
  public async simulate(tx: Tx): Promise<PublicTxResult> {
57
- const txHash = this.computeTxHash(tx);
58
- this.log.debug(`C++ simulation of ${tx.publicFunctionCalldata.length} public calls for tx ${txHash}`, {
59
- txHash,
60
- });
61
-
62
- const wsRevision = this.merkleTree.getRevision();
63
- const wsdbIpcPath = this.merkleTree.getIpcPath();
55
+ this.abortController = new AbortController();
56
+ this.simulationPromise = this.doSimulate(tx, this.abortController.signal);
57
+ try {
58
+ return await this.simulationPromise;
59
+ } finally {
60
+ this.abortController = undefined;
61
+ this.simulationPromise = undefined;
62
+ }
63
+ }
64
64
 
65
- this.log.trace(`Running C++ simulation with world state revision ${JSON.stringify(wsRevision)}`);
65
+ protected async doSimulate(tx: Tx, signal: AbortSignal): Promise<PublicTxResult> {
66
+ const txHash = this.computeTxHash(tx);
67
+ this.log.debug(
68
+ `Simulating ${tx.publicFunctionCalldata.length} public calls for tx ${txHash}, forkId=${this.forkId}`,
69
+ { txHash },
70
+ );
66
71
 
67
- // Create the fast simulation inputs
72
+ // Create the fast simulation inputs.
68
73
  const txHint = AvmTxHint.fromTx(tx, this.globalVariables.gasFees);
69
- const protocolContracts = ProtocolContractsList;
70
74
  const fastSimInputs = new AvmFastSimulationInputs(
71
- wsRevision,
75
+ // blockNumber: WorldStateRevision.LATEST sentinel so the WSDB walks the fork's current
76
+ // uncommitted state. Using 0 here makes WSDB treat this as a historical query against
77
+ // the empty genesis tree and miss any in-fork uncommitted leaves (deployed contracts,
78
+ // etc.) from earlier txs in the same block.
79
+ { forkId: this.forkId, blockNumber: WorldStateRevision.LATEST, includeUncommitted: true },
72
80
  this.config,
73
81
  txHint,
74
82
  this.globalVariables,
75
- protocolContracts,
83
+ this.protocolContracts,
76
84
  );
77
85
 
78
- // Create contract provider for callbacks to TypeScript PublicContractsDB from C++
79
- const contractProvider = new ContractProviderForCpp(this.contractsDB, this.globalVariables, this.bindings);
80
-
81
- // Serialize to msgpack and call the C++ simulator
82
86
  this.log.trace(`Serializing fast simulation inputs to msgpack...`);
83
87
  const inputBuffer = fastSimInputs.serializeWithMessagePack();
84
88
 
85
- // Create cancellation token for this simulation
86
- this.cancellationToken = createCancellationToken();
87
-
88
- // Store the promise so cancel() can wait for it
89
- this.log.debug(`Calling C++ simulator for tx ${txHash}`);
90
- this.simulationPromise = avmSimulate(
91
- inputBuffer,
92
- contractProvider,
93
- wsdbIpcPath,
94
- this.log.level,
95
- undefined,
96
- this.cancellationToken,
97
- );
98
-
99
- let resultBuffer: Buffer;
89
+ this.log.debug(`Running AVM simulation for tx ${txHash}`);
90
+ const context: AvmContractsDBContext = {
91
+ contractsDB: this.contractsDB,
92
+ forkId: this.forkId,
93
+ timestamp: this.globalVariables.timestamp,
94
+ };
95
+ let resultBuffer: Uint8Array;
100
96
  try {
101
- resultBuffer = await this.simulationPromise;
97
+ resultBuffer = await this.avmSimulator.simulate(inputBuffer, context, signal);
102
98
  } catch (error: any) {
103
- // Check if this was a cancellation
104
- if (error.message?.includes('Simulation cancelled')) {
105
- throw new SimulationError(`C++ simulation cancelled`, []);
99
+ if (error.message?.includes('cancelled')) {
100
+ throw new SimulationError(`AVM simulation cancelled`, []);
106
101
  }
107
- throw new SimulationError(`C++ simulation failed: ${error.message}`, []);
108
- } finally {
109
- this.cancellationToken = undefined;
110
- this.simulationPromise = undefined;
102
+ throw new SimulationError(`AVM simulation failed: ${error.message}`, []);
111
103
  }
112
104
 
113
- // If we've reached this point, C++ succeeded during simulation,
105
+ this.log.trace(`Deserializing simulation result from buffer (size: ${resultBuffer.length})...`);
106
+ const resultJSON: object = deserializeFromMessagePack(Buffer.from(resultBuffer));
107
+ const result = PublicTxResult.fromPlainObject(resultJSON);
114
108
 
115
- // Deserialize the msgpack result
116
- this.log.trace(`Deserializing C++ from buffer (size: ${resultBuffer.length})...`);
117
- const cppResultJSON: object = deserializeFromMessagePack(resultBuffer);
118
- this.log.trace(`Deserializing C++ result to PublicTxResult...`);
119
- const cppResult = PublicTxResult.fromPlainObject(cppResultJSON);
120
-
121
- this.log.trace(`C++ simulation completed for tx ${txHash}`, {
109
+ this.log.trace(`AVM simulation completed for tx ${txHash}`, {
122
110
  txHash,
123
- reverted: !cppResult.revertCode.isOK(),
124
- cppGasUsed: cppResult.gasUsed.totalGas.l2Gas,
111
+ reverted: !result.revertCode.isOK(),
112
+ l2GasUsed: result.gasUsed.totalGas.l2Gas,
125
113
  });
126
114
 
127
- return cppResult;
115
+ return result;
128
116
  }
129
117
 
130
118
  /**
131
119
  * Cancel the current simulation if one is in progress.
132
- * This signals the C++ simulator to stop at the next opcode or before the next WorldState write.
133
- * Safe to call even if no simulation is in progress.
120
+ * This signals the underlying simulator to stop at the next safe point (between opcodes, before a
121
+ * world-state write). Safe to call even if no simulation is in progress.
134
122
  *
135
123
  * @param waitTimeoutMs - If provided, wait up to this many ms for the simulation to actually stop.
136
- * This is important because C++ might be in the middle of a slow operation
137
- * (e.g., pad_trees) and won't check the cancellation flag until it completes.
124
+ * Cancellation is cooperative: the simulator may be mid slow-operation and
125
+ * won't observe the cancellation until it completes.
138
126
  * Default timeout of 100ms after cancellation.
139
127
  */
140
128
  public async cancel(waitTimeoutMs: number = 100): Promise<void> {
141
- if (this.cancellationToken) {
142
- this.log.debug('Cancelling C++ simulation');
143
- cancelSimulation(this.cancellationToken);
129
+ if (this.abortController) {
130
+ this.log.debug('Cancelling AVM simulation');
131
+ this.abortController.abort();
144
132
  }
145
133
 
146
- // Wait for the simulation to actually complete if not already done
147
134
  if (this.simulationPromise) {
148
- this.log.debug(`Waiting up to ${waitTimeoutMs}ms for C++ simulation to stop`);
135
+ this.log.debug(`Waiting up to ${waitTimeoutMs}ms for AVM simulation to stop`);
149
136
  await Promise.race([
150
137
  this.simulationPromise.catch(() => {}), // Ignore rejection, just wait for completion
151
138
  sleep(waitTimeoutMs),
152
139
  ]);
153
- this.log.debug('C++ simulation stopped or wait timed out');
140
+ this.log.debug('AVM simulation stopped or wait timed out');
154
141
  }
155
142
  }
156
143
  }
157
144
 
158
145
  export class MeasuredPublicTxSimulator extends PublicTxSimulator implements MeasuredPublicTxSimulatorInterface {
159
146
  constructor(
160
- merkleTree: MerkleTreeWriteOperations,
161
- contractsDB: PublicContractsDB,
147
+ avmSimulator: AvmSimulator,
162
148
  globalVariables: GlobalVariables,
149
+ contractsDB: PublicContractsDB,
150
+ forkId: number,
163
151
  protected readonly metrics: ExecutorMetricsInterface,
164
152
  config?: Partial<PublicSimulatorConfig>,
165
153
  bindings?: LoggerBindings,
166
154
  ) {
167
- super(merkleTree, contractsDB, globalVariables, config, bindings);
155
+ super(avmSimulator, globalVariables, contractsDB, forkId, config, bindings);
168
156
  }
169
157
 
170
158
  public override async simulate(tx: Tx, txLabel: string = 'unlabeledTx'): Promise<PublicTxResult> {
@@ -180,22 +168,23 @@ export class MeasuredPublicTxSimulator extends PublicTxSimulator implements Meas
180
168
  }
181
169
 
182
170
  /**
183
- * A C++ public tx simulator that tracks runtime/production metrics with telemetry.
171
+ * A public tx simulator that tracks runtime/production metrics with telemetry.
184
172
  */
185
173
  export class TelemetryPublicTxSimulator extends MeasuredPublicTxSimulator {
186
174
  /* tracer needed by trackSpans */
187
175
  public readonly tracer: Tracer;
188
176
 
189
177
  constructor(
190
- merkleTree: MerkleTreeWriteOperations,
191
- contractsDB: PublicContractsDB,
178
+ avmSimulator: AvmSimulator,
192
179
  globalVariables: GlobalVariables,
180
+ contractsDB: PublicContractsDB,
181
+ forkId: number,
193
182
  telemetryClient: TelemetryClient = getTelemetryClient(),
194
183
  config?: Partial<PublicSimulatorConfig>,
195
184
  bindings?: LoggerBindings,
196
185
  ) {
197
186
  const metrics = new ExecutorMetrics(telemetryClient, 'PublicTxSimulator');
198
- super(merkleTree, contractsDB, globalVariables, metrics, config, bindings);
187
+ super(avmSimulator, globalVariables, contractsDB, forkId, metrics, config, bindings);
199
188
  this.tracer = metrics.tracer;
200
189
  }
201
190
  }