@aztec/simulator 0.66.0 → 0.67.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 (125) hide show
  1. package/dest/acvm/acvm.js +3 -3
  2. package/dest/acvm/oracle/oracle.d.ts +1 -1
  3. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  4. package/dest/acvm/oracle/oracle.js +3 -3
  5. package/dest/acvm/oracle/typed_oracle.d.ts +2 -2
  6. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  7. package/dest/acvm/oracle/typed_oracle.js +3 -3
  8. package/dest/acvm/serialize.js +2 -2
  9. package/dest/avm/avm_context.d.ts +2 -2
  10. package/dest/avm/avm_context.d.ts.map +1 -1
  11. package/dest/avm/avm_context.js +3 -4
  12. package/dest/avm/avm_execution_environment.d.ts +4 -6
  13. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  14. package/dest/avm/avm_execution_environment.js +8 -13
  15. package/dest/avm/avm_memory_types.d.ts +2 -2
  16. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  17. package/dest/avm/avm_memory_types.js +3 -3
  18. package/dest/avm/avm_simulator.d.ts +3 -3
  19. package/dest/avm/avm_simulator.d.ts.map +1 -1
  20. package/dest/avm/avm_simulator.js +22 -13
  21. package/dest/avm/errors.d.ts +3 -3
  22. package/dest/avm/errors.d.ts.map +1 -1
  23. package/dest/avm/errors.js +8 -15
  24. package/dest/avm/fixtures/index.d.ts.map +1 -1
  25. package/dest/avm/fixtures/index.js +4 -4
  26. package/dest/avm/journal/journal.d.ts +15 -4
  27. package/dest/avm/journal/journal.d.ts.map +1 -1
  28. package/dest/avm/journal/journal.js +108 -29
  29. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  30. package/dest/avm/opcodes/external_calls.js +4 -11
  31. package/dest/avm/opcodes/misc.d.ts.map +1 -1
  32. package/dest/avm/opcodes/misc.js +3 -3
  33. package/dest/client/client_execution_context.d.ts +3 -3
  34. package/dest/client/client_execution_context.d.ts.map +1 -1
  35. package/dest/client/client_execution_context.js +14 -8
  36. package/dest/client/db_oracle.d.ts +2 -2
  37. package/dest/client/db_oracle.d.ts.map +1 -1
  38. package/dest/client/execution_note_cache.d.ts +9 -1
  39. package/dest/client/execution_note_cache.d.ts.map +1 -1
  40. package/dest/client/execution_note_cache.js +10 -3
  41. package/dest/client/private_execution.d.ts.map +1 -1
  42. package/dest/client/private_execution.js +4 -4
  43. package/dest/client/simulator.d.ts.map +1 -1
  44. package/dest/client/simulator.js +4 -4
  45. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  46. package/dest/client/unconstrained_execution.js +3 -3
  47. package/dest/client/view_data_oracle.d.ts +2 -2
  48. package/dest/client/view_data_oracle.d.ts.map +1 -1
  49. package/dest/client/view_data_oracle.js +5 -6
  50. package/dest/common/debug_fn_name.d.ts +2 -2
  51. package/dest/common/debug_fn_name.d.ts.map +1 -1
  52. package/dest/common/debug_fn_name.js +8 -14
  53. package/dest/providers/acvm_native.js +4 -4
  54. package/dest/providers/factory.d.ts +2 -2
  55. package/dest/providers/factory.d.ts.map +1 -1
  56. package/dest/providers/factory.js +4 -4
  57. package/dest/public/enqueued_call_side_effect_trace.d.ts +11 -23
  58. package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
  59. package/dest/public/enqueued_call_side_effect_trace.js +37 -58
  60. package/dest/public/executor_metrics.d.ts.map +1 -1
  61. package/dest/public/executor_metrics.js +2 -5
  62. package/dest/public/fixtures/index.d.ts +24 -1
  63. package/dest/public/fixtures/index.d.ts.map +1 -1
  64. package/dest/public/fixtures/index.js +15 -9
  65. package/dest/public/index.d.ts +0 -1
  66. package/dest/public/index.d.ts.map +1 -1
  67. package/dest/public/index.js +1 -2
  68. package/dest/public/public_db_sources.d.ts.map +1 -1
  69. package/dest/public/public_db_sources.js +4 -4
  70. package/dest/public/public_processor.d.ts +7 -8
  71. package/dest/public/public_processor.d.ts.map +1 -1
  72. package/dest/public/public_processor.js +30 -22
  73. package/dest/public/public_tx_context.d.ts +13 -10
  74. package/dest/public/public_tx_context.d.ts.map +1 -1
  75. package/dest/public/public_tx_context.js +46 -31
  76. package/dest/public/public_tx_simulator.d.ts +2 -2
  77. package/dest/public/public_tx_simulator.d.ts.map +1 -1
  78. package/dest/public/public_tx_simulator.js +43 -23
  79. package/dest/public/side_effect_trace_interface.d.ts +4 -17
  80. package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
  81. package/dest/public/transitional_adapters.d.ts +2 -2
  82. package/dest/public/transitional_adapters.d.ts.map +1 -1
  83. package/dest/public/transitional_adapters.js +28 -24
  84. package/package.json +16 -9
  85. package/src/acvm/acvm.ts +2 -2
  86. package/src/acvm/oracle/oracle.ts +2 -2
  87. package/src/acvm/oracle/typed_oracle.ts +3 -3
  88. package/src/acvm/serialize.ts +1 -1
  89. package/src/avm/avm_context.ts +2 -3
  90. package/src/avm/avm_execution_environment.ts +6 -31
  91. package/src/avm/avm_memory_types.ts +2 -2
  92. package/src/avm/avm_simulator.ts +24 -20
  93. package/src/avm/errors.ts +12 -14
  94. package/src/avm/fixtures/index.ts +2 -3
  95. package/src/avm/journal/journal.ts +189 -63
  96. package/src/avm/opcodes/external_calls.ts +3 -19
  97. package/src/avm/opcodes/misc.ts +2 -2
  98. package/src/client/client_execution_context.ts +17 -9
  99. package/src/client/db_oracle.ts +2 -2
  100. package/src/client/execution_note_cache.ts +13 -3
  101. package/src/client/private_execution.ts +3 -3
  102. package/src/client/simulator.ts +4 -4
  103. package/src/client/unconstrained_execution.ts +2 -2
  104. package/src/client/view_data_oracle.ts +5 -6
  105. package/src/common/debug_fn_name.ts +7 -13
  106. package/src/providers/acvm_native.ts +3 -3
  107. package/src/providers/factory.ts +3 -3
  108. package/src/public/enqueued_call_side_effect_trace.ts +54 -74
  109. package/src/public/executor_metrics.ts +0 -4
  110. package/src/public/fixtures/index.ts +23 -10
  111. package/src/public/index.ts +0 -1
  112. package/src/public/public_db_sources.ts +3 -3
  113. package/src/public/public_processor.ts +46 -47
  114. package/src/public/public_tx_context.ts +52 -32
  115. package/src/public/public_tx_simulator.ts +58 -38
  116. package/src/public/side_effect_trace_interface.ts +8 -15
  117. package/src/public/transitional_adapters.ts +39 -24
  118. package/dest/public/dual_side_effect_trace.d.ts +0 -77
  119. package/dest/public/dual_side_effect_trace.d.ts.map +0 -1
  120. package/dest/public/dual_side_effect_trace.js +0 -119
  121. package/dest/public/side_effect_trace.d.ts +0 -96
  122. package/dest/public/side_effect_trace.d.ts.map +0 -1
  123. package/dest/public/side_effect_trace.js +0 -309
  124. package/src/public/dual_side_effect_trace.ts +0 -242
  125. package/src/public/side_effect_trace.ts +0 -536
