@aztec/simulator 3.0.3 → 4.0.0-devnet.1-patch.0

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 (246) hide show
  1. package/README.md +2 -0
  2. package/dest/common/errors.d.ts +7 -1
  3. package/dest/common/errors.d.ts.map +1 -1
  4. package/dest/private/acvm/acvm.d.ts +4 -2
  5. package/dest/private/acvm/acvm.d.ts.map +1 -1
  6. package/dest/private/acvm/acvm.js +4 -3
  7. package/dest/private/acvm_native.d.ts +5 -3
  8. package/dest/private/acvm_native.d.ts.map +1 -1
  9. package/dest/private/acvm_native.js +8 -6
  10. package/dest/private/acvm_wasm.d.ts +4 -3
  11. package/dest/private/acvm_wasm.d.ts.map +1 -1
  12. package/dest/private/acvm_wasm.js +4 -4
  13. package/dest/private/circuit_recording/circuit_recorder.d.ts +4 -3
  14. package/dest/private/circuit_recording/circuit_recorder.d.ts.map +1 -1
  15. package/dest/private/circuit_recording/circuit_recorder.js +20 -17
  16. package/dest/private/circuit_recording/file_circuit_recorder.d.ts +3 -2
  17. package/dest/private/circuit_recording/file_circuit_recorder.d.ts.map +1 -1
  18. package/dest/private/circuit_recording/file_circuit_recorder.js +2 -2
  19. package/dest/private/circuit_recording/memory_circuit_recorder.d.ts +7 -2
  20. package/dest/private/circuit_recording/memory_circuit_recorder.d.ts.map +1 -1
  21. package/dest/private/circuit_recording/memory_circuit_recorder.js +4 -4
  22. package/dest/private/factory.d.ts +3 -3
  23. package/dest/private/factory.d.ts.map +1 -1
  24. package/dest/private/factory.js +7 -4
  25. package/dest/public/avm/avm_context.d.ts +3 -3
  26. package/dest/public/avm/avm_context.d.ts.map +1 -1
  27. package/dest/public/avm/avm_contract_call_result.d.ts +6 -6
  28. package/dest/public/avm/avm_contract_call_result.d.ts.map +1 -1
  29. package/dest/public/avm/avm_contract_call_result.js +3 -3
  30. package/dest/public/avm/avm_execution_environment.d.ts +6 -5
  31. package/dest/public/avm/avm_execution_environment.d.ts.map +1 -1
  32. package/dest/public/avm/avm_machine_state.d.ts +6 -5
  33. package/dest/public/avm/avm_machine_state.d.ts.map +1 -1
  34. package/dest/public/avm/avm_machine_state.js +3 -2
  35. package/dest/public/avm/avm_memory_types.d.ts +1 -1
  36. package/dest/public/avm/avm_memory_types.d.ts.map +1 -1
  37. package/dest/public/avm/avm_memory_types.js +3 -0
  38. package/dest/public/avm/avm_simulator.d.ts +3 -2
  39. package/dest/public/avm/avm_simulator.d.ts.map +1 -1
  40. package/dest/public/avm/avm_simulator.js +5 -4
  41. package/dest/public/avm/calldata.d.ts +51 -0
  42. package/dest/public/avm/calldata.d.ts.map +1 -0
  43. package/dest/public/avm/calldata.js +63 -0
  44. package/dest/public/avm/fixtures/account_proof_fetcher.d.ts +2 -0
  45. package/dest/public/avm/fixtures/account_proof_fetcher.d.ts.map +1 -0
  46. package/dest/public/avm/fixtures/account_proof_fetcher.js +152 -0
  47. package/dest/public/avm/fixtures/avm_simulation_tester.d.ts +1 -1
  48. package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -1
  49. package/dest/public/avm/fixtures/avm_simulation_tester.js +3 -2
  50. package/dest/public/avm/fixtures/initializers.d.ts +1 -1
  51. package/dest/public/avm/fixtures/initializers.d.ts.map +1 -1
  52. package/dest/public/avm/fixtures/initializers.js +2 -1
  53. package/dest/public/avm/opcodes/accrued_substate.d.ts +16 -17
  54. package/dest/public/avm/opcodes/accrued_substate.d.ts.map +1 -1
  55. package/dest/public/avm/opcodes/accrued_substate.js +39 -39
  56. package/dest/public/avm/opcodes/arithmetic.d.ts +8 -8
  57. package/dest/public/avm/opcodes/arithmetic.d.ts.map +1 -1
  58. package/dest/public/avm/opcodes/arithmetic.js +1 -1
  59. package/dest/public/avm/opcodes/bitwise.d.ts +7 -7
  60. package/dest/public/avm/opcodes/bitwise.d.ts.map +1 -1
  61. package/dest/public/avm/opcodes/bitwise.js +5 -5
  62. package/dest/public/avm/opcodes/comparators.d.ts +4 -4
  63. package/dest/public/avm/opcodes/comparators.d.ts.map +1 -1
  64. package/dest/public/avm/opcodes/comparators.js +1 -1
  65. package/dest/public/avm/opcodes/contract.d.ts +3 -3
  66. package/dest/public/avm/opcodes/contract.d.ts.map +1 -1
  67. package/dest/public/avm/opcodes/contract.js +8 -8
  68. package/dest/public/avm/opcodes/control_flow.d.ts +3 -3
  69. package/dest/public/avm/opcodes/control_flow.d.ts.map +1 -1
  70. package/dest/public/avm/opcodes/control_flow.js +4 -4
  71. package/dest/public/avm/opcodes/conversion.d.ts +3 -3
  72. package/dest/public/avm/opcodes/conversion.d.ts.map +1 -1
  73. package/dest/public/avm/opcodes/conversion.js +4 -4
  74. package/dest/public/avm/opcodes/ec_add.d.ts +4 -4
  75. package/dest/public/avm/opcodes/ec_add.d.ts.map +1 -1
  76. package/dest/public/avm/opcodes/ec_add.js +15 -6
  77. package/dest/public/avm/opcodes/environment_getters.d.ts +5 -5
  78. package/dest/public/avm/opcodes/environment_getters.d.ts.map +1 -1
  79. package/dest/public/avm/opcodes/environment_getters.js +6 -6
  80. package/dest/public/avm/opcodes/external_calls.d.ts +9 -9
  81. package/dest/public/avm/opcodes/external_calls.d.ts.map +1 -1
  82. package/dest/public/avm/opcodes/external_calls.js +23 -22
  83. package/dest/public/avm/opcodes/hashing.d.ts +8 -8
  84. package/dest/public/avm/opcodes/hashing.d.ts.map +1 -1
  85. package/dest/public/avm/opcodes/hashing.js +18 -15
  86. package/dest/public/avm/opcodes/instruction_impl.d.ts +4 -4
  87. package/dest/public/avm/opcodes/instruction_impl.d.ts.map +1 -1
  88. package/dest/public/avm/opcodes/instruction_impl.js +4 -4
  89. package/dest/public/avm/opcodes/memory.d.ts +14 -14
  90. package/dest/public/avm/opcodes/memory.d.ts.map +1 -1
  91. package/dest/public/avm/opcodes/memory.js +25 -25
  92. package/dest/public/avm/opcodes/misc.d.ts +3 -3
  93. package/dest/public/avm/opcodes/misc.d.ts.map +1 -1
  94. package/dest/public/avm/opcodes/misc.js +4 -4
  95. package/dest/public/avm/opcodes/storage.d.ts +16 -15
  96. package/dest/public/avm/opcodes/storage.d.ts.map +1 -1
  97. package/dest/public/avm/opcodes/storage.js +34 -24
  98. package/dest/public/debug_fn_name.d.ts +4 -4
  99. package/dest/public/debug_fn_name.d.ts.map +1 -1
  100. package/dest/public/debug_fn_name.js +14 -5
  101. package/dest/public/executor_metrics.d.ts +1 -1
  102. package/dest/public/executor_metrics.d.ts.map +1 -1
  103. package/dest/public/executor_metrics.js +12 -33
  104. package/dest/public/fixtures/bulk_test.d.ts +3 -3
  105. package/dest/public/fixtures/bulk_test.d.ts.map +1 -1
  106. package/dest/public/fixtures/bulk_test.js +4 -68
  107. package/dest/public/fixtures/custom_bytecode_tester.d.ts +28 -6
  108. package/dest/public/fixtures/custom_bytecode_tester.d.ts.map +1 -1
  109. package/dest/public/fixtures/custom_bytecode_tester.js +36 -12
  110. package/dest/public/fixtures/custom_bytecode_tests.d.ts +11 -9
  111. package/dest/public/fixtures/custom_bytecode_tests.d.ts.map +1 -1
  112. package/dest/public/fixtures/custom_bytecode_tests.js +66 -22
  113. package/dest/public/fixtures/index.d.ts +4 -2
  114. package/dest/public/fixtures/index.d.ts.map +1 -1
  115. package/dest/public/fixtures/index.js +3 -1
  116. package/dest/public/fixtures/minimal_public_tx.d.ts +2 -7
  117. package/dest/public/fixtures/minimal_public_tx.d.ts.map +1 -1
  118. package/dest/public/fixtures/minimal_public_tx.js +4 -14
  119. package/dest/public/fixtures/opcode_spammer.d.ts +122 -0
  120. package/dest/public/fixtures/opcode_spammer.d.ts.map +1 -0
  121. package/dest/public/fixtures/opcode_spammer.js +1653 -0
  122. package/dest/public/fixtures/public_tx_simulation_tester.d.ts +15 -2
  123. package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
  124. package/dest/public/fixtures/public_tx_simulation_tester.js +34 -7
  125. package/dest/public/fixtures/utils.d.ts +1 -1
  126. package/dest/public/fixtures/utils.d.ts.map +1 -1
  127. package/dest/public/fixtures/utils.js +3 -2
  128. package/dest/public/fuzzing/avm_fuzzer_simulator.d.ts +21 -7
  129. package/dest/public/fuzzing/avm_fuzzer_simulator.d.ts.map +1 -1
  130. package/dest/public/fuzzing/avm_fuzzer_simulator.js +46 -11
  131. package/dest/public/fuzzing/avm_simulator_bin.js +47 -13
  132. package/dest/public/hinting_db_sources.d.ts +2 -1
  133. package/dest/public/hinting_db_sources.d.ts.map +1 -1
  134. package/dest/public/hinting_db_sources.js +5 -0
  135. package/dest/public/public_db_sources.d.ts +4 -3
  136. package/dest/public/public_db_sources.d.ts.map +1 -1
  137. package/dest/public/public_db_sources.js +4 -4
  138. package/dest/public/public_processor/guarded_merkle_tree.d.ts +2 -1
  139. package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -1
  140. package/dest/public/public_processor/guarded_merkle_tree.js +5 -0
  141. package/dest/public/public_processor/public_processor.d.ts +6 -4
  142. package/dest/public/public_processor/public_processor.d.ts.map +1 -1
  143. package/dest/public/public_processor/public_processor.js +428 -34
  144. package/dest/public/public_processor/public_processor_metrics.d.ts +2 -2
  145. package/dest/public/public_processor/public_processor_metrics.d.ts.map +1 -1
  146. package/dest/public/public_processor/public_processor_metrics.js +28 -45
  147. package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts +3 -2
  148. package/dest/public/public_tx_simulator/contract_provider_for_cpp.d.ts.map +1 -1
  149. package/dest/public/public_tx_simulator/contract_provider_for_cpp.js +17 -13
  150. package/dest/public/public_tx_simulator/cpp_public_tx_simulator.d.ts +20 -5
  151. package/dest/public/public_tx_simulator/cpp_public_tx_simulator.d.ts.map +1 -1
  152. package/dest/public/public_tx_simulator/cpp_public_tx_simulator.js +50 -11
  153. package/dest/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.d.ts +4 -4
  154. package/dest/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.d.ts.map +1 -1
  155. package/dest/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.js +5 -5
  156. package/dest/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.d.ts +4 -4
  157. package/dest/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.d.ts.map +1 -1
  158. package/dest/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.js +8 -7
  159. package/dest/public/public_tx_simulator/dumping_cpp_public_tx_simulator.d.ts +3 -2
  160. package/dest/public/public_tx_simulator/dumping_cpp_public_tx_simulator.d.ts.map +1 -1
  161. package/dest/public/public_tx_simulator/dumping_cpp_public_tx_simulator.js +2 -2
  162. package/dest/public/public_tx_simulator/factories.d.ts +3 -2
  163. package/dest/public/public_tx_simulator/factories.d.ts.map +1 -1
  164. package/dest/public/public_tx_simulator/factories.js +3 -3
  165. package/dest/public/public_tx_simulator/measured_public_tx_simulator.d.ts +1 -1
  166. package/dest/public/public_tx_simulator/public_tx_context.d.ts +4 -3
  167. package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
  168. package/dest/public/public_tx_simulator/public_tx_context.js +8 -8
  169. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +6 -4
  170. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
  171. package/dest/public/public_tx_simulator/public_tx_simulator.js +12 -7
  172. package/dest/public/public_tx_simulator/public_tx_simulator_interface.d.ts +24 -1
  173. package/dest/public/public_tx_simulator/public_tx_simulator_interface.d.ts.map +1 -1
  174. package/dest/public/public_tx_simulator/telemetry_public_tx_simulator.js +395 -19
  175. package/dest/public/side_effect_trace.d.ts +5 -4
  176. package/dest/public/side_effect_trace.d.ts.map +1 -1
  177. package/dest/public/side_effect_trace.js +3 -3
  178. package/dest/public/state_manager/state_manager.d.ts +10 -4
  179. package/dest/public/state_manager/state_manager.d.ts.map +1 -1
  180. package/dest/public/state_manager/state_manager.js +14 -7
  181. package/dest/public/test_executor_metrics.d.ts +3 -2
  182. package/dest/public/test_executor_metrics.d.ts.map +1 -1
  183. package/dest/public/test_executor_metrics.js +2 -2
  184. package/package.json +17 -17
  185. package/src/private/acvm/acvm.ts +4 -3
  186. package/src/private/acvm_native.ts +11 -5
  187. package/src/private/acvm_wasm.ts +7 -3
  188. package/src/private/circuit_recording/circuit_recorder.ts +21 -18
  189. package/src/private/circuit_recording/file_circuit_recorder.ts +7 -2
  190. package/src/private/circuit_recording/memory_circuit_recorder.ts +6 -4
  191. package/src/private/factory.ts +7 -4
  192. package/src/public/avm/avm_context.ts +2 -2
  193. package/src/public/avm/avm_contract_call_result.ts +8 -6
  194. package/src/public/avm/avm_execution_environment.ts +9 -4
  195. package/src/public/avm/avm_machine_state.ts +6 -5
  196. package/src/public/avm/avm_memory_types.ts +4 -0
  197. package/src/public/avm/avm_simulator.ts +8 -5
  198. package/src/public/avm/calldata.ts +100 -0
  199. package/src/public/avm/fixtures/account_proof.json +553 -0
  200. package/src/public/avm/fixtures/account_proof_fetcher.ts +166 -0
  201. package/src/public/avm/fixtures/avm_simulation_tester.ts +8 -2
  202. package/src/public/avm/fixtures/initializers.ts +2 -1
  203. package/src/public/avm/opcodes/accrued_substate.ts +28 -30
  204. package/src/public/avm/opcodes/arithmetic.ts +1 -1
  205. package/src/public/avm/opcodes/bitwise.ts +3 -3
  206. package/src/public/avm/opcodes/comparators.ts +1 -1
  207. package/src/public/avm/opcodes/contract.ts +4 -7
  208. package/src/public/avm/opcodes/control_flow.ts +2 -2
  209. package/src/public/avm/opcodes/conversion.ts +3 -3
  210. package/src/public/avm/opcodes/ec_add.ts +13 -4
  211. package/src/public/avm/opcodes/environment_getters.ts +7 -7
  212. package/src/public/avm/opcodes/external_calls.ts +17 -15
  213. package/src/public/avm/opcodes/hashing.ts +13 -9
  214. package/src/public/avm/opcodes/instruction_impl.ts +2 -2
  215. package/src/public/avm/opcodes/memory.ts +19 -19
  216. package/src/public/avm/opcodes/misc.ts +2 -2
  217. package/src/public/avm/opcodes/storage.ts +30 -22
  218. package/src/public/debug_fn_name.ts +17 -8
  219. package/src/public/executor_metrics.ts +9 -33
  220. package/src/public/fixtures/bulk_test.ts +8 -8
  221. package/src/public/fixtures/custom_bytecode_tester.ts +53 -19
  222. package/src/public/fixtures/custom_bytecode_tests.ts +91 -22
  223. package/src/public/fixtures/index.ts +7 -1
  224. package/src/public/fixtures/minimal_public_tx.ts +5 -14
  225. package/src/public/fixtures/opcode_spammer.ts +1721 -0
  226. package/src/public/fixtures/public_tx_simulation_tester.ts +38 -5
  227. package/src/public/fixtures/utils.ts +1 -2
  228. package/src/public/fuzzing/avm_fuzzer_simulator.ts +67 -12
  229. package/src/public/fuzzing/avm_simulator_bin.ts +64 -10
  230. package/src/public/hinting_db_sources.ts +4 -0
  231. package/src/public/public_db_sources.ts +15 -5
  232. package/src/public/public_processor/guarded_merkle_tree.ts +4 -0
  233. package/src/public/public_processor/public_processor.ts +41 -16
  234. package/src/public/public_processor/public_processor_metrics.ts +16 -44
  235. package/src/public/public_tx_simulator/contract_provider_for_cpp.ts +22 -14
  236. package/src/public/public_tx_simulator/cpp_public_tx_simulator.ts +65 -9
  237. package/src/public/public_tx_simulator/cpp_public_tx_simulator_with_hinted_dbs.ts +6 -4
  238. package/src/public/public_tx_simulator/cpp_vs_ts_public_tx_simulator.ts +9 -6
  239. package/src/public/public_tx_simulator/dumping_cpp_public_tx_simulator.ts +3 -1
  240. package/src/public/public_tx_simulator/factories.ts +4 -2
  241. package/src/public/public_tx_simulator/public_tx_context.ts +13 -6
  242. package/src/public/public_tx_simulator/public_tx_simulator.ts +18 -7
  243. package/src/public/public_tx_simulator/public_tx_simulator_interface.ts +23 -0
  244. package/src/public/side_effect_trace.ts +5 -2
  245. package/src/public/state_manager/state_manager.ts +29 -20
  246. package/src/public/test_executor_metrics.ts +3 -3
