@aztec/simulator 0.80.0 → 0.81.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 (89) hide show
  1. package/dest/common/db_interfaces.d.ts +24 -5
  2. package/dest/common/db_interfaces.d.ts.map +1 -1
  3. package/dest/common/debug_fn_name.d.ts +2 -2
  4. package/dest/common/debug_fn_name.d.ts.map +1 -1
  5. package/dest/private/acvm/deserialize.d.ts +19 -0
  6. package/dest/private/acvm/deserialize.d.ts.map +1 -1
  7. package/dest/private/acvm/deserialize.js +29 -0
  8. package/dest/private/acvm/oracle/oracle.d.ts +2 -0
  9. package/dest/private/acvm/oracle/oracle.d.ts.map +1 -1
  10. package/dest/private/acvm/oracle/oracle.js +18 -3
  11. package/dest/private/acvm/oracle/typed_oracle.d.ts +2 -1
  12. package/dest/private/acvm/oracle/typed_oracle.d.ts.map +1 -1
  13. package/dest/private/acvm/oracle/typed_oracle.js +3 -0
  14. package/dest/private/acvm/serialize.d.ts +11 -0
  15. package/dest/private/acvm/serialize.d.ts.map +1 -1
  16. package/dest/private/acvm/serialize.js +27 -0
  17. package/dest/private/execution_data_provider.d.ts +12 -4
  18. package/dest/private/execution_data_provider.d.ts.map +1 -1
  19. package/dest/private/private_execution_oracle.d.ts.map +1 -1
  20. package/dest/private/private_execution_oracle.js +1 -1
  21. package/dest/private/unconstrained_execution_oracle.d.ts +4 -2
  22. package/dest/private/unconstrained_execution_oracle.d.ts.map +1 -1
  23. package/dest/private/unconstrained_execution_oracle.js +6 -2
  24. package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -1
  25. package/dest/public/avm/fixtures/avm_simulation_tester.js +5 -5
  26. package/dest/public/avm/fixtures/index.d.ts +4 -4
  27. package/dest/public/avm/fixtures/index.d.ts.map +1 -1
  28. package/dest/public/avm/fixtures/index.js +9 -6
  29. package/dest/public/avm/fixtures/simple_contract_data_source.d.ts +1 -2
  30. package/dest/public/avm/fixtures/simple_contract_data_source.d.ts.map +1 -1
  31. package/dest/public/avm/fixtures/simple_contract_data_source.js +0 -3
  32. package/dest/public/avm/journal/journal.d.ts +16 -70
  33. package/dest/public/avm/journal/journal.d.ts.map +1 -1
  34. package/dest/public/avm/journal/journal.js +88 -210
  35. package/dest/public/avm/journal/nullifiers.d.ts +2 -2
  36. package/dest/public/avm/journal/nullifiers.d.ts.map +1 -1
  37. package/dest/public/avm/journal/public_storage.d.ts +2 -2
  38. package/dest/public/avm/journal/public_storage.d.ts.map +1 -1
  39. package/dest/public/avm/test_utils.d.ts +10 -13
  40. package/dest/public/avm/test_utils.d.ts.map +1 -1
  41. package/dest/public/avm/test_utils.js +7 -12
  42. package/dest/public/fixtures/public_tx_simulation_tester.d.ts +3 -3
  43. package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
  44. package/dest/public/fixtures/public_tx_simulation_tester.js +10 -9
  45. package/dest/public/hinting_db_sources.d.ts +19 -0
  46. package/dest/public/hinting_db_sources.d.ts.map +1 -0
  47. package/dest/public/hinting_db_sources.js +36 -0
  48. package/dest/public/public_db_sources.d.ts +45 -21
  49. package/dest/public/public_db_sources.d.ts.map +1 -1
  50. package/dest/public/public_db_sources.js +79 -24
  51. package/dest/public/public_processor/public_processor.d.ts +5 -5
  52. package/dest/public/public_processor/public_processor.d.ts.map +1 -1
  53. package/dest/public/public_processor/public_processor.js +21 -20
  54. package/dest/public/public_tx_simulator/public_tx_context.d.ts +9 -14
  55. package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
  56. package/dest/public/public_tx_simulator/public_tx_context.js +15 -19
  57. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +9 -6
  58. package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
  59. package/dest/public/public_tx_simulator/public_tx_simulator.js +28 -14
  60. package/dest/public/side_effect_trace.d.ts +6 -22
  61. package/dest/public/side_effect_trace.d.ts.map +1 -1
  62. package/dest/public/side_effect_trace.js +11 -70
  63. package/dest/public/side_effect_trace_interface.d.ts +5 -19
  64. package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
  65. package/package.json +14 -14
  66. package/src/common/db_interfaces.ts +26 -5
  67. package/src/common/debug_fn_name.ts +2 -2
  68. package/src/private/acvm/deserialize.ts +33 -0
  69. package/src/private/acvm/oracle/oracle.ts +37 -3
  70. package/src/private/acvm/oracle/typed_oracle.ts +5 -1
  71. package/src/private/acvm/serialize.ts +28 -0
  72. package/src/private/execution_data_provider.ts +13 -4
  73. package/src/private/private_execution_oracle.ts +5 -1
  74. package/src/private/unconstrained_execution_oracle.ts +12 -3
  75. package/src/public/avm/fixtures/avm_simulation_tester.ts +8 -5
  76. package/src/public/avm/fixtures/index.ts +16 -10
  77. package/src/public/avm/fixtures/simple_contract_data_source.ts +1 -10
  78. package/src/public/avm/journal/journal.ts +119 -353
  79. package/src/public/avm/journal/nullifiers.ts +2 -2
  80. package/src/public/avm/journal/public_storage.ts +2 -2
  81. package/src/public/avm/test_utils.ts +20 -29
  82. package/src/public/fixtures/public_tx_simulation_tester.ts +9 -12
  83. package/src/public/hinting_db_sources.ts +71 -0
  84. package/src/public/public_db_sources.ts +131 -29
  85. package/src/public/public_processor/public_processor.ts +22 -21
  86. package/src/public/public_tx_simulator/public_tx_context.ts +30 -38
  87. package/src/public/public_tx_simulator/public_tx_simulator.ts +47 -17
  88. package/src/public/side_effect_trace.ts +8 -172
  89. package/src/public/side_effect_trace_interface.ts +4 -55