@@ -1,23 +1,27 @@
1
1
  import { MerkleTreeId } from '@aztec/circuit-types';
2
2
  import {
3
- type AztecAddress,
4
- type Gas,
5
- type NullifierLeafPreimage,
3
+ AztecAddress,
4
+ CANONICAL_AUTH_REGISTRY_ADDRESS,
5
+ DEPLOYER_CONTRACT_ADDRESS,
6
+ FEE_JUICE_ADDRESS,
7
+ MULTI_CALL_ENTRYPOINT_ADDRESS,
8
+ NullifierLeafPreimage,
6
9
  type PublicCallRequest,
7
10
  type PublicDataTreeLeafPreimage,
11
+ REGISTERER_CONTRACT_ADDRESS,
12
+ ROUTER_ADDRESS,
8
13
  SerializableContractInstance,
9
14
  } from '@aztec/circuits.js';
10
15
  import { computePublicDataTreeLeafSlot, siloNoteHash, siloNullifier } from '@aztec/circuits.js/hash';
11
16
  import { Fr } from '@aztec/foundation/fields';
12
17
  import { jsonStringify } from '@aztec/foundation/json-rpc';
13
- import { createDebugLogger } from '@aztec/foundation/log';
18
+ import { createLogger } from '@aztec/foundation/log';
14
19
 
15
20
  import { strict as assert } from 'assert';
16
21
 
17
22
  import { getPublicFunctionDebugName } from '../../common/debug_fn_name.js';
18
23
  import { type WorldStateDB } from '../../public/public_db_sources.js';
19
24
  import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js';
20
- import { type AvmContractCallResult } from '../avm_contract_call_result.js';
21
25
  import { type AvmExecutionEnvironment } from '../avm_execution_environment.js';
22
26
  import { AvmEphemeralForest } from '../avm_tree.js';
23
27
  import { NullifierCollisionError, NullifierManager } from './nullifiers.js';
@@ -33,7 +37,7 @@ import { PublicStorage } from './public_storage.js';
33
37
  * Manages merging of successful/reverted child state into current state.
34
38
  */