@@ -31,7 +31,7 @@ const DEFAULT_GAS_FEES = new GasFees(2, 3);
31
31
  export type TestEnqueuedCall = {
32
32
  sender?: AztecAddress;
33
33
  address: AztecAddress;
34
- fnName: string;
34
+ fnName?: string;
35
35
  args: any[];
36
36
  isStaticCall?: boolean;
37
37
  contractArtifact?: ContractArtifact;
@@ -225,6 +225,25 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
225
225
  this.metrics.prettyPrint();
226
226
  }
227
227
 
228
+ /**
229
+ * Cancel the current simulation if one is in progress.
230
+ * This signals the underlying simulator (e.g., C++) to stop at the next safe point.
231
+ * Safe to call even if no simulation is in progress.
232
+ *
233
+ * @param waitTimeoutMs - If provided, wait up to this many ms for the simulation to actually stop.
234
+ */
235
+ public async cancel(waitTimeoutMs?: number): Promise<void> {
236
+ await this.simulator.cancel?.(waitTimeoutMs);
237
+ }
238
+
239
+ /**
240
+ * Get the underlying simulator for advanced test scenarios.
241
+ * Use this when you need direct control over simulation (e.g., for testing cancellation).
242
+ */
243
+ public getSimulator(): MeasuredPublicTxSimulatorInterface {
244
+ return this.simulator;
245
+ }
246
+
228
247
  async #createPubicCallRequestForCall(