@@ -10,18 +10,11 @@ import { padArrayEnd } from '@aztec/foundation/collection';
10
10
  import { Fr } from '@aztec/foundation/fields';
11
11
  import { type Logger, createLogger } from '@aztec/foundation/log';
12
12
  import { assertLength } from '@aztec/foundation/serialize';
13
- import {
14
- AvmCircuitInputs,
15
- type AvmCircuitPublicInputs,
16
- type AvmProvingRequest,
17
- PublicDataWrite,
18
- RevertCode,
19
- } from '@aztec/stdlib/avm';
13
+ import { type AvmCircuitPublicInputs, AvmExecutionHints, PublicDataWrite, RevertCode } from '@aztec/stdlib/avm';
20
14
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
21
15
  import type { SimulationError } from '@aztec/stdlib/errors';
22
16
  import { computeTransactionFee } from '@aztec/stdlib/fees';
23
17
  import { Gas, GasSettings } from '@aztec/stdlib/gas';
24
- import type { MerkleTreeReadOperations } from '@aztec/stdlib/interfaces/server';
25
18
  import {
26
19
  PrivateToAvmAccumulatedData,
27
20
  PrivateToAvmAccumulatedDataArrayLengths,
@@ -30,7 +23,6 @@ import {
30
23
  countAccumulatedItems,
31
24
  mergeAccumulatedData,
32
25
  } from '@aztec/stdlib/kernel';
33
- import { ProvingRequestType } from '@aztec/stdlib/proofs';
34
26
  import { MerkleTreeId } from '@aztec/stdlib/trees';
35
27
  import {
36
28
  type GlobalVariables,
@@ -45,8 +37,10 @@ import {
45
37
  import { strict as assert } from 'assert';
46
38
  import { inspect } from 'util';
47
39
 
40
+ import type { PublicContractsDBInterface } from '../../server.js';
48
41
  import { AvmPersistableStateManager } from '../avm/index.js';
49
- import type { WorldStateDB } from '../public_db_sources.js';
42
+ import { HintingPublicContractsDB } from '../hinting_db_sources.js';
43
+ import type { PublicTreesDB } from '../public_db_sources.js';
50
44
  import { SideEffectArrayLengths, SideEffectTrace } from '../side_effect_trace.js';
51
45
  import { getCallRequestsByPhase, getExecutionRequestsByPhase } from '../utils.js';
52
46
 
@@ -68,9 +62,7 @@ export class PublicTxContext {
68
62
  /* What caused a revert (if one occurred)? */
69
63
  public revertReason: SimulationError | undefined;
70
64
 
71
- public avmProvingRequest: AvmProvingRequest | undefined; // FIXME(dbanks12): remove
72
-
73
- constructor(
65
+ private constructor(
74
66
  public readonly txHash: TxHash,
75
67
  public readonly state: PhaseStateManager,
76
68
  private readonly globalVariables: GlobalVariables,
@@ -87,14 +79,15 @@ export class PublicTxContext {
87
79
  public readonly nonRevertibleAccumulatedDataFromPrivate: PrivateToPublicAccumulatedData,
88
80
  public readonly revertibleAccumulatedDataFromPrivate: PrivateToPublicAccumulatedData,
89
81
  public readonly feePayer: AztecAddress,
90
- public trace: SideEffectTrace, // FIXME(dbanks12): should be private
82
+ private readonly trace: SideEffectTrace,
83
+ public readonly hints: AvmExecutionHints, // This is public due to enqueued call hinting.
91
84
  ) {
92
85
  this.log = createLogger(`simulator:public_tx_context`);
93
86
  }
94
87
 
95
88
  public static async create(
96
- db: MerkleTreeReadOperations,
97
- worldStateDB: WorldStateDB,
89
+ treesDB: PublicTreesDB,
90
+ contractsDB: PublicContractsDBInterface,
98
91
  tx: Tx,
99
92
  globalVariables: GlobalVariables,
100
93
  doMerkleOperations: boolean,
@@ -114,8 +107,20 @@ export class PublicTxContext {
114
107
 
115
108
  const firstNullifier = nonRevertibleAccumulatedDataFromPrivate.nullifiers[0];
116
109
 
110
+ // We wrap the DB to collect AVM hints.
111
+ const hints = new AvmExecutionHints();
112
+ const hintingContractsDB = new HintingPublicContractsDB(contractsDB, hints);
113
+ // TODO: Wrap merkle db.
114
+
117
115
  // Transaction level state manager that will be forked for revertible phases.
118
- const txStateManager = AvmPersistableStateManager.create(worldStateDB, trace, doMerkleOperations, firstNullifier);
116
+ const txStateManager = AvmPersistableStateManager.create(
117
+ treesDB,
118
+ hintingContractsDB,
119
+ trace,
120
+ doMerkleOperations,
121
+ firstNullifier,
122
+ globalVariables.blockNumber.toNumber(),
123
+ );
119
124
 
120
125
  const gasSettings = tx.data.constants.txContext.gasSettings;
121
126
  const gasUsedByPrivate = tx.data.gasUsed;
@@ -126,7 +131,7 @@ export class PublicTxContext {
126
131
  await tx.getTxHash(),
127
132
  new PhaseStateManager(txStateManager),
128
133
  globalVariables,
129
- await db.getStateReference(),
134
+ await treesDB.getStateReference(),
130
135
  gasSettings,
131
136
  gasUsedByPrivate,
132
137
  gasAllocatedToPublic,
@@ -140,6 +145,7 @@ export class PublicTxContext {
140
145
  tx.data.forPublic!.revertibleAccumulatedData,
141
146
  tx.data.feePayer,
142
147
  trace,
148
+ hints,
143
149
  );
144
150
  }
145
151
 
@@ -322,7 +328,7 @@ export class PublicTxContext {
322
328
  /**
323
329
  * Generate the public inputs for the AVM circuit.
324
330
  */
325
- private async generateAvmCircuitPublicInputs(endStateReference: StateReference): Promise<AvmCircuitPublicInputs> {
331
+ public async generateAvmCircuitPublicInputs(endStateReference: StateReference): Promise<AvmCircuitPublicInputs> {
326
332
  assert(this.halted, 'Can only get AvmCircuitPublicInputs after tx execution ends');
327
333
  const stateManager = this.state.getActiveStateManager();
328
334
 
@@ -406,16 +412,18 @@ export class PublicTxContext {
406
412
  );
407
413
  const numNoteHashesToPad =
408
414
  MAX_NOTE_HASHES_PER_TX - countAccumulatedItems(avmCircuitPublicInputs.accumulatedData.noteHashes);
409
- await stateManager.db.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, padArrayEnd([], Fr.ZERO, numNoteHashesToPad));
415
+ await stateManager
416
+ .deprecatedGetTreesForPIGeneration()
417
+ .appendLeaves(MerkleTreeId.NOTE_HASH_TREE, padArrayEnd([], Fr.ZERO, numNoteHashesToPad));
410
418
  const numNullifiersToPad =
411
419
  MAX_NULLIFIERS_PER_TX - countAccumulatedItems(avmCircuitPublicInputs.accumulatedData.nullifiers);
412
- await stateManager.db.batchInsert(
420
+ await stateManager.deprecatedGetTreesForPIGeneration().batchInsert(
413
421
  MerkleTreeId.NULLIFIER_TREE,
414
422
  padArrayEnd([], Fr.ZERO, numNullifiersToPad).map(nullifier => nullifier.toBuffer()),
415
423
  NULLIFIER_SUBTREE_HEIGHT,
416
424
  );
417
425
 
418
- const paddedState = await stateManager.db.getStateReference();
426
+ const paddedState = await stateManager.deprecatedGetTreesForPIGeneration().getStateReference();
419
427
  avmCircuitPublicInputs.endTreeSnapshots = new TreeSnapshots(
420
428
  paddedState.l1ToL2MessageTree,
421
429
  paddedState.partial.noteHashTree,
@@ -425,22 +433,6 @@ export class PublicTxContext {
425
433
 
426
434
  return avmCircuitPublicInputs;
427
435
  }
428
-
429
- /**
430
- * Generate the proving request for the AVM circuit.
431
- */
432
- async generateProvingRequest(endStateReference: StateReference): Promise<AvmProvingRequest> {
433
- const hints = this.trace.getAvmCircuitHints();
434
- return {
435
- type: ProvingRequestType.PUBLIC_VM,
436
- inputs: new AvmCircuitInputs(
437
- 'public_dispatch',
438
- [],
439
- hints,
440
- await this.generateAvmCircuitPublicInputs(endStateReference),
441
- ),
442
- };
443
- }
444
436
  }
445
437
 
446
438
  /**
@@ -3,11 +3,18 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
3
3
  import { Timer } from '@aztec/foundation/timer';
4
4
  import { ProtocolContractAddress } from '@aztec/protocol-contracts';
5
5
  import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
6
- import type { AvmProvingRequest, RevertCode } from '@aztec/stdlib/avm';
6
+ import {
7
+ AvmCircuitInputs,
8
+ AvmCircuitPublicInputs,
9
+ AvmEnqueuedCallHint,
10
+ AvmExecutionHints,
11
+ type AvmProvingRequest,
12
+ type RevertCode,
13
+ } from '@aztec/stdlib/avm';
7
14
  import { SimulationError } from '@aztec/stdlib/errors';
8
15
  import type { Gas, GasUsed } from '@aztec/stdlib/gas';
9
- import type { MerkleTreeReadOperations } from '@aztec/stdlib/interfaces/server';
10
16
  import type { PublicCallRequest } from '@aztec/stdlib/kernel';
17
+ import { ProvingRequestType } from '@aztec/stdlib/proofs';
11
18
  import type { AvmSimulationStats } from '@aztec/stdlib/stats';
12
19
  import {
13
20
  type GlobalVariables,
@@ -25,7 +32,7 @@ import type { AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js'
25
32
  import { type AvmPersistableStateManager, AvmSimulator } from '../avm/index.js';
26
33
  import { NullifierCollisionError } from '../avm/journal/nullifiers.js';
27
34
  import { ExecutorMetrics } from '../executor_metrics.js';
28
- import type { WorldStateDB } from '../public_db_sources.js';
35
+ import type { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
29
36
  import { PublicTxContext } from './public_tx_context.js';
30
37
 
31
38
  export type ProcessedPhase = {
@@ -52,8 +59,8 @@ export class PublicTxSimulator {
52
59
  private log: Logger;
53
60
 
54
61
  constructor(
55
- private db: MerkleTreeReadOperations,
56
- private worldStateDB: WorldStateDB,
62
+ private treesDB: PublicTreesDB,
63
+ private contractsDB: PublicContractsDB,
57
64
  private globalVariables: GlobalVariables,
58
65
  private doMerkleOperations: boolean = false,
59
66
  private skipFeeEnforcement: boolean = false,
@@ -79,8 +86,8 @@ export class PublicTxSimulator {
79
86
  this.log.debug(`Simulating ${tx.enqueuedPublicFunctionCalls.length} public calls for tx ${txHash}`, { txHash });
80
87
 
81
88
  const context = await PublicTxContext.create(
82
- this.db,
83
- this.worldStateDB,
89
+ this.treesDB,
90
+ this.contractsDB,
84
91
  tx,
85
92
  this.globalVariables,
86
93
  this.doMerkleOperations,
@@ -90,7 +97,7 @@ export class PublicTxSimulator {
90
97
  await this.insertNonRevertiblesFromPrivate(context);
91
98
  // add new contracts to the contracts db so that their functions may be found and called
92
99
  // TODO(#6464): Should we allow emitting contracts in the private setup phase?
93
- await this.worldStateDB.addNewNonRevertibleContracts(tx);
100
+ await this.contractsDB.addNewNonRevertibleContracts(tx);
94
101
  const nonRevertEnd = process.hrtime.bigint();
95
102
  this.metrics.recordPrivateEffectsInsertion(Number(nonRevertEnd - nonRevertStart) / 1_000, 'non-revertible');
96
103
 
@@ -104,7 +111,7 @@ export class PublicTxSimulator {
104
111
  const success = await this.insertRevertiblesFromPrivate(context);
105
112
  if (success) {
106
113
  // add new contracts to the contracts db so that their functions may be found and called
107
- await this.worldStateDB.addNewRevertibleContracts(tx);
114
+ await this.contractsDB.addNewRevertibleContracts(tx);
108
115
  const revertEnd = process.hrtime.bigint();
109
116
  this.metrics.recordPrivateEffectsInsertion(Number(revertEnd - revertStart) / 1_000, 'revertible');
110
117
 
@@ -125,9 +132,8 @@ export class PublicTxSimulator {
125
132
  await context.halt();
126
133
  await this.payFee(context);
127
134
 
128
- const endStateReference = await this.db.getStateReference();
129
-
130
- const avmProvingRequest = await context.generateProvingRequest(endStateReference);
135
+ const publicInputs = await context.generateAvmCircuitPublicInputs(await this.treesDB.getStateReference());
136
+ const avmProvingRequest = PublicTxSimulator.generateProvingRequest(publicInputs, context.hints);
131
137
 
132
138
  const revertCode = context.getFinalRevertCode();
133
139
 
@@ -137,7 +143,7 @@ export class PublicTxSimulator {
137
143
  // Commit contracts from this TX to the block-level cache and clear tx cache
138
144
  // If the tx reverted, only commit non-revertible contracts
139
145
  // NOTE: You can't create contracts in public, so this is only relevant for private-created contracts
140
- this.worldStateDB.commitContractsForTx(/*onlyNonRevertibles=*/ !revertCode.isOK());
146
+ this.contractsDB.commitContractsForTx(/*onlyNonRevertibles=*/ !revertCode.isOK());
141
147
 
142
148
  const endTime = process.hrtime.bigint();
143
149
  this.log.debug(`Public TX simulator took ${Number(endTime - startTime) / 1_000_000} ms\n`);
@@ -157,7 +163,7 @@ export class PublicTxSimulator {
157
163
  } finally {
158
164
  // Make sure there are no new contracts in the tx-level cache.
159
165
  // They should either be committed to block-level cache or cleared.
160
- this.worldStateDB.clearContractsForTx();
166
+ this.contractsDB.clearContractsForTx();
161
167
  }
162
168
  }
163
169
 
@@ -288,10 +294,23 @@ export class PublicTxSimulator {
288
294
  ): Promise<AvmFinalizedCallResult> {
289
295
  const stateManager = context.state.getActiveStateManager();
290
296
  const address = executionRequest.callContext.contractAddress;
291
- const fnName = await getPublicFunctionDebugName(this.worldStateDB, address, executionRequest.args);
297
+ const fnName = await getPublicFunctionDebugName(this.contractsDB, address, executionRequest.args);
292
298
 
293
299
  const allocatedGas = context.getGasLeftAtPhase(phase);
294
300
 
301
+ // The reason we need enqueued hints at all (and cannot just use the public inputs) is
302
+ // because they don't have the actual calldata, just the hash of it.
303
+ // If/when we pass the whole TX to C++, we can remove this class of hints.
304
+ stateManager.traceEnqueuedCall(callRequest);
305
+ context.hints.enqueuedCalls.push(
306
+ new AvmEnqueuedCallHint(
307
+ executionRequest.callContext.msgSender,
308
+ executionRequest.callContext.contractAddress,
309
+ executionRequest.args,
310
+ executionRequest.callContext.isStaticCall,
311
+ ),
312
+ );
313
+
295
314
  const result = await this.simulateEnqueuedCallInternal(
296
315
  context.state.getActiveStateManager(),
297
316
  executionRequest,
@@ -306,8 +325,6 @@ export class PublicTxSimulator {
306
325
  `Simulated enqueued public call (${fnName}) consumed ${gasUsed.l2Gas} L2 gas ending with ${result.gasLeft.l2Gas} L2 gas left.`,
307
326
  );
308
327
 
309
- stateManager.traceEnqueuedCall(callRequest, executionRequest.args, result.reverted);
310
-
311
328
  if (result.reverted) {
312
329
  const culprit = `${executionRequest.callContext.contractAddress}:${executionRequest.callContext.functionSelector}`;
313
330
  context.revert(phase, result.revertReason, culprit); // throws if in setup (non-revertible) phase
@@ -471,4 +488,17 @@ export class PublicTxSimulator {
471
488
  const updatedBalance = currentBalance.sub(txFee);
472
489
  await stateManager.writeStorage(feeJuiceAddress, balanceSlot, updatedBalance, true);
473
490
  }
491
+
492
+ /**
493
+ * Generate the proving request for the AVM circuit.
494
+ */
495
+ private static generateProvingRequest(
496
+ publicInputs: AvmCircuitPublicInputs,
497
+ hints: AvmExecutionHints,
498
+ ): AvmProvingRequest {
499
+ return {
500
+ type: ProvingRequestType.PUBLIC_VM,
501
+ inputs: new AvmCircuitInputs('public_dispatch', [], hints, publicInputs),
502
+ };
503
+ }
474
504
  }
@@ -1,5 +1,4 @@
1
1
  import {
2
- L1_TO_L2_MSG_TREE_HEIGHT,
3
2
  MAX_ENQUEUED_CALLS_PER_TX,
4
3
  MAX_L2_TO_L1_MSGS_PER_TX,
5
4
  MAX_NOTE_HASHES_PER_TX,
@@ -8,10 +7,7 @@ import {
8
7
  MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
9
8
  MAX_PUBLIC_LOGS_PER_TX,
10
9
  MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
11
- NOTE_HASH_TREE_HEIGHT,
12
- NULLIFIER_TREE_HEIGHT,
13
10
  PROTOCOL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
14
- PUBLIC_DATA_TREE_HEIGHT,
15
11
  PUBLIC_LOG_DATA_SIZE_IN_FIELDS,
16
12
  } from '@aztec/constants';
17
13
  import { padArrayEnd } from '@aztec/foundation/collection';
@@ -20,21 +16,11 @@ import { Fr } from '@aztec/foundation/fields';
20
16
  import { createLogger } from '@aztec/foundation/log';
21
17
  import {
22
18
  AvmAccumulatedData,
23
- AvmAppendTreeHint,
24
19
  AvmCircuitPublicInputs,
25
- AvmContractClassHint,
26
- AvmContractInstanceHint,
27
- AvmEnqueuedCallHint,
28
- AvmExecutionHints,
29
- AvmNullifierReadTreeHint,
30
- AvmNullifierWriteTreeHint,
31
- AvmPublicDataReadTreeHint,
32
- AvmPublicDataWriteTreeHint,
33
20
  PublicDataUpdateRequest,
34
21
  PublicDataWrite,
35
22
  } from '@aztec/stdlib/avm';
36
23
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
37
- import { type ContractClassWithCommitment, SerializableContractInstance } from '@aztec/stdlib/contract';
38
24
  import type { Gas, GasSettings } from '@aztec/stdlib/gas';
39
25
  import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
40
26
  import {
@@ -46,7 +32,6 @@ import {
46
32
  } from '@aztec/stdlib/kernel';
47
33
  import { PublicLog } from '@aztec/stdlib/logs';
48
34
  import { L2ToL1Message, ScopedL2ToL1Message } from '@aztec/stdlib/messaging';
49
- import { NullifierLeafPreimage, PublicDataTreeLeafPreimage } from '@aztec/stdlib/trees';
50
35
  import type { GlobalVariables, TreeSnapshots } from '@aztec/stdlib/tx';
51
36
 
52
37
  import { strict as assert } from 'assert';
@@ -55,11 +40,6 @@ import { SideEffectLimitReachedError } from './side_effect_errors.js';
55
40
  import type { PublicSideEffectTraceInterface } from './side_effect_trace_interface.js';
56
41
  import { UniqueClassIds } from './unique_class_ids.js';
57
42
 
58
- const emptyPublicDataPath = () => new Array(PUBLIC_DATA_TREE_HEIGHT).fill(Fr.zero());
59
- const emptyNoteHashPath = () => new Array(NOTE_HASH_TREE_HEIGHT).fill(Fr.zero());
60
- const emptyNullifierPath = () => new Array(NULLIFIER_TREE_HEIGHT).fill(Fr.zero());
61
- const emptyL1ToL2MessagePath = () => new Array(L1_TO_L2_MSG_TREE_HEIGHT).fill(Fr.zero());
62
-
63
43
  /**
64
44
  * A struct containing just the side effects as regular arrays
65
45
  * as opposed to "Tuple" arrays used by circuit public inputs.
@@ -67,12 +47,10 @@ const emptyL1ToL2MessagePath = () => new Array(L1_TO_L2_MSG_TREE_HEIGHT).fill(Fr
67
47
  **/
68
48
  export type SideEffects = {
69
49
  enqueuedCalls: PublicCallRequest[];
70
-
71
50
  publicDataWrites: PublicDataUpdateRequest[];
72
51
  noteHashes: NoteHash[];
73
52
  nullifiers: Nullifier[];
74
53
  l2ToL1Msgs: ScopedL2ToL1Message[];
75
-
76
54
  publicLogs: PublicLog[];
77
55
  };
78
56
 
@@ -101,7 +79,6 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
101
79
  private sideEffectCounter: number;
102
80
 
103
81
  private enqueuedCalls: PublicCallRequest[] = [];
104
-
105
82
  private publicDataWrites: PublicDataUpdateRequest[] = [];
106
83
  private protocolPublicDataWritesLength: number = 0;
107
84
  private userPublicDataWritesLength: number = 0;
@@ -110,8 +87,6 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
110
87
  private l2ToL1Messages: ScopedL2ToL1Message[] = [];
111
88
  private publicLogs: PublicLog[] = [];
112
89
 
113
- private avmCircuitHints: AvmExecutionHints;
114
-
115
90
  /** Make sure a forked trace is never merged twice. */
116
91
  private alreadyMergedIntoParent = false;
117
92
 
@@ -126,7 +101,6 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
126
101
  private uniqueClassIds: UniqueClassIds = new UniqueClassIds(),
127
102
  ) {
128
103
  this.sideEffectCounter = startSideEffectCounter;
129
- this.avmCircuitHints = AvmExecutionHints.empty();
130
104
  }
131
105
 
132
106
  public fork() {
@@ -154,6 +128,7 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
154
128
 
155
129
  this.sideEffectCounter = forkedTrace.sideEffectCounter;
156
130
  this.enqueuedCalls.push(...forkedTrace.enqueuedCalls);
131
+ this.uniqueClassIds.acceptAndMerge(forkedTrace.uniqueClassIds);
157
132
 
158
133
  if (!reverted) {
159
134
  this.publicDataWrites.push(...forkedTrace.publicDataWrites);
@@ -162,21 +137,6 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
162
137
  this.l2ToL1Messages.push(...forkedTrace.l2ToL1Messages);
163
138
  this.publicLogs.push(...forkedTrace.publicLogs);
164
139
  }
165
- this.mergeHints(forkedTrace);
166
- }
167
-
168
- private mergeHints(forkedTrace: this) {
169
- this.uniqueClassIds.acceptAndMerge(forkedTrace.uniqueClassIds);
170
- this.avmCircuitHints.enqueuedCalls.push(...forkedTrace.avmCircuitHints.enqueuedCalls);
171
- this.avmCircuitHints.contractInstances.push(...forkedTrace.avmCircuitHints.contractInstances);
172
- this.avmCircuitHints.contractClasses.push(...forkedTrace.avmCircuitHints.contractClasses);
173
- this.avmCircuitHints.publicDataReads.push(...forkedTrace.avmCircuitHints.publicDataReads);
174
- this.avmCircuitHints.publicDataWrites.push(...forkedTrace.avmCircuitHints.publicDataWrites);
175
- this.avmCircuitHints.nullifierReads.push(...forkedTrace.avmCircuitHints.nullifierReads);
176
- this.avmCircuitHints.nullifierWrites.push(...forkedTrace.avmCircuitHints.nullifierWrites);
177
- this.avmCircuitHints.noteHashReads.push(...forkedTrace.avmCircuitHints.noteHashReads);
178
- this.avmCircuitHints.noteHashWrites.push(...forkedTrace.avmCircuitHints.noteHashWrites);
179
- this.avmCircuitHints.l1ToL2MessageReads.push(...forkedTrace.avmCircuitHints.l1ToL2MessageReads);
180
140
  }
181
141
 
182
142
  public getCounter() {
@@ -191,31 +151,11 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
191
151
  return this.previousSideEffectArrayLengths.noteHashes + this.noteHashes.length;
192
152
  }
193
153
 
194
- public tracePublicStorageRead(
195
- contractAddress: AztecAddress,
196
- slot: Fr,
197
- value: Fr,
198
- leafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(),
199
- leafIndex: Fr = Fr.zero(),
200
- path: Fr[] = emptyPublicDataPath(),
201
- ) {
202
- this.avmCircuitHints.publicDataReads.push(new AvmPublicDataReadTreeHint(leafPreimage, leafIndex, path));
203
- this.log.trace(
204
- `Tracing storage read (address=${contractAddress}, slot=${slot}): value=${value} (counter=${this.sideEffectCounter})`,
205
- );
206
- this.incrementSideEffectCounter();
207
- }
208
-
209
154
  public async tracePublicStorageWrite(
210
155
  contractAddress: AztecAddress,
211
156
  slot: Fr,
212
157
  value: Fr,
213
158
  protocolWrite: boolean,
214
- lowLeafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(),
215
- lowLeafIndex: Fr = Fr.zero(),
216
- lowLeafPath: Fr[] = emptyPublicDataPath(),
217
- newLeafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(),
218
- insertionPath: Fr[] = emptyPublicDataPath(),
219
159
  ): Promise<void> {
220
160
  if (protocolWrite) {
221
161
  if (
@@ -244,86 +184,33 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
244
184
  const leafSlot = await computePublicDataTreeLeafSlot(contractAddress, slot);
245
185
  this.publicDataWrites.push(new PublicDataUpdateRequest(leafSlot, value, this.sideEffectCounter));
246
186
 
247
- // New hinting
248
- const readHint = new AvmPublicDataReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath);
249
- this.avmCircuitHints.publicDataWrites.push(
250
- new AvmPublicDataWriteTreeHint(readHint, newLeafPreimage, insertionPath),
251
- );
252
-
253
187
  this.log.trace(
254
188
  `Traced public data write (address=${contractAddress}, slot=${slot}): value=${value} (counter=${this.sideEffectCounter}, isProtocol:${protocolWrite})`,
255
189
  );
256
190
  this.incrementSideEffectCounter();
257
191
  }
258
192
 
259
- // TODO(8287): _exists can be removed once we have the vm properly handling the equality check
260
- public traceNoteHashCheck(
261
- _contractAddress: AztecAddress,
262
- noteHash: Fr,
263
- leafIndex: Fr,
264
- _exists: boolean,
265
- path: Fr[] = emptyNoteHashPath(),
266
- ) {
267
- // New Hinting
268
- this.avmCircuitHints.noteHashReads.push(new AvmAppendTreeHint(leafIndex, noteHash, path));
269
- // NOTE: counter does not increment for note hash checks (because it doesn't rely on pending note hashes)
270
- this.log.trace(`Tracing note hash check (counter=${this.sideEffectCounter})`);
271
- }
272
-
273
- public traceNewNoteHash(noteHash: Fr, leafIndex: Fr = Fr.zero(), path: Fr[] = emptyNoteHashPath()) {
193
+ public traceNewNoteHash(noteHash: Fr) {
274
194
  if (this.noteHashes.length + this.previousSideEffectArrayLengths.noteHashes >= MAX_NOTE_HASHES_PER_TX) {
275
195
  throw new SideEffectLimitReachedError('note hash', MAX_NOTE_HASHES_PER_TX);
276
196
  }
277
197
 
278
198
  this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter));
279
- this.avmCircuitHints.noteHashWrites.push(new AvmAppendTreeHint(leafIndex, noteHash, path));
280
199
  this.log.trace(`Tracing new note hash (counter=${this.sideEffectCounter})`);
281
200
  this.incrementSideEffectCounter();
282
201
  }
283
202
 
284
- public traceNullifierCheck(
285
- _siloedNullifier: Fr,
286
- _exists: boolean,
287
- lowLeafPreimage: NullifierLeafPreimage = NullifierLeafPreimage.empty(),
288
- lowLeafIndex: Fr = Fr.zero(),
289
- lowLeafPath: Fr[] = emptyNullifierPath(),
290
- ) {
291
- this.avmCircuitHints.nullifierReads.push(new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath));
292
- this.log.trace(`Tracing nullifier check (counter=${this.sideEffectCounter})`);
293
- this.incrementSideEffectCounter();
294
- }
295
-
296
- public traceNewNullifier(
297
- siloedNullifier: Fr,
298
- lowLeafPreimage: NullifierLeafPreimage = NullifierLeafPreimage.empty(),
299
- lowLeafIndex: Fr = Fr.zero(),
300
- lowLeafPath: Fr[] = emptyNullifierPath(),
301
- insertionPath: Fr[] = emptyNullifierPath(),
302
- ) {
203
+ public traceNewNullifier(siloedNullifier: Fr) {
303
204
  if (this.nullifiers.length + this.previousSideEffectArrayLengths.nullifiers >= MAX_NULLIFIERS_PER_TX) {
304
205
  throw new SideEffectLimitReachedError('nullifier', MAX_NULLIFIERS_PER_TX);
305
206
  }
306
207
 
307
208
  this.nullifiers.push(new Nullifier(siloedNullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO));
308
209
 
309
- const lowLeafReadHint = new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath);
310
- this.avmCircuitHints.nullifierWrites.push(new AvmNullifierWriteTreeHint(lowLeafReadHint, insertionPath));
311
210
  this.log.trace(`Tracing new nullifier (counter=${this.sideEffectCounter})`);
312
211
  this.incrementSideEffectCounter();
313
212
  }
314
213
 
315
- // TODO(8287): _exists can be removed once we have the vm properly handling the equality check
316
- public traceL1ToL2MessageCheck(
317
- _contractAddress: AztecAddress,
318
- msgHash: Fr,
319
- msgLeafIndex: Fr,
320
- _exists: boolean,
321
- path: Fr[] = emptyL1ToL2MessagePath(),
322
- ) {
323
- this.avmCircuitHints.l1ToL2MessageReads.push(new AvmAppendTreeHint(msgLeafIndex, msgHash, path));
324
- this.log.trace(`Tracing l1 to l2 message check (counter=${this.sideEffectCounter})`);
325
- }
326
-
327
214
  public traceNewL2ToL1Message(contractAddress: AztecAddress, recipient: Fr, content: Fr) {
328
215
  if (this.l2ToL1Messages.length + this.previousSideEffectArrayLengths.l2ToL1Msgs >= MAX_L2_TO_L1_MSGS_PER_TX) {
329
216
  throw new SideEffectLimitReachedError('l2 to l1 message', MAX_L2_TO_L1_MSGS_PER_TX);
@@ -351,37 +238,9 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
351
238
  this.incrementSideEffectCounter();
352
239
  }
353
240
 
354
- public traceGetContractInstance(
355
- contractAddress: AztecAddress,
356
- exists: boolean,
357
- instance: SerializableContractInstance = SerializableContractInstance.default(),
358
- updateMembershipHint: AvmPublicDataReadTreeHint = AvmPublicDataReadTreeHint.empty(),
359
- updatePreimage: Fr[] = [],
360
- ) {
361
- this.avmCircuitHints.contractInstances.push(
362
- new AvmContractInstanceHint(
363
- contractAddress,
364
- exists,
365
- instance.salt,
366
- instance.deployer,
367
- instance.currentContractClassId,
368
- instance.originalContractClassId,
369
- instance.initializationHash,
370
- instance.publicKeys,
371
- updateMembershipHint,
372
- updatePreimage,
373
- ),
374
- );
375
- this.log.trace(`Tracing contract instance retrieval (counter=${this.sideEffectCounter})`);
376
- this.incrementSideEffectCounter();
377
- }
378
-
379
- public traceGetContractClass(contractClassId: Fr, exists: boolean, contractClass?: ContractClassWithCommitment) {
380
- if (!exists) {
381
- this.avmCircuitHints.contractClasses.push(
382
- new AvmContractClassHint(contractClassId, exists, Fr.zero(), Fr.zero(), Fr.zero(), Buffer.alloc(0)),
383
- );
384
- } else if (!this.uniqueClassIds.has(contractClassId.toString())) {
241
+ public traceGetContractClass(contractClassId: Fr, exists: boolean) {
242
+ // We limit the number of unique contract class IDs due to hashing and the trace length limit.
243
+ if (exists && !this.uniqueClassIds.has(contractClassId.toString())) {
385
244
  if (this.uniqueClassIds.size() >= MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS) {
386
245
  this.log.debug(`Bytecode retrieval failure for contract class ID ${contractClassId} (limit reached)`);
387
246
  throw new SideEffectLimitReachedError(
@@ -389,19 +248,8 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
389
248
  MAX_PUBLIC_CALLS_TO_UNIQUE_CONTRACT_CLASS_IDS,
390
249
  );
391
250
  }
392
-
251
+ this.log.trace(`Adding contract class ID ${contractClassId} (counter=${this.sideEffectCounter})`);
393
252
  this.uniqueClassIds.add(contractClassId.toString());
394
- this.avmCircuitHints.contractClasses.push(
395
- new AvmContractClassHint(
396
- contractClassId,
397
- exists,
398
- contractClass!.artifactHash,
399
- contractClass!.privateFunctionsRoot,
400
- contractClass!.publicBytecodeCommitment,
401
- contractClass!.packedBytecode,
402
- ),
403
- );
404
-
405
253
  this.incrementSideEffectCounter();
406
254
  }
407
255
  }
@@ -410,17 +258,9 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
410
258
  * Trace an enqueued call.
411
259
  * Accept some results from a finished call's trace into this one.
412
260
  */
413
- public traceEnqueuedCall(
414
- /** The call request from private that enqueued this call. */
415
- publicCallRequest: PublicCallRequest,
416
- /** The call's calldata */
417
- calldata: Fr[],
418
- /** Did the call revert? */
419
- _reverted: boolean,
420
- ) {
261
+ public traceEnqueuedCall(publicCallRequest: PublicCallRequest) {
421
262
  // TODO(4805): check if some threshold is reached for max enqueued or nested calls (to unique contracts?)
422
263
  this.enqueuedCalls.push(publicCallRequest);
423
- this.avmCircuitHints.enqueuedCalls.push(new AvmEnqueuedCallHint(publicCallRequest.contractAddress, calldata));
424
264
  }
425
265
 
426
266
  public getSideEffects(): SideEffects {
@@ -488,10 +328,6 @@ export class SideEffectTrace implements PublicSideEffectTraceInterface {
488
328
  return this.publicLogs;
489
329
  }
490
330
 
491
- public getAvmCircuitHints() {
492
- return this.avmCircuitHints;
493
- }
494
-
495
331
  private getAvmAccumulatedData() {
496
332
  return new AvmAccumulatedData(
497
333
  padArrayEnd(