35
39
  export class AvmPersistableStateManager {
36
- private readonly log = createDebugLogger('aztec:avm_simulator:state_manager');
40
+ private readonly log = createLogger('simulator:avm:state_manager');
37
41
 
38
42
  /** Make sure a forked state is never merged twice. */
39
43
  private alreadyMergedIntoParent = false;
@@ -148,14 +152,16 @@ export class AvmPersistableStateManager {
148
152
  * @param slot - the slot in the contract's storage being written to
149
153
  * @param value - the value being written to the slot
150
154
  */
151
- public async writeStorage(contractAddress: AztecAddress, slot: Fr, value: Fr): Promise<void> {
155
+ public async writeStorage(contractAddress: AztecAddress, slot: Fr, value: Fr, protocolWrite = false): Promise<void> {
152
156
  this.log.debug(`Storage write (address=${contractAddress}, slot=${slot}): value=${value}`);
157
+ const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot);
158
+ this.log.debug(`leafSlot=${leafSlot}`);
153
159
  // Cache storage writes for later reference/reads
154
160
  this.publicStorage.write(contractAddress, slot, value);
155
- const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot);
161
+
156
162
  if (this.doMerkleOperations) {
157
163
  const result = await this.merkleTrees.writePublicStorage(leafSlot, value);
158
- assert(result !== undefined, 'Public data tree insertion error. You might want to disable skipMerkleOperations.');
164
+ assert(result !== undefined, 'Public data tree insertion error. You might want to disable doMerkleOperations.');
159
165
  this.log.debug(`Inserted public data tree leaf at leafSlot ${leafSlot}, value: ${value}`);
160
166
 
161
167
  const lowLeafInfo = result.lowWitness;
@@ -164,16 +170,20 @@ export class AvmPersistableStateManager {
164
170
  const lowLeafPath = lowLeafInfo.siblingPath;
165
171
 
166
172
  const newLeafPreimage = result.element as PublicDataTreeLeafPreimage;
167
- let insertionPath;
168
-
173
+ let insertionPath: Fr[] | undefined;
169
174
  if (!result.update) {
170
175
  insertionPath = result.insertionPath;
176
+ assert(
177
+ newLeafPreimage.value.equals(value),
178
+ `Value mismatch when performing public data write (got value: ${value}, value in ephemeral tree: ${newLeafPreimage.value})`,
179
+ );
171
180
  }
172
181
 
173
182
  this.trace.tracePublicStorageWrite(
174
183
  contractAddress,
175
184
  slot,
176
185
  value,
186
+ protocolWrite,
177
187
  lowLeafPreimage,
178
188
  new Fr(lowLeafIndex),
179
189
  lowLeafPath,
@@ -181,7 +191,7 @@ export class AvmPersistableStateManager {
181
191
  insertionPath,
182
192
  );
183
193
  } else {
184
- this.trace.tracePublicStorageWrite(contractAddress, slot, value);
194
+ this.trace.tracePublicStorageWrite(contractAddress, slot, value, protocolWrite);
185
195
  }
186
196
  }
187
197
 
@@ -195,8 +205,8 @@ export class AvmPersistableStateManager {
195
205
  public async readStorage(contractAddress: AztecAddress, slot: Fr): Promise<Fr> {
196
206
  const { value, cached } = await this.publicStorage.read(contractAddress, slot);
197
207
  this.log.debug(`Storage read (address=${contractAddress}, slot=${slot}): value=${value}, cached=${cached}`);
198
-
199
208
  const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot);
209
+ this.log.debug(`leafSlot=${leafSlot}`);
200
210
 
201
211
  if (this.doMerkleOperations) {
202
212
  // Get leaf if present, low leaf if absent
@@ -211,12 +221,18 @@ export class AvmPersistableStateManager {
211
221
  const leafPath = await this.merkleTrees.getSiblingPath(MerkleTreeId.PUBLIC_DATA_TREE, leafIndex);
212
222
  const leafPreimage = preimage as PublicDataTreeLeafPreimage;
213
223
 
224
+ this.log.debug(`leafPreimage.slot: ${leafPreimage.slot}, leafPreimage.value: ${leafPreimage.value}`);
214
225
  this.log.debug(
215
226
  `leafPreimage.nextSlot: ${leafPreimage.nextSlot}, leafPreimage.nextIndex: ${Number(leafPreimage.nextIndex)}`,
216
227
  );
217
- this.log.debug(`leafPreimage.slot: ${leafPreimage.slot}, leafPreimage.value: ${leafPreimage.value}`);
218
228
 
219
- if (!alreadyPresent) {
229
+ if (alreadyPresent) {
230
+ assert(
231
+ leafPreimage.value.equals(value),
232
+ `Value mismatch when performing public data read (got value: ${value}, value in ephemeral tree: ${leafPreimage.value})`,
233
+ );
234
+ } else {
235
+ this.log.debug(`Slot has never been written before!`);
220
236
  // Sanity check that the leaf slot is skipped by low leaf when it doesn't exist
221
237
  assert(
222
238
  leafPreimage.slot.toBigInt() < leafSlot.toBigInt() &&
@@ -224,9 +240,6 @@ export class AvmPersistableStateManager {
224
240
  'Public data tree low leaf should skip the target leaf slot when the target leaf does not exist or is the max value.',
225
241
  );
226
242
  }
227
- this.log.debug(
228
- `Tracing storage leaf preimage slot=${slot}, leafSlot=${leafSlot}, value=${value}, nextKey=${leafPreimage.nextSlot}, nextIndex=${leafPreimage.nextIndex}`,
229
- );
230
243
  // On non-existence, AVM circuit will need to recognize that leafPreimage.slot != leafSlot,
231
244
  // prove that this is a low leaf that skips leafSlot, and then prove membership of the leaf.
232
245
  this.trace.tracePublicStorageRead(contractAddress, slot, value, leafPreimage, new Fr(leafIndex), leafPath);
@@ -303,8 +316,47 @@ export class AvmPersistableStateManager {
303
316
  public async checkNullifierExists(contractAddress: AztecAddress, nullifier: Fr): Promise<boolean> {
304
317
  this.log.debug(`Checking existence of nullifier (address=${contractAddress}, nullifier=${nullifier})`);
305
318
  const siloedNullifier = siloNullifier(contractAddress, nullifier);
319
+ const [exists, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(
320
+ siloedNullifier,
321
+ );
322
+
323
+ if (this.doMerkleOperations) {
324
+ this.trace.traceNullifierCheck(
325
+ siloedNullifier,
326
+ exists,
327
+ leafOrLowLeafPreimage,
328
+ leafOrLowLeafIndex,
329
+ leafOrLowLeafPath,
330
+ );
331
+ } else {
332
+ this.trace.traceNullifierCheck(siloedNullifier, exists);
333
+ }
334
+ return Promise.resolve(exists);
335
+ }
336
+
337
+ /**
338
+ * Helper to get membership information for a siloed nullifier when checking its existence.
339
+ * Optionally trace the nullifier check.
340
+ *
341
+ * @param siloedNullifier - the siloed nullifier to get membership information for
342
+ * @returns
343
+ * - exists - whether the nullifier exists in the nullifier set
344
+ * - leafOrLowLeafPreimage - the preimage of the nullifier leaf or its low-leaf if it doesn't exist
345
+ * - leafOrLowLeafIndex - the leaf index of the nullifier leaf or its low-leaf if it doesn't exist
346
+ * - leafOrLowLeafPath - the sibling path of the nullifier leaf or its low-leaf if it doesn't exist
347
+ */
348
+ private async getNullifierMembership(
349
+ siloedNullifier: Fr,
350
+ ): Promise<
351
+ [
352
+ /*exists=*/ boolean,
353
+ /*leafOrLowLeafPreimage=*/ NullifierLeafPreimage,
354
+ /*leafOrLowLeafIndex=*/ Fr,
355
+ /*leafOrLowLeafIndexPath=*/ Fr[],
356
+ ]
357
+ > {
306
358
  const [exists, isPending, _] = await this.nullifiers.checkExists(siloedNullifier);
307
- this.log.debug(`Checked siloed nullifier ${siloedNullifier} (exists=${exists}, pending=${isPending})`);
359
+ this.log.debug(`Checked siloed nullifier ${siloedNullifier} (exists=${exists}), pending=${isPending}`);
308
360
 
309
361
  if (this.doMerkleOperations) {
310
362
  // Get leaf if present, low leaf if absent
@@ -319,7 +371,7 @@ export class AvmPersistableStateManager {
319
371
 
320
372
  assert(
321
373
  alreadyPresent == exists,
322
- 'WorldStateDB contains nullifier leaf, but merkle tree does not.... This is a bug!',
374
+ 'WorldStateDB contains nullifier leaf, but merkle tree does not (or vice versa).... This is a bug!',
323
375
  );
324
376
 
325
377
  if (exists) {
@@ -327,17 +379,15 @@ export class AvmPersistableStateManager {
327
379
  } else {
328
380
  // Sanity check that the leaf value is skipped by low leaf when it doesn't exist
329
381
  assert(
330
- siloedNullifier.toBigInt() > leafPreimage.nullifier.toBigInt() &&
331
- siloedNullifier.toBigInt() < leafPreimage.nextNullifier.toBigInt(),
382
+ leafPreimage.nullifier.toBigInt() < siloedNullifier.toBigInt() &&
383
+ (leafPreimage.nextIndex === 0n || leafPreimage.nextNullifier.toBigInt() > siloedNullifier.toBigInt()),
332
384
  'Nullifier tree low leaf should skip the target leaf nullifier when the target leaf does not exist.',
333
385
  );
334
386
  }
335
-
336
- this.trace.traceNullifierCheck(siloedNullifier, exists, leafPreimage, new Fr(leafIndex), leafPath);
387
+ return [exists, leafPreimage, new Fr(leafIndex), leafPath];
337
388
  } else {
338
- this.trace.traceNullifierCheck(siloedNullifier, exists);
389
+ return [exists, NullifierLeafPreimage.empty(), Fr.ZERO, []];
339
390
  }
340
- return Promise.resolve(exists);
341
391
  }
342
392
 
343
393
  /**
@@ -484,18 +534,59 @@ export class AvmPersistableStateManager {
484
534
  const instanceWithAddress = await this.worldStateDB.getContractInstance(contractAddress);
485
535
  const exists = instanceWithAddress !== undefined;
486
536
 
487
- // TODO: nullifier check!
537
+ let [existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = [
538
+ exists,
539
+ NullifierLeafPreimage.empty(),
540
+ Fr.ZERO,
541
+ new Array<Fr>(),
542
+ ];
543
+ if (!contractAddressIsCanonical(contractAddress)) {
544
+ const contractAddressNullifier = siloNullifier(
545
+ AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
546
+ contractAddress.toField(),
547
+ );
548
+ [existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(
549
+ /*siloedNullifier=*/ contractAddressNullifier,
550
+ );
551
+ assert(
552
+ exists == existsInTree,
553
+ 'WorldStateDB contains contract instance, but nullifier tree does not contain contract address (or vice versa).... This is a bug!',
554
+ );
555
+ }
556
+
488
557
  if (exists) {
489
558
  const instance = new SerializableContractInstance(instanceWithAddress);
490
559
  this.log.debug(
491
560
  `Got contract instance (address=${contractAddress}): exists=${exists}, instance=${jsonStringify(instance)}`,
492
561
  );
493
- this.trace.traceGetContractInstance(contractAddress, exists, instance);
562
+ if (this.doMerkleOperations) {
563
+ this.trace.traceGetContractInstance(
564
+ contractAddress,
565
+ exists,
566
+ instance,
567
+ leafOrLowLeafPreimage,
568
+ leafOrLowLeafIndex,
569
+ leafOrLowLeafPath,
570
+ );
571
+ } else {
572
+ this.trace.traceGetContractInstance(contractAddress, exists, instance);
573
+ }
494
574
 
495
575
  return Promise.resolve(instance);
496
576
  } else {
497
577
  this.log.debug(`Contract instance NOT FOUND (address=${contractAddress})`);
498
- this.trace.traceGetContractInstance(contractAddress, exists);
578
+ if (this.doMerkleOperations) {
579
+ this.trace.traceGetContractInstance(
580
+ contractAddress,
581
+ exists,
582
+ /*instance=*/ undefined,
583
+ leafOrLowLeafPreimage,
584
+ leafOrLowLeafIndex,
585
+ leafOrLowLeafPath,
586
+ );
587
+ } else {
588
+ this.trace.traceGetContractInstance(contractAddress, exists);
589
+ }
499
590
  return Promise.resolve(undefined);
500
591
  }
501
592
  }
@@ -508,6 +599,26 @@ export class AvmPersistableStateManager {
508
599
  const instanceWithAddress = await this.worldStateDB.getContractInstance(contractAddress);
509
600
  const exists = instanceWithAddress !== undefined;
510
601
 
602
+ let [existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = [
603
+ exists,
604
+ NullifierLeafPreimage.empty(),
605
+ Fr.ZERO,
606
+ new Array<Fr>(),
607
+ ];
608
+ if (!contractAddressIsCanonical(contractAddress)) {
609
+ const contractAddressNullifier = siloNullifier(
610
+ AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
611
+ contractAddress.toField(),
612
+ );
613
+ [existsInTree, leafOrLowLeafPreimage, leafOrLowLeafIndex, leafOrLowLeafPath] = await this.getNullifierMembership(
614
+ /*siloedNullifier=*/ contractAddressNullifier,
615
+ );
616
+ assert(
617
+ exists == existsInTree,
618
+ 'WorldStateDB contains contract instance, but nullifier tree does not contain contract address (or vice versa).... This is a bug!',
619
+ );
620
+ }
621
+
511
622
  if (exists) {
512
623
  const instance = new SerializableContractInstance(instanceWithAddress);
513
624
  const contractClass = await this.worldStateDB.getContractClass(instance.contractClassId);
@@ -529,51 +640,66 @@ export class AvmPersistableStateManager {
529
640
  publicBytecodeCommitment: bytecodeCommitment,
530
641
  };
531
642
 
532
- this.trace.traceGetBytecode(
533
- contractAddress,
534
- exists,
535
- contractClass.packedBytecode,
536
- instance,
537
- contractClassPreimage,
538
- );
643
+ if (this.doMerkleOperations) {
644
+ this.trace.traceGetBytecode(
645
+ contractAddress,
646
+ exists,
647
+ contractClass.packedBytecode,
648
+ instance,
649
+ contractClassPreimage,
650
+ leafOrLowLeafPreimage,
651
+ leafOrLowLeafIndex,
652
+ leafOrLowLeafPath,
653
+ );
654
+ } else {
655
+ this.trace.traceGetBytecode(
656
+ contractAddress,
657
+ exists,
658
+ contractClass.packedBytecode,
659
+ instance,
660
+ contractClassPreimage,
661
+ );
662
+ }
539
663
 
540
664
  return contractClass.packedBytecode;
541
665
  } else {
542
666
  // If the contract instance is not found, we assume it has not been deployed.
543
667
  // It doesnt matter what the values of the contract instance are in this case, as long as we tag it with exists=false.
544
668
  // This will hint to the avm circuit to just perform the non-membership check on the address and disregard the bytecode hash
545
- this.trace.traceGetBytecode(contractAddress, exists); // bytecode, instance, class undefined
669
+ if (this.doMerkleOperations) {
670
+ this.trace.traceGetBytecode(
671
+ contractAddress,
672
+ exists,
673
+ /*instance=*/ undefined,
674
+ /*contractClass=*/ undefined,
675
+ /*bytecode=*/ undefined,
676
+ leafOrLowLeafPreimage,
677
+ leafOrLowLeafIndex,
678
+ leafOrLowLeafPath,
679
+ );
680
+ } else {
681
+ this.trace.traceGetBytecode(contractAddress, exists); // bytecode, instance, class undefined
682
+ }
546
683
  return undefined;
547
684
  }
548
685
  }
549
686
 
550
- public async traceNestedCall(
551
- forkedState: AvmPersistableStateManager,
552
- nestedEnvironment: AvmExecutionEnvironment,
553
- startGasLeft: Gas,
554
- bytecode: Buffer,
555
- avmCallResults: AvmContractCallResult,
556
- ) {
557
- const functionName = await getPublicFunctionDebugName(
558
- this.worldStateDB,
559
- nestedEnvironment.address,
560
- nestedEnvironment.functionSelector,
561
- nestedEnvironment.calldata,
562
- );
563
-
564
- this.log.verbose(`[AVM] Tracing nested external contract call ${functionName}`);
565
-
566
- this.trace.traceNestedCall(
567
- forkedState.trace,
568
- nestedEnvironment,
569
- startGasLeft,
570
- bytecode,
571
- avmCallResults,
572
- functionName,
573
- );
574
- }
575
-
576
687
  public traceEnqueuedCall(publicCallRequest: PublicCallRequest, calldata: Fr[], reverted: boolean) {
577
688
  this.trace.traceEnqueuedCall(publicCallRequest, calldata, reverted);
578
689
  }
690
+
691
+ public async getPublicFunctionDebugName(avmEnvironment: AvmExecutionEnvironment): Promise<string> {
692
+ return await getPublicFunctionDebugName(this.worldStateDB, avmEnvironment.address, avmEnvironment.calldata);
693
+ }
694
+ }
695
+
696
+ function contractAddressIsCanonical(contractAddress: AztecAddress): boolean {
697
+ return (
698
+ contractAddress.equals(AztecAddress.fromNumber(CANONICAL_AUTH_REGISTRY_ADDRESS)) ||
699
+ contractAddress.equals(AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS)) ||
700
+ contractAddress.equals(AztecAddress.fromNumber(REGISTERER_CONTRACT_ADDRESS)) ||
701
+ contractAddress.equals(AztecAddress.fromNumber(MULTI_CALL_ENTRYPOINT_ADDRESS)) ||
702
+ contractAddress.equals(AztecAddress.fromNumber(FEE_JUICE_ADDRESS)) ||
703
+ contractAddress.equals(AztecAddress.fromNumber(ROUTER_ADDRESS))
704
+ );
579
705
  }
@@ -1,5 +1,3 @@
1
- import { Fr, FunctionSelector, Gas, PUBLIC_DISPATCH_SELECTOR } from '@aztec/circuits.js';
2
-
3
1
  import type { AvmContext } from '../avm_context.js';
4
2
  import { type AvmContractCallResult } from '../avm_contract_call_result.js';
5
3
  import { type Field, TypeTag, Uint1 } from '../avm_memory_types.js';
@@ -45,7 +43,6 @@ abstract class ExternalCall extends Instruction {
45
43
 
46
44
  const callAddress = memory.getAs<Field>(addrOffset);
47
45
  const calldata = memory.getSlice(argsOffset, calldataSize).map(f => f.toFr());
48
- const functionSelector = new Fr(PUBLIC_DISPATCH_SELECTOR);
49
46
  // If we are already in a static call, we propagate the environment.
50
47
  const callType = context.environment.isStaticCall ? 'STATICCALL' : this.type;
51
48
 
@@ -62,15 +59,10 @@ abstract class ExternalCall extends Instruction {
62
59
  const allocatedGas = { l2Gas: allocatedL2Gas, daGas: allocatedDaGas };
63
60
  context.machineState.consumeGas(allocatedGas);
64
61
 
65
- const nestedContext = context.createNestedContractCallContext(
66
- callAddress.toAztecAddress(),
67
- calldata,
68
- allocatedGas,
69
- callType,
70
- FunctionSelector.fromField(functionSelector),
71
- );
62
+ const aztecAddress = callAddress.toAztecAddress();
63
+ const nestedContext = context.createNestedContractCallContext(aztecAddress, calldata, allocatedGas, callType);
72
64
 
73
- const simulator = new AvmSimulator(nestedContext);
65
+ const simulator = await AvmSimulator.build(nestedContext);
74
66
  const nestedCallResults: AvmContractCallResult = await simulator.execute();
75
67
  const success = !nestedCallResults.reverted;
76
68
 
@@ -102,14 +94,6 @@ abstract class ExternalCall extends Instruction {
102
94
  } else {
103
95
  context.persistableState.reject(nestedContext.persistableState);
104
96
  }
105
- await context.persistableState.traceNestedCall(
106
- /*nestedState=*/ nestedContext.persistableState,
107
- /*nestedEnvironment=*/ nestedContext.environment,
108
- /*startGasLeft=*/ Gas.from(allocatedGas),
109
- /*bytecode=*/ simulator.getBytecode()!,
110
- /*avmCallResults=*/ nestedCallResults,
111
- );
112
-
113
97
  memory.assert({ reads: calldataSize + 4, writes: 1, addressing });
114
98
  }
115
99
 
@@ -1,4 +1,4 @@
1
- import { applyStringFormatting, createDebugLogger } from '@aztec/foundation/log';
1
+ import { applyStringFormatting, createLogger } from '@aztec/foundation/log';
2
2
 
3
3
  import { type AvmContext } from '../avm_context.js';
4
4
  import { TypeTag } from '../avm_memory_types.js';
@@ -9,7 +9,7 @@ import { Instruction } from './instruction.js';
9
9
  export class DebugLog extends Instruction {
10
10
  static type: string = 'DEBUGLOG';
11
11
  static readonly opcode: Opcode = Opcode.DEBUGLOG;
12
- static readonly logger = createDebugLogger('aztec:avm_simulator:debug_log');
12
+ static readonly logger = createLogger('simulator:avm:debug_log');
13
13
 
14
14
  // Informs (de)serialization. See Instruction.deserialize.
15
15
  static readonly wireFormat: OperandType[] = [
@@ -11,9 +11,9 @@ import {
11
11
  type UnencryptedL2Log,
12
12
  } from '@aztec/circuit-types';
13
13
  import {
14
+ type BlockHeader,
14
15
  CallContext,
15
16
  FunctionSelector,
16
- type Header,
17
17
  PRIVATE_CONTEXT_INPUTS_LENGTH,
18
18
  PUBLIC_DISPATCH_SELECTOR,
19
19
  PrivateContextInputs,
@@ -23,7 +23,7 @@ import { computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash';
23
23
  import { type FunctionAbi, type FunctionArtifact, type NoteSelector, countArgumentsSize } from '@aztec/foundation/abi';
24
24
  import { AztecAddress } from '@aztec/foundation/aztec-address';
25
25
  import { Fr } from '@aztec/foundation/fields';
26
- import { applyStringFormatting, createDebugLogger } from '@aztec/foundation/log';
26
+ import { applyStringFormatting, createLogger } from '@aztec/foundation/log';
27
27
 
28
28
  import { type NoteData, toACVMWitness } from '../acvm/index.js';
29
29
  import { type PackedValuesCache } from '../common/packed_values_cache.js';
@@ -66,7 +66,7 @@ export class ClientExecutionContext extends ViewDataOracle {
66
66
  private readonly txContext: TxContext,
67
67
  private readonly callContext: CallContext,
68
68
  /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
69
- protected readonly historicalHeader: Header,
69
+ protected readonly historicalHeader: BlockHeader,
70
70
  /** List of transient auth witnesses to be used during this simulation */
71
71
  authWitnesses: AuthWitness[],
72
72
  private readonly packedValuesCache: PackedValuesCache,
@@ -74,7 +74,7 @@ export class ClientExecutionContext extends ViewDataOracle {
74
74
  db: DBOracle,
75
75
  private node: AztecNode,
76
76
  protected sideEffectCounter: number = 0,
77
- log = createDebugLogger('aztec:simulator:client_execution_context'),
77
+ log = createLogger('simulator:client_execution_context'),
78
78
  scopes?: AztecAddress[],
79
79
  ) {
80
80
  super(callContext.contractAddress, authWitnesses, db, node, log, scopes);
@@ -247,9 +247,10 @@ export class ClientExecutionContext extends ViewDataOracle {
247
247
 
248
248
  notes.forEach(n => {
249
249
  if (n.index !== undefined) {
250
- const uniqueNoteHash = computeUniqueNoteHash(n.nonce, n.noteHash);
251
- const siloedNoteHash = siloNoteHash(n.contractAddress, uniqueNoteHash);
252
- this.noteHashLeafIndexMap.set(siloedNoteHash.toBigInt(), n.index);
250
+ const siloedNoteHash = siloNoteHash(n.contractAddress, n.noteHash);
251
+ const uniqueNoteHash = computeUniqueNoteHash(n.nonce, siloedNoteHash);
252
+
253
+ this.noteHashLeafIndexMap.set(uniqueNoteHash.toBigInt(), n.index);
253
254
  }
254
255
  });
255
256
 
@@ -419,7 +420,14 @@ export class ClientExecutionContext extends ViewDataOracle {
419
420
  const args = this.packedValuesCache.unpack(argsHash);
420
421
 
421
422
  this.log.verbose(
422
- `Created PublicExecutionRequest to ${targetArtifact.name}@${targetContractAddress}, of type [${callType}], side-effect counter [${sideEffectCounter}]`,
423
+ `Created ${callType} public execution request to ${targetArtifact.name}@${targetContractAddress}`,
424
+ {
425
+ sideEffectCounter,
426
+ isStaticCall,
427
+ functionSelector,
428
+ targetContractAddress,
429
+ callType,
430
+ },
423
431
  );
424
432
 
425
433
  const request = PublicExecutionRequest.from({
@@ -537,7 +545,7 @@ export class ClientExecutionContext extends ViewDataOracle {
537
545
  }
538
546
 
539
547
  public override debugLog(message: string, fields: Fr[]) {
540
- this.log.verbose(`debug_log ${applyStringFormatting(message, fields)}`);
548
+ this.log.verbose(`${applyStringFormatting(message, fields)}`, { module: `${this.log.module}:debug_log` });
541
549
  }
542
550
 
543
551
  public getDebugFunctionName() {
@@ -8,9 +8,9 @@ import {
8
8
  type TxScopedL2Log,
9
9
  } from '@aztec/circuit-types';
10
10
  import {
11
+ type BlockHeader,
11
12
  type CompleteAddress,
12
13
  type ContractInstance,
13
- type Header,
14
14
  type IndexedTaggingSecret,
15
15
  type KeyValidationRequest,
16
16
  } from '@aztec/circuits.js';
@@ -138,7 +138,7 @@ export interface DBOracle extends CommitmentsDB {
138
138
  *
139
139
  * @returns A Promise that resolves to a Header object.
140
140
  */
141
- getHeader(): Promise<Header>;
141
+ getBlockHeader(): Promise<BlockHeader>;
142
142
 
143
143
  /**
144
144
  * Fetch the index of the leaf in the respective tree
@@ -1,6 +1,6 @@
1
1
  import { computeNoteHashNonce, computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/circuits.js/hash';
2
2
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
3
- import { type Fr } from '@aztec/foundation/fields';
3
+ import { Fr } from '@aztec/foundation/fields';
4
4
 
5
5
  import { type NoteData } from '../acvm/index.js';
6
6
 
@@ -51,11 +51,11 @@ export class ExecutionNoteCache {
51
51
  // The nonces will be used to create the "complete" nullifier.
52
52
  const updatedNotes = this.notes.map(({ note, counter }, i) => {
53
53
  const nonce = computeNoteHashNonce(this.txHash, i);
54
- const uniqueNoteHash = computeUniqueNoteHash(nonce, note.noteHash);
54
+ const uniqueNoteHash = computeUniqueNoteHash(nonce, siloNoteHash(note.contractAddress, note.noteHash));
55
55
  return {
56
56
  counter,
57
57
  note: { ...note, nonce },
58
- noteHashForConsumption: siloNoteHash(note.contractAddress, uniqueNoteHash),
58
+ noteHashForConsumption: uniqueNoteHash,
59
59
  };
60
60
  });
61
61
  // Rebuild the data.
@@ -146,4 +146,14 @@ export class ExecutionNoteCache {
146
146
  notes.push(note);
147
147
  this.noteMap.set(note.note.contractAddress.toBigInt(), notes);
148
148
  }
149
+
150
+ getAllNotes(): PendingNote[] {
151
+ return this.notes;
152
+ }
153
+
154
+ getAllNullifiers(): Fr[] {
155
+ return [...this.nullifierMap.values()].flatMap(nullifierArray =>
156
+ [...nullifierArray.values()].map(val => new Fr(val)),
157
+ );
158
+ }
149
159
  }
@@ -8,7 +8,7 @@ import {
8
8
  } from '@aztec/circuits.js';
9
9
  import { type FunctionArtifact, type FunctionSelector, countArgumentsSize } from '@aztec/foundation/abi';
10
10
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
11
- import { createDebugLogger } from '@aztec/foundation/log';
11
+ import { createLogger } from '@aztec/foundation/log';
12
12
  import { Timer } from '@aztec/foundation/timer';
13
13
 
14
14
  import { fromACVMField, witnessMapToFields } from '../acvm/deserialize.js';
@@ -24,10 +24,10 @@ export async function executePrivateFunction(
24
24
  artifact: FunctionArtifact,
25
25
  contractAddress: AztecAddress,
26
26
  functionSelector: FunctionSelector,
27
- log = createDebugLogger('aztec:simulator:private_execution'),
27
+ log = createLogger('simulator:private_execution'),
28
28
  ): Promise<PrivateExecutionResult> {
29
29
  const functionName = await context.getDebugFunctionName();
30
- log.verbose(`Executing external function ${functionName}@${contractAddress}`);
30
+ log.verbose(`Executing private function ${functionName}@${contractAddress}`);
31
31
  const acir = artifact.bytecode;
32
32
  const initialWitness = context.getInitialWitness(artifact);
33
33
  const acvmCallback = new Oracle(context);
@@ -10,7 +10,7 @@ import {
10
10
  } from '@aztec/foundation/abi';
11
11
  import { AztecAddress } from '@aztec/foundation/aztec-address';
12
12
  import { Fr } from '@aztec/foundation/fields';
13
- import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
13
+ import { type Logger, createLogger } from '@aztec/foundation/log';
14
14
 
15
15
  import { createSimulationError } from '../common/errors.js';
16
16
  import { PackedValuesCache } from '../common/packed_values_cache.js';
@@ -25,10 +25,10 @@ import { ViewDataOracle } from './view_data_oracle.js';
25
25
  * The ACIR simulator.
26
26
  */
27
27
  export class AcirSimulator {
28
- private log: DebugLogger;
28
+ private log: Logger;
29
29
 
30
30
  constructor(private db: DBOracle, private node: AztecNode) {
31
- this.log = createDebugLogger('aztec:simulator');
31
+ this.log = createLogger('simulator');
32
32
  }
33
33
 
34
34
  /**
@@ -57,7 +57,7 @@ export class AcirSimulator {
57
57
  );
58
58
  }
59
59
 
60
- const header = await this.db.getHeader();
60
+ const header = await this.db.getBlockHeader();
61
61
 
62
62
  // reserve the first side effect for the tx hash (inserted by the private kernel)
63
63
  const startSideEffectCounter = 1;
@@ -1,7 +1,7 @@
1
1
  import { type AbiDecoded, type FunctionArtifact, type FunctionSelector, decodeFromAbi } from '@aztec/foundation/abi';
2
2
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
3
3
  import { type Fr } from '@aztec/foundation/fields';
4
- import { createDebugLogger } from '@aztec/foundation/log';
4
+ import { createLogger } from '@aztec/foundation/log';
5
5
 
6
6
  import { witnessMapToFields } from '../acvm/deserialize.js';
7
7
  import { Oracle, acvm, extractCallStack, toACVMWitness } from '../acvm/index.js';
@@ -18,7 +18,7 @@ export async function executeUnconstrainedFunction(
18
18
  contractAddress: AztecAddress,
19
19
  functionSelector: FunctionSelector,
20
20
  args: Fr[],
21
- log = createDebugLogger('aztec:simulator:unconstrained_execution'),
21
+ log = createLogger('simulator:unconstrained_execution'),
22
22
  ): Promise<AbiDecoded> {
23
23
  log.verbose(`Executing unconstrained function ${contractAddress}:${functionSelector}(${artifact.name})`);
24
24