229
248
  call: TestEnqueuedCall,
230
249
  sender: AztecAddress,
@@ -235,10 +254,24 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
235
254
  throw new Error(`Contract artifact not found for address: ${address}`);
236
255
  }
237
256
 
238
- const fnSelector = await getFunctionSelector(call.fnName, contractArtifact);
239
- const fnAbi = getContractFunctionAbi(call.fnName, contractArtifact)!;
240
- const encodedArgs = encodeArguments(fnAbi, call.args);
241
- const calldata = [fnSelector.toField(), ...encodedArgs];
257
+ let calldata: Fr[] = [];
258
+ if (!call.fnName) {
259
+ this.logger.debug(
260
+ `No function name specified for call to contract ${call.address.toString()}. Assuming this is a custom bytecode with no public_dispatch function.`,
261
+ );
262
+ this.logger.debug(`Not using ABI to encode arguments. Not prepending fn selector to calldata.`);
263
+ try {
264
+ calldata = call.args.map(arg => new Fr(arg));
265
+ } catch (error) {
266
+ this.logger.warn(`Tried assuming that all arguments are Field-like. Failed. Error: ${error}`);
267
+ throw error;
268
+ }
269
+ } else {
270
+ const fnSelector = await getFunctionSelector(call.fnName, contractArtifact);
271
+ const fnAbi = getContractFunctionAbi(call.fnName, contractArtifact)!;
272
+ const encodedArgs = encodeArguments(fnAbi, call.args);
273
+ calldata = [fnSelector.toField(), ...encodedArgs];
274
+ }
242
275
  const isStaticCall = call.isStaticCall ?? false;
243
276
  const request = await PublicCallRequest.fromCalldata(sender, address, isStaticCall, calldata);
244
277
 
@@ -132,8 +132,7 @@ export async function createTxForPublicCalls(
132
132
  : Gas.empty();
133
133
  const gasSettings = new GasSettings(gasLimits, teardownGasLimits, maxFeesPerGas, GasFees.empty());
134
134
  const txContext = new TxContext(Fr.zero(), Fr.zero(), gasSettings);
135
- const header = BlockHeader.empty();
136
- header.globalVariables = globals;
135
+ const header = BlockHeader.empty({ globalVariables: globals });
137
136
  const constantData = new TxConstantData(header, txContext, Fr.zero(), Fr.zero());
138
137
  const includeByTimestamp = 0n; // Not used in the simulator.
139
138
 
@@ -4,6 +4,7 @@ import {
4
4
  MAX_NOTE_HASHES_PER_TX,
5
5
  MAX_NULLIFIERS_PER_TX,
6
6
  MAX_PRIVATE_LOGS_PER_TX,
7
+ MAX_PROTOCOL_CONTRACTS,
7
8
  } from '@aztec/constants';
8
9
  import { padArrayEnd } from '@aztec/foundation/collection';
9
10
  import { Fr } from '@aztec/foundation/curves/bn254';
@@ -19,8 +20,17 @@ import {
19
20
  import { PrivateLog } from '@aztec/stdlib/logs';
20
21
  import { ScopedL2ToL1Message } from '@aztec/stdlib/messaging';
21
22
  import { ChonkProof } from '@aztec/stdlib/proofs';
22
- import type { MerkleTreeWriteOperations } from '@aztec/stdlib/trees';
23
- import { BlockHeader, GlobalVariables, HashedValues, Tx, TxConstantData, TxContext, TxHash } from '@aztec/stdlib/tx';
23
+ import { MerkleTreeId, type MerkleTreeWriteOperations, PublicDataTreeLeaf } from '@aztec/stdlib/trees';
24
+ import {
25
+ BlockHeader,
26
+ GlobalVariables,
27
+ HashedValues,
28
+ ProtocolContracts,
29
+ Tx,
30
+ TxConstantData,
31
+ TxContext,
32
+ TxHash,
33
+ } from '@aztec/stdlib/tx';
24
34
  import type { NativeWorldStateService } from '@aztec/world-state';
25
35
 
26
36
  import { BaseAvmSimulationTester } from '../avm/fixtures/base_avm_simulation_tester.js';
@@ -40,6 +50,9 @@ export class FuzzerSimulationRequest {
40
50
  public readonly globals: GlobalVariables,
41
51
  public readonly contractClasses: any[], // Raw, processed by addContractClassFromCpp
42
52
  public readonly contractInstances: [any, any][], // Raw pairs [address, instance]
53
+ public readonly publicDataWrites: any[], // Raw public data tree writes to apply before simulation
54
+ public readonly noteHashes: any[], // Raw note hashes to apply before simulation
55
+ public readonly protocolContracts: ProtocolContracts, // Protocol contracts mapping from C++
43
56
  ) {}
44
57
 
45
58
  static fromPlainObject(obj: any): FuzzerSimulationRequest {
@@ -53,6 +66,9 @@ export class FuzzerSimulationRequest {
53
66
  GlobalVariables.fromPlainObject(obj.globals),
54
67
  obj.contractClasses,
55
68
  obj.contractInstances,
69
+ obj.publicDataWrites ?? [],
70
+ obj.noteHashes ?? [],
71
+ ProtocolContracts.fromPlainObject(obj.protocolContracts),
56
72
  );
57
73
  }
58
74
  }
@@ -181,16 +197,23 @@ export class AvmFuzzerSimulator extends BaseAvmSimulationTester {
181
197
  merkleTrees: MerkleTreeWriteOperations,
182
198
  contractDataSource: SimpleContractDataSource,
183
199
  globals: GlobalVariables,
200
+ protocolContracts: ProtocolContracts,
184
201
  ) {
185
202
  super(contractDataSource, merkleTrees);
186
203
  const contractsDb = new PublicContractsDB(contractDataSource);
187
- this.simulator = new PublicTxSimulator(merkleTrees, contractsDb, globals, {
188
- skipFeeEnforcement: true,
189
- collectDebugLogs: false,
190
- collectHints: false,
191
- collectStatistics: false,
192
- collectCallMetadata: false,
193
- });
204
+ this.simulator = new PublicTxSimulator(
205
+ merkleTrees,
206
+ contractsDb,
207
+ globals,
208
+ {
209
+ skipFeeEnforcement: false,
210
+ collectDebugLogs: false,
211
+ collectHints: false,
212
+ collectStatistics: false,
213
+ collectCallMetadata: false,
214
+ },
215
+ protocolContracts,
216
+ );
194
217
  }
195
218
 
196
219
  /**
@@ -199,16 +222,24 @@ export class AvmFuzzerSimulator extends BaseAvmSimulationTester {
199
222
  public static async create(
200
223
  worldStateService: NativeWorldStateService,
201
224
  globals: GlobalVariables,
225
+ protocolContracts: ProtocolContracts,
202
226
  ): Promise<AvmFuzzerSimulator> {
203
227
  const contractDataSource = new SimpleContractDataSource();
204
228
  const merkleTrees = await worldStateService.fork();
205
- return new AvmFuzzerSimulator(merkleTrees, contractDataSource, globals);
229
+ return new AvmFuzzerSimulator(merkleTrees, contractDataSource, globals, protocolContracts);
206
230
  }
207
231
 
208
232
  /**
209
233
  * Simulate a transaction from a C++ AvmTxHint.
210
234
  */
211
235
  public async simulate(txHint: AvmTxHint): Promise<PublicTxResult> {
236
+ // Compute fee from gas limits and max fees per gas (upper bound on fee)
237
+ const totalFee =
238
+ BigInt(txHint.gasSettings.gasLimits.daGas) * txHint.gasSettings.maxFeesPerGas.feePerDaGas +
239
+ BigInt(txHint.gasSettings.gasLimits.l2Gas) * txHint.gasSettings.maxFeesPerGas.feePerL2Gas;
240
+
241
+ await this.setFeePayerBalance(txHint.feePayer, new Fr(totalFee));
242
+
212
243
  const tx = await createTxFromHint(txHint);
213
244
  return await this.simulator.simulate(tx);
214
245
  }
@@ -223,11 +254,35 @@ export class AvmFuzzerSimulator extends BaseAvmSimulationTester {
223
254
 
224
255
  /**
225
256
  * Add a contract instance from C++ raw msgpack data.
226
- * This also inserts the contract address nullifier into the nullifier tree.
257
+ * This also inserts the contract address nullifier into the nullifier tree,
258
+ * unless the address is a protocol canonical address (1-11).
227
259
  */
228
260
  public async addContractInstanceFromCpp(rawAddress: any, rawInstance: any): Promise<void> {
229
261
  const address = AztecAddress.fromPlainObject(rawAddress);
230
262
  const instance = contractInstanceWithAddressFromPlainObject(address, rawInstance);
231
- await this.addContractInstance(instance);
263
+ // Protocol canonical addresses (1-11) should not have nullifiers inserted
264
+ const isProtocolCanonicalAddress = address.toBigInt() <= MAX_PROTOCOL_CONTRACTS && address.toBigInt() >= 1n;
265
+ await this.addContractInstance(instance, /* skipNullifierInsertion */ isProtocolCanonicalAddress);
266
+ }
267
+
268
+ /**
269
+ * Apply public data tree writes from C++ raw msgpack data.
270
+ * This is used to pre-populate the public data tree before simulation (e.g., for bytecode upgrades).
271
+ */
272
+ public async applyPublicDataWrites(rawWrites: any[]): Promise<void> {
273
+ for (const rawWrite of rawWrites) {
274
+ const leaf = PublicDataTreeLeaf.fromPlainObject(rawWrite);
275
+ await this.merkleTrees.sequentialInsert(MerkleTreeId.PUBLIC_DATA_TREE, [leaf.toBuffer()]);
276
+ }
277
+ }
278
+
279
+ /**
280
+ * Apply note hashes from C++ raw msgpack data.
281
+ * This is used to pre-populate the note hash tree before simulation.
282
+ */
283
+ public async applyNoteHashes(rawNoteHashes: any[]): Promise<void> {
284
+ const paddingLeaves = MAX_NOTE_HASHES_PER_TX - (rawNoteHashes.length % MAX_NOTE_HASHES_PER_TX);
285
+ const paddedNoteHashes = [...rawNoteHashes, ...Array(paddingLeaves).fill(Fr.ZERO)];
286
+ await this.merkleTrees.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, paddedNoteHashes);
232
287
  }
233
288
  }
@@ -3,17 +3,30 @@ import { EthAddress } from '@aztec/foundation/eth-address';
3
3
  import {
4
4
  AvmCircuitPublicInputs,
5
5
  type AvmTxHint,
6
+ PublicTxEffect,
6
7
  deserializeFromMessagePack,
7
8
  serializeWithMessagePack,
8
9
  } from '@aztec/stdlib/avm';
9
- import { GlobalVariables, TreeSnapshots } from '@aztec/stdlib/tx';
10
+ import { GlobalVariables, ProtocolContracts, TreeSnapshots } from '@aztec/stdlib/tx';
10
11
  import { NativeWorldStateService } from '@aztec/world-state';
11
12
 
12
- import { writeSync } from 'fs';
13
13
  import { createInterface } from 'readline';
14
14
 
15
15
  import { AvmFuzzerSimulator, FuzzerSimulationRequest } from './avm_fuzzer_simulator.js';
16
16
 
17
+ /** Write data to stdout, letting Node handle buffering. */
18
+ function writeOutput(data: string): Promise<void> {
19
+ return new Promise<void>((resolve, reject) => {
20
+ process.stdout.write(data, err => {
21
+ if (err) {
22
+ reject(err);
23
+ } else {
24
+ resolve();
25
+ }
26
+ });
27
+ });
28
+ }
29
+
17
30
  // This cache holds opened world states to avoid reopening them for each invocation.
18
31
  // It's a map so that in the future we could support multiple world states (if we had multiple fuzzers).
19
32
  const worldStateCache = new Map<string, NativeWorldStateService>();
@@ -43,12 +56,23 @@ async function simulateWithFuzzer(
43
56
  globals: GlobalVariables,
44
57
  rawContractClasses: any[], // Replace these when we are moving contract classes to TS
45
58
  rawContractInstances: [any, any][], // Replace these when we are moving contract instances to TS
46
- ): Promise<{ reverted: boolean; output: Fr[]; revertReason?: string; publicInputs: AvmCircuitPublicInputs }> {
59
+ rawPublicDataWrites: any[], // Public data tree writes to apply before simulation
60
+ rawNoteHashes: any[], // Note hashes to apply before simulation
61
+ protocolContracts: ProtocolContracts, // Protocol contracts mapping from C++
62
+ ): Promise<{
63
+ reverted: boolean;
64
+ output: Fr[];
65
+ revertReason?: string;
66
+ publicInputs: AvmCircuitPublicInputs;
67
+ publicTxEffect: PublicTxEffect;
68
+ }> {
47
69
  const worldStateService = await openExistingWorldState(dataDir, mapSizeKb);
48
70
 
49
- const simulator = await AvmFuzzerSimulator.create(worldStateService, globals);
71
+ const simulator = await AvmFuzzerSimulator.create(worldStateService, globals, protocolContracts);
72
+
73
+ await simulator.applyNoteHashes(rawNoteHashes);
50
74
 
51
- // Register contract classes from C++
75
+ // Register contract classes from C++ (must happen before public data writes to match C++ order)
52
76
  for (const rawClass of rawContractClasses) {
53
77
  await simulator.addContractClassFromCpp(rawClass);
54
78
  }
@@ -58,6 +82,10 @@ async function simulateWithFuzzer(
58
82
  await simulator.addContractInstanceFromCpp(rawAddress, rawInstance);
59
83
  }
60
84
 
85
+ // Apply public data writes after contract registration (e.g., for bytecode upgrades)
86
+ // This must happen last to match C++ setup_fuzzer_state ordering
87
+ await simulator.applyPublicDataWrites(rawPublicDataWrites);
88
+
61
89
  const result = await simulator.simulate(txHint);
62
90
 
63
91
  const output = result
@@ -69,6 +97,7 @@ async function simulateWithFuzzer(
69
97
  output,
70
98
  revertReason: result.findRevertReason()?.message,
71
99
  publicInputs: result.publicInputs!,
100
+ publicTxEffect: result.publicTxEffect,
72
101
  };
73
102
  }
74
103
 
@@ -87,6 +116,9 @@ async function execute(base64Line: string): Promise<void> {
87
116
  request.globals,
88
117
  request.contractClasses,
89
118
  request.contractInstances,
119
+ request.publicDataWrites,
120
+ request.noteHashes,
121
+ request.protocolContracts,
90
122
  );
91
123
 
92
124
  // Serialize the result to msgpack and encode it in base64 for output
@@ -95,27 +127,49 @@ async function execute(base64Line: string): Promise<void> {
95
127
  output: result.output,
96
128
  revertReason: result.revertReason ?? '',
97
129
  endTreeSnapshots: result.publicInputs.endTreeSnapshots,
130
+ publicTxEffect: result.publicTxEffect,
98
131
  });
99
- writeSync(process.stdout.fd, resultBuffer.toString('base64') + '\n');
132
+ const base64Response = resultBuffer.toString('base64') + '\n';
133
+ await writeOutput(base64Response);
100
134
  } catch (error: any) {
135
+ // If we error, treat as reverted
101
136
  const errorResult = serializeWithMessagePack({
102
137
  reverted: true,
103
- output: [] as string[],
138
+ output: [] as Fr[],
104
139
  revertReason: `Unexpected Error ${error.message}`,
105
140
  endTreeSnapshots: TreeSnapshots.empty(),
141
+ publicTxEffect: PublicTxEffect.empty(),
106
142
  });
107
- writeSync(process.stdout.fd, errorResult.toString('base64') + '\n');
143
+ await writeOutput(errorResult.toString('base64') + '\n');
108
144
  }
109
145
  }
110
146
 
111
147
  function mainLoop() {
112
148
  const rl = createInterface({ input: process.stdin, terminal: false });
149
+
150
+ // Process lines sequentially to avoid race conditions in responses
151
+ const lineQueue: string[] = [];
152
+ let processing = false;
153
+
154
+ async function processQueue() {
155
+ if (processing || lineQueue.length === 0) {
156
+ return;
157
+ }
158
+ processing = true;
159
+ while (lineQueue.length > 0) {
160
+ const line = lineQueue.shift()!;
161
+ await execute(line);
162
+ }
163
+ processing = false;
164
+ }
165
+
113
166
  rl.on('line', (line: string) => {
114
167
  if (line.trim()) {
115
- void execute(line);
168
+ lineQueue.push(line);
169
+ void processQueue();
116
170
  }
117
171
  });
118
172
  rl.on('close', () => process.exit(0));
119
173
  }
120
174
 
121
- mainLoop();
175
+ void mainLoop();
@@ -572,6 +572,10 @@ export class HintingMerkleWriteOperations implements MerkleTreeWriteOperations {
572
572
  return await this.db.close();
573
573
  }
574
574
 
575
+ async [Symbol.dispose](): Promise<void> {
576
+ await this.close();
577
+ }
578
+
575
579
  public async findLeafIndices<ID extends MerkleTreeId>(
576
580
  treeId: ID,
577
581
  values: MerkleTreeLeafType<ID>[],
@@ -5,7 +5,7 @@ import {
5
5
  PUBLIC_DATA_SUBTREE_HEIGHT,
6
6
  } from '@aztec/constants';
7
7
  import { Fr } from '@aztec/foundation/curves/bn254';
8
- import { createLogger } from '@aztec/foundation/log';
8
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
9
9
  import { Timer } from '@aztec/foundation/timer';
10
10
  import { ContractClassPublishedEvent } from '@aztec/protocol-contracts/class-registry';
11
11
  import { ContractInstancePublishedEvent } from '@aztec/protocol-contracts/instance-registry';
@@ -46,9 +46,14 @@ import { L1ToL2MessageIndexOutOfRangeError, NoteHashIndexOutOfRangeError } from
46
46
  export class PublicContractsDB implements PublicContractsDBInterface {
47
47
  private contractStateStack: ContractsDbCheckpoint[] = [new ContractsDbCheckpoint()];
48
48
 
49
- private log = createLogger('simulator:contracts-data-source');
49
+ private log: Logger;
50
50
 
51
- constructor(private dataSource: ContractDataSource) {}
51
+ constructor(
52
+ private dataSource: ContractDataSource,
53
+ bindings?: LoggerBindings,
54
+ ) {
55
+ this.log = createLogger('simulator:contracts-data-source', bindings);
56
+ }
52
57
 
53
58
  public async addContracts(contractDeploymentData: ContractDeploymentData): Promise<void> {
54
59
  const currentState = this.getCurrentState();
@@ -208,9 +213,14 @@ export class PublicContractsDB implements PublicContractsDBInterface {
208
213
  * to decide whether to use hints or not (same with tracing, etc).
209
214
  */
210
215
  export class PublicTreesDB implements PublicStateDBInterface {
211
- private logger = createLogger('simulator:public-trees-db');
216
+ private logger: Logger;
212
217
 
213
- constructor(private readonly db: MerkleTreeWriteOperations) {}
218
+ constructor(
219
+ private readonly db: MerkleTreeWriteOperations,
220
+ bindings?: LoggerBindings,
221
+ ) {
222
+ this.logger = createLogger('simulator:public-trees-db', bindings);
223
+ }
214
224
 
215
225
  public async storageRead(contract: AztecAddress, slot: Fr): Promise<Fr> {
216
226
  const timer = new Timer();
@@ -81,6 +81,10 @@ export class GuardedMerkleTreeOperations implements MerkleTreeWriteOperations {
81
81
  close(): Promise<void> {
82
82
  return this.guardAndPush(() => this.target.close());
83
83
  }
84
+
85
+ async [Symbol.dispose](): Promise<void> {
86
+ await this.close();
87
+ }
84
88
  getTreeInfo(treeId: MerkleTreeId): Promise<TreeInfo> {
85
89
  return this.guardAndPush(() => this.target.getTreeInfo(treeId));
86
90
  }
@@ -1,7 +1,7 @@
1
1
  import { MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, NULLIFIER_SUBTREE_HEIGHT } from '@aztec/constants';
2
2
  import { padArrayEnd } from '@aztec/foundation/collection';
3
3
  import { Fr } from '@aztec/foundation/curves/bn254';
4
- import { createLogger } from '@aztec/foundation/log';
4
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
5
5
  import { sleep } from '@aztec/foundation/sleep';
6
6
  import { DateProvider, Timer, elapsed, executeTimeout } from '@aztec/foundation/timer';
7
7
  import { ProtocolContractAddress } from '@aztec/protocol-contracts';
@@ -62,11 +62,15 @@ import { PublicProcessorMetrics } from './public_processor_metrics.js';
62
62
  * Creates new instances of PublicProcessor given the provided merkle tree db and contract data source.
63
63
  */
64
64
  export class PublicProcessorFactory {
65
+ private log: Logger;
65
66
  constructor(
66
67
  private contractDataSource: ContractDataSource,
67
68
  private dateProvider: DateProvider = new DateProvider(),
68
69
  protected telemetryClient: TelemetryClient = getTelemetryClient(),
69
- ) {}
70
+ bindings?: LoggerBindings,
71
+ ) {
72
+ this.log = createLogger('simulator:public-processor-factory', bindings);
73
+ }
70
74
 
71
75
  /**
72
76
  * Creates a new instance of a PublicProcessor.
@@ -79,7 +83,8 @@ export class PublicProcessorFactory {
79
83
  globalVariables: GlobalVariables,
80
84
  config: PublicSimulatorConfig,
81
85
  ): PublicProcessor {
82
- const contractsDB = new PublicContractsDB(this.contractDataSource);
86
+ const bindings = this.log.getBindings();
87
+ const contractsDB = new PublicContractsDB(this.contractDataSource, bindings);
83
88
 
84
89
  const guardedFork = new GuardedMerkleTreeOperations(merkleTree);
85
90
  const publicTxSimulator = this.createPublicTxSimulator(guardedFork, contractsDB, globalVariables, config);
@@ -91,6 +96,7 @@ export class PublicProcessorFactory {
91
96
  publicTxSimulator,
92
97
  this.dateProvider,
93
98
  this.telemetryClient,
99
+ createLogger('simulator:public-processor', bindings),
94
100
  );
95
101
  }
96
102
 
@@ -100,7 +106,14 @@ export class PublicProcessorFactory {
100
106
  globalVariables: GlobalVariables,
101
107
  config?: Partial<PublicTxSimulatorConfig>,
102
108
  ): PublicTxSimulatorInterface {
103
- return new TelemetryCppPublicTxSimulator(merkleTree, contractsDB, globalVariables, this.telemetryClient, config);
109
+ return new TelemetryCppPublicTxSimulator(
110
+ merkleTree,
111
+ contractsDB,
112
+ globalVariables,
113
+ this.telemetryClient,
114
+ config,
115
+ this.log.getBindings(),
116
+ );
104
117
  }
105
118
  }
106
119
 
@@ -125,8 +138,8 @@ export class PublicProcessor implements Traceable {
125
138
  protected publicTxSimulator: PublicTxSimulatorInterface,
126
139
  private dateProvider: DateProvider,
127
140
  telemetryClient: TelemetryClient = getTelemetryClient(),
128
- private log = createLogger('simulator:public-processor'),
129
- private opts: Pick<SequencerConfig, 'fakeProcessingDelayPerTxMs'> = {},
141
+ private log: Logger,
142
+ private opts: Pick<SequencerConfig, 'fakeProcessingDelayPerTxMs' | 'fakeThrowAfterProcessingTxCount'> = {},
130
143
  ) {
131
144
  this.metrics = new PublicProcessorMetrics(telemetryClient, 'PublicProcessor');
132
145
  }
@@ -146,7 +159,7 @@ export class PublicProcessor implements Traceable {
146
159
  txs: Iterable<Tx> | AsyncIterable<Tx>,
147
160
  limits: PublicProcessorLimits = {},
148
161
  validator: PublicProcessorValidator = {},
149
- ): Promise<[ProcessedTx[], FailedTx[], Tx[], NestedProcessReturnValues[]]> {
162
+ ): Promise<[ProcessedTx[], FailedTx[], Tx[], NestedProcessReturnValues[], number]> {
150
163
  const { maxTransactions, maxBlockSize, deadline, maxBlockGas, maxBlobFields } = limits;
151
164
  const { preprocessValidator, nullifierCache } = validator;
152
165
  const result: ProcessedTx[] = [];
@@ -160,7 +173,7 @@ export class PublicProcessor implements Traceable {
160
173
  let totalBlockGas = new Gas(0, 0);
161
174
  let totalBlobFields = 0;
162
175
 
163
- for await (const origTx of txs) {
176
+ for await (const tx of txs) {
164
177
  // Only process up to the max tx limit
165
178
  if (maxTransactions !== undefined && result.length >= maxTransactions) {
166
179
  this.log.debug(`Stopping tx processing due to reaching the max tx limit.`);
@@ -174,8 +187,8 @@ export class PublicProcessor implements Traceable {
174
187
  }
175
188
 
176
189
  // Skip this tx if it'd exceed max block size
177
- const txHash = origTx.getTxHash().toString();
178
- const preTxSizeInBytes = origTx.getEstimatedPrivateTxEffectsSize();
190
+ const txHash = tx.getTxHash().toString();
191
+ const preTxSizeInBytes = tx.getEstimatedPrivateTxEffectsSize();
179
192
  if (maxBlockSize !== undefined && totalSizeInBytes + preTxSizeInBytes > maxBlockSize) {
180
193
  this.log.warn(`Skipping processing of tx ${txHash} sized ${preTxSizeInBytes} bytes due to block size limit`, {
181
194
  txHash,
@@ -187,7 +200,7 @@ export class PublicProcessor implements Traceable {
187
200
  }
188
201
 
189
202
  // Skip this tx if its gas limit would exceed the block gas limit
190
- const txGasLimit = origTx.data.constants.txContext.gasSettings.gasLimits;
203
+ const txGasLimit = tx.data.constants.txContext.gasSettings.gasLimits;
191
204
  if (maxBlockGas !== undefined && totalBlockGas.add(txGasLimit).gtAny(maxBlockGas)) {
192
205
  this.log.warn(`Skipping processing of tx ${txHash} due to block gas limit`, {
193
206
  txHash,
@@ -198,9 +211,6 @@ export class PublicProcessor implements Traceable {
198
211
  continue;
199
212
  }
200
213
 
201
- // The processor modifies the tx objects in place, so we need to clone them.
202
- const tx = Tx.clone(origTx);
203
-
204
214
  // We validate the tx before processing it, to avoid unnecessary work.
205
215
  if (preprocessValidator) {
206
216
  const result = await preprocessValidator.validateTx(tx);
@@ -233,6 +243,12 @@ export class PublicProcessor implements Traceable {
233
243
  try {
234
244
  const [processedTx, returnValues] = await this.processTx(tx, deadline);
235
245
 
246
+ // Inject a fake processing failure after N txs if requested
247
+ const fakeThrowAfter = this.opts.fakeThrowAfterProcessingTxCount;
248
+ if (fakeThrowAfter !== undefined && result.length + failed.length + 1 >= fakeThrowAfter) {
249
+ throw new Error(`Fake error after processing ${fakeThrowAfter} txs`);
250
+ }
251
+
236
252
  const txBlobFields = processedTx.txEffect.getNumBlobFields();
237
253
 
238
254
  // If the actual size of this tx would exceed block size, skip it
@@ -251,6 +267,7 @@ export class PublicProcessor implements Traceable {
251
267
  }
252
268
 
253
269
  // If the actual blob fields of this tx would exceed the limit, skip it
270
+ // Note: maxBlobFields already accounts for block end blob fields and previous blocks in checkpoint.
254
271
  if (maxBlobFields !== undefined && totalBlobFields + txBlobFields > maxBlobFields) {
255
272
  this.log.debug(
256
273
  `Skipping processed tx ${txHash} with ${txBlobFields} blob fields due to max blob fields limit.`,
@@ -282,7 +299,15 @@ export class PublicProcessor implements Traceable {
282
299
  if (err?.name === 'PublicProcessorTimeoutError') {
283
300
  this.log.warn(`Stopping tx processing due to timeout.`);
284
301
  // We hit the transaction execution deadline.
285
- // There may still be a transaction executing. We stop the guarded fork to prevent any further access to the world state.
302
+ // There may still be a transaction executing on a worker thread (C++ via NAPI).
303
+ // Signal cancellation AND WAIT for the simulation to actually stop.
304
+ // This is critical because C++ might be in the middle of a slow operation (e.g., pad_trees)
305
+ // and won't check the cancellation flag until that operation completes.
306
+ // Without waiting, we'd proceed to revert checkpoints while C++ is still writing to state.
307
+ // Wait for C++ to stop gracefully.
308
+ await this.publicTxSimulator.cancel?.();
309
+
310
+ // Now stop the guarded fork to prevent any further TS-side access to the world state.
286
311
  await this.guardedMerkleTree.stop();
287
312
 
288
313
  // We now know there can't be any further access to world state. The fork is in a state where there is:
@@ -338,7 +363,7 @@ export class PublicProcessor implements Traceable {
338
363
  totalSizeInBytes,
339
364
  });
340
365
 
341
- return [result, failed, usedTxs, returns];
366
+ return [result, failed, usedTxs, returns, totalBlobFields];
342
367
  }
343
368
 
344
369
  private async checkWorldStateUnchanged(