@aztec/simulator 0.69.1 → 0.70.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 (137) hide show
  1. package/dest/acvm/acvm.d.ts +1 -2
  2. package/dest/acvm/acvm.d.ts.map +1 -1
  3. package/dest/acvm/acvm.js +12 -2
  4. package/dest/acvm/index.d.ts +1 -1
  5. package/dest/acvm/index.d.ts.map +1 -1
  6. package/dest/acvm/index.js +2 -2
  7. package/dest/acvm/oracle/oracle.d.ts +13 -5
  8. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  9. package/dest/acvm/oracle/oracle.js +46 -21
  10. package/dest/acvm/oracle/typed_oracle.d.ts +8 -17
  11. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  12. package/dest/acvm/oracle/typed_oracle.js +16 -23
  13. package/dest/avm/avm_simulator.d.ts.map +1 -1
  14. package/dest/avm/avm_simulator.js +7 -1
  15. package/dest/avm/fixtures/index.d.ts +2 -3
  16. package/dest/avm/fixtures/index.d.ts.map +1 -1
  17. package/dest/avm/fixtures/index.js +4 -4
  18. package/dest/avm/journal/journal.d.ts +3 -4
  19. package/dest/avm/journal/journal.d.ts.map +1 -1
  20. package/dest/avm/journal/journal.js +11 -10
  21. package/dest/avm/journal/nullifiers.d.ts +1 -1
  22. package/dest/avm/journal/nullifiers.d.ts.map +1 -1
  23. package/dest/avm/journal/public_storage.d.ts +1 -1
  24. package/dest/avm/journal/public_storage.d.ts.map +1 -1
  25. package/dest/client/client_execution_context.d.ts +29 -18
  26. package/dest/client/client_execution_context.d.ts.map +1 -1
  27. package/dest/client/client_execution_context.js +42 -29
  28. package/dest/client/db_oracle.d.ts +24 -16
  29. package/dest/client/db_oracle.d.ts.map +1 -1
  30. package/dest/client/db_oracle.js +1 -1
  31. package/dest/client/execution_note_cache.d.ts +27 -4
  32. package/dest/client/execution_note_cache.d.ts.map +1 -1
  33. package/dest/client/execution_note_cache.js +62 -12
  34. package/dest/client/index.d.ts +11 -3
  35. package/dest/client/index.d.ts.map +1 -1
  36. package/dest/client/index.js +11 -4
  37. package/dest/client/private_execution.d.ts +3 -2
  38. package/dest/client/private_execution.d.ts.map +1 -1
  39. package/dest/client/private_execution.js +9 -7
  40. package/dest/client/simulator.d.ts +4 -2
  41. package/dest/client/simulator.d.ts.map +1 -1
  42. package/dest/client/simulator.js +13 -8
  43. package/dest/client/unconstrained_execution.d.ts +2 -1
  44. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  45. package/dest/client/unconstrained_execution.js +6 -4
  46. package/dest/client/view_data_oracle.d.ts +4 -10
  47. package/dest/client/view_data_oracle.d.ts.map +1 -1
  48. package/dest/client/view_data_oracle.js +17 -19
  49. package/dest/common/hashed_values_cache.d.ts +28 -0
  50. package/dest/common/hashed_values_cache.d.ts.map +1 -0
  51. package/dest/common/{packed_values_cache.js → hashed_values_cache.js} +22 -22
  52. package/dest/common/index.d.ts +1 -1
  53. package/dest/common/index.js +1 -1
  54. package/dest/common/message_load_oracle_inputs.d.ts +15 -0
  55. package/dest/common/message_load_oracle_inputs.d.ts.map +1 -0
  56. package/dest/common/message_load_oracle_inputs.js +15 -0
  57. package/dest/common/simulation_provider.d.ts +19 -0
  58. package/dest/common/simulation_provider.d.ts.map +1 -0
  59. package/dest/common/simulation_provider.js +27 -0
  60. package/dest/common.d.ts +2 -0
  61. package/dest/common.d.ts.map +1 -0
  62. package/dest/common.js +2 -0
  63. package/dest/providers/acvm_native.d.ts +5 -2
  64. package/dest/providers/acvm_native.d.ts.map +1 -1
  65. package/dest/providers/acvm_native.js +5 -2
  66. package/dest/providers/acvm_wasm.d.ts +8 -2
  67. package/dest/providers/acvm_wasm.d.ts.map +1 -1
  68. package/dest/providers/acvm_wasm.js +31 -5
  69. package/dest/providers/acvm_wasm_with_blobs.d.ts +14 -2
  70. package/dest/providers/acvm_wasm_with_blobs.d.ts.map +1 -1
  71. package/dest/providers/acvm_wasm_with_blobs.js +25 -5
  72. package/dest/providers/factory.d.ts +1 -1
  73. package/dest/providers/factory.d.ts.map +1 -1
  74. package/dest/providers/factory.js +1 -1
  75. package/dest/providers/index.d.ts +1 -1
  76. package/dest/providers/index.d.ts.map +1 -1
  77. package/dest/providers/index.js +2 -2
  78. package/dest/public/db_interfaces.d.ts +1 -1
  79. package/dest/public/db_interfaces.d.ts.map +1 -1
  80. package/dest/public/fixtures/index.d.ts +3 -3
  81. package/dest/public/fixtures/index.d.ts.map +1 -1
  82. package/dest/public/fixtures/index.js +48 -18
  83. package/dest/public/public_db_sources.d.ts +2 -1
  84. package/dest/public/public_db_sources.d.ts.map +1 -1
  85. package/dest/public/public_db_sources.js +2 -2
  86. package/dest/public/public_processor.js +2 -2
  87. package/dest/public/public_tx_context.d.ts +3 -7
  88. package/dest/public/public_tx_context.d.ts.map +1 -1
  89. package/dest/public/public_tx_context.js +7 -20
  90. package/dest/public/public_tx_simulator.js +5 -5
  91. package/{src/index.ts → dest/server.d.ts} +1 -2
  92. package/dest/server.d.ts.map +1 -0
  93. package/dest/server.js +6 -0
  94. package/package.json +11 -12
  95. package/src/acvm/acvm.ts +20 -3
  96. package/src/acvm/index.ts +1 -1
  97. package/src/acvm/oracle/oracle.ts +48 -27
  98. package/src/acvm/oracle/typed_oracle.ts +20 -24
  99. package/src/avm/avm_simulator.ts +6 -0
  100. package/src/avm/fixtures/index.ts +5 -4
  101. package/src/avm/journal/journal.ts +9 -9
  102. package/src/avm/journal/nullifiers.ts +1 -1
  103. package/src/avm/journal/public_storage.ts +1 -1
  104. package/src/client/client_execution_context.ts +47 -30
  105. package/src/client/db_oracle.ts +25 -17
  106. package/src/client/execution_note_cache.ts +67 -14
  107. package/src/client/index.ts +11 -3
  108. package/src/client/private_execution.ts +21 -17
  109. package/src/client/simulator.ts +20 -7
  110. package/src/client/unconstrained_execution.ts +17 -13
  111. package/src/client/view_data_oracle.ts +23 -19
  112. package/src/common/hashed_values_cache.ts +55 -0
  113. package/src/common/index.ts +1 -1
  114. package/src/common/message_load_oracle_inputs.ts +15 -0
  115. package/src/common/simulation_provider.ts +45 -0
  116. package/src/common.ts +1 -0
  117. package/src/providers/acvm_native.ts +12 -2
  118. package/src/providers/acvm_wasm.ts +36 -9
  119. package/src/providers/acvm_wasm_with_blobs.ts +35 -10
  120. package/src/providers/factory.ts +1 -1
  121. package/src/providers/index.ts +1 -1
  122. package/src/public/db_interfaces.ts +1 -1
  123. package/src/public/fixtures/index.ts +62 -26
  124. package/src/public/public_db_sources.ts +3 -6
  125. package/src/public/public_processor.ts +1 -1
  126. package/src/public/public_tx_context.ts +6 -19
  127. package/src/public/public_tx_simulator.ts +4 -4
  128. package/{dest/index.d.ts → src/server.ts} +0 -3
  129. package/dest/common/packed_values_cache.d.ts +0 -28
  130. package/dest/common/packed_values_cache.d.ts.map +0 -1
  131. package/dest/index.d.ts.map +0 -1
  132. package/dest/index.js +0 -8
  133. package/dest/providers/simulation_provider.d.ts +0 -9
  134. package/dest/providers/simulation_provider.d.ts.map +0 -1
  135. package/dest/providers/simulation_provider.js +0 -2
  136. package/src/common/packed_values_cache.ts +0 -55
  137. package/src/providers/simulation_provider.ts +0 -10
@@ -2,12 +2,15 @@ import { MerkleTreeId, UnencryptedL2Log } from '@aztec/circuit-types';
2
2
  import { FunctionSelector, NoteSelector } from '@aztec/foundation/abi';
3
3
  import { AztecAddress } from '@aztec/foundation/aztec-address';
4
4
  import { Fr } from '@aztec/foundation/fields';
5
+ import { createLogger } from '@aztec/foundation/log';
5
6
 
6
7
  import { type ACVMField } from '../acvm_types.js';
7
8
  import { frToBoolean, frToNumber, fromACVMField } from '../deserialize.js';
8
9
  import { toACVMField } from '../serialize.js';
9
10
  import { type TypedOracle } from './typed_oracle.js';
10
11
 
12
+ const logger = createLogger('simulator:acvm:oracle');
13
+
11
14
  /**
12
15
  * A data source that has all the apis required by Aztec.nr.
13
16
  */
@@ -19,25 +22,20 @@ export class Oracle {
19
22
  return toACVMField(val);
20
23
  }
21
24
 
22
- async packArgumentsArray(args: ACVMField[]): Promise<ACVMField> {
23
- const packed = await this.typedOracle.packArgumentsArray(args.map(fromACVMField));
24
- return toACVMField(packed);
25
- }
26
-
27
- async packArguments(_length: ACVMField[], values: ACVMField[]): Promise<ACVMField> {
28
- const packed = await this.typedOracle.packArgumentsArray(values.map(fromACVMField));
29
- return toACVMField(packed);
25
+ async storeArrayInExecutionCache(values: ACVMField[]): Promise<ACVMField> {
26
+ const hash = await this.typedOracle.storeArrayInExecutionCache(values.map(fromACVMField));
27
+ return toACVMField(hash);
30
28
  }
31
29
 
32
30
  // Since the argument is a slice, noir automatically adds a length field to oracle call.
33
- async packReturns(_length: ACVMField[], values: ACVMField[]): Promise<ACVMField> {
34
- const packed = await this.typedOracle.packReturns(values.map(fromACVMField));
35
- return toACVMField(packed);
31
+ async storeInExecutionCache(_length: ACVMField[], values: ACVMField[]): Promise<ACVMField> {
32
+ const hash = await this.typedOracle.storeInExecutionCache(values.map(fromACVMField));
33
+ return toACVMField(hash);
36
34
  }
37
35
 
38
- async unpackReturns([returnsHash]: ACVMField[]): Promise<ACVMField[]> {
39
- const unpacked = await this.typedOracle.unpackReturns(fromACVMField(returnsHash));
40
- return unpacked.map(toACVMField);
36
+ async loadFromExecutionCache([returnsHash]: ACVMField[]): Promise<ACVMField[]> {
37
+ const values = await this.typedOracle.loadFromExecutionCache(fromACVMField(returnsHash));
38
+ return values.map(toACVMField);
41
39
  }
42
40
 
43
41
  async getBlockNumber(): Promise<ACVMField> {
@@ -92,19 +90,6 @@ export class Oracle {
92
90
  return witness.map(toACVMField);
93
91
  }
94
92
 
95
- async getSiblingPath(
96
- [blockNumber]: ACVMField[],
97
- [treeId]: ACVMField[],
98
- [leafIndex]: ACVMField[],
99
- ): Promise<ACVMField[]> {
100
- const parsedBlockNumber = frToNumber(fromACVMField(blockNumber));
101
- const parsedTreeId = frToNumber(fromACVMField(treeId));
102
- const parsedLeafIndex = fromACVMField(leafIndex);
103
-
104
- const path = await this.typedOracle.getSiblingPath(parsedBlockNumber, parsedTreeId, parsedLeafIndex);
105
- return path.map(toACVMField);
106
- }
107
-
108
93
  async getNullifierMembershipWitness(
109
94
  [blockNumber]: ACVMField[],
110
95
  [nullifier]: ACVMField[], // nullifier, we try to find the witness for (to prove inclusion)
@@ -268,6 +253,11 @@ export class Oracle {
268
253
  return toACVMField(0);
269
254
  }
270
255
 
256
+ async notifyCreatedNullifier([innerNullifier]: ACVMField[]): Promise<ACVMField> {
257
+ await this.typedOracle.notifyCreatedNullifier(fromACVMField(innerNullifier));
258
+ return toACVMField(0);
259
+ }
260
+
271
261
  async checkNullifierExists([innerNullifier]: ACVMField[]): Promise<ACVMField> {
272
262
  const exists = await this.typedOracle.checkNullifierExists(fromACVMField(innerNullifier));
273
263
  return toACVMField(exists);
@@ -393,4 +383,35 @@ export class Oracle {
393
383
  async syncNotes() {
394
384
  await this.typedOracle.syncNotes();
395
385
  }
386
+
387
+ async store([contract]: ACVMField[], [key]: ACVMField[], values: ACVMField[]) {
388
+ const processedContract = AztecAddress.fromField(fromACVMField(contract));
389
+ const processedKey = fromACVMField(key);
390
+ const processedValues = values.map(fromACVMField);
391
+ logger.debug(`Storing data for key ${processedKey} in contract ${processedContract}. Data: [${processedValues}]`);
392
+ await this.typedOracle.store(processedContract, processedKey, processedValues);
393
+ }
394
+
395
+ /**
396
+ * Load data from pxe db.
397
+ * @param contract - The contract address.
398
+ * @param key - The key to load.
399
+ * @param tSize - The size of the serialized object to return.
400
+ * @returns The data found flag and the serialized object concatenated in one array.
401
+ */
402
+ async load([contract]: ACVMField[], [key]: ACVMField[], [tSize]: ACVMField[]): Promise<(ACVMField | ACVMField[])[]> {
403
+ const processedContract = AztecAddress.fromField(fromACVMField(contract));
404
+ const processedKey = fromACVMField(key);
405
+ const values = await this.typedOracle.load(processedContract, processedKey);
406
+ if (values === null) {
407
+ // No data was found so we set the data-found flag to 0 and we pad with zeros get the correct return size.
408
+ const processedTSize = frToNumber(fromACVMField(tSize));
409
+ logger.debug(`No data found for key ${processedKey} in contract ${processedContract}`);
410
+ return [toACVMField(0), Array(processedTSize).fill(toACVMField(0))];
411
+ } else {
412
+ // Data was found so we set the data-found flag to 1 and return it along with the data.
413
+ logger.debug(`Returning data for key ${processedKey} in contract ${processedContract}. Data: [${values}]`);
414
+ return [toACVMField(1), values.map(toACVMField)];
415
+ }
416
+ }
396
417
  }
@@ -5,7 +5,6 @@ import {
5
5
  type NoteStatus,
6
6
  type NullifierMembershipWitness,
7
7
  type PublicDataWitness,
8
- type SiblingPath,
9
8
  type UnencryptedL2Log,
10
9
  } from '@aztec/circuit-types';
11
10
  import {
@@ -19,6 +18,8 @@ import { type FunctionSelector, type NoteSelector } from '@aztec/foundation/abi'
19
18
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
20
19
  import { Fr } from '@aztec/foundation/fields';
21
20
 
21
+ import { type MessageLoadOracleInputs } from '../../common/message_load_oracle_inputs.js';
22
+
22
23
  /**
23
24
  * Information about a note needed during execution.
24
25
  */
@@ -39,19 +40,6 @@ export interface NoteData {
39
40
  index?: bigint;
40
41
  }
41
42
 
42
- export class MessageLoadOracleInputs<N extends number> {
43
- constructor(
44
- /** The index of the message commitment in the merkle tree. */
45
- public index: bigint,
46
- /** The path in the merkle tree to the message. */
47
- public siblingPath: SiblingPath<N>,
48
- ) {}
49
-
50
- toFields(): Fr[] {
51
- return [new Fr(this.index), ...this.siblingPath.toFields()];
52
- }
53
- }
54
-
55
43
  class OracleMethodNotAvailableError extends Error {
56
44
  constructor(methodName: string) {
57
45
  super(`Oracle method ${methodName} is not available.`);
@@ -68,16 +56,16 @@ export abstract class TypedOracle {
68
56
  return Fr.random();
69
57
  }
70
58
 
71
- packArgumentsArray(_args: Fr[]): Promise<Fr> {
72
- throw new OracleMethodNotAvailableError('packArgumentsArray');
59
+ storeArrayInExecutionCache(_args: Fr[]): Promise<Fr> {
60
+ throw new OracleMethodNotAvailableError('storeArrayInExecutionCache');
73
61
  }
74
62
 
75
- packReturns(_returns: Fr[]): Promise<Fr> {
76
- throw new OracleMethodNotAvailableError('packReturns');
63
+ storeInExecutionCache(_values: Fr[]): Promise<Fr> {
64
+ throw new OracleMethodNotAvailableError('storeInExecutionCache');
77
65
  }
78
66
 
79
- unpackReturns(_returnsHash: Fr): Promise<Fr[]> {
80
- throw new OracleMethodNotAvailableError('unpackReturns');
67
+ loadFromExecutionCache(_hash: Fr): Promise<Fr[]> {
68
+ throw new OracleMethodNotAvailableError('loadFromExecutionCache');
81
69
  }
82
70
 
83
71
  getBlockNumber(): Promise<number> {
@@ -108,10 +96,6 @@ export abstract class TypedOracle {
108
96
  throw new OracleMethodNotAvailableError('getMembershipWitness');
109
97
  }
110
98
 
111
- getSiblingPath(_blockNumber: number, _treeId: MerkleTreeId, _leafIndex: Fr): Promise<Fr[]> {
112
- throw new OracleMethodNotAvailableError('getSiblingPath');
113
- }
114
-
115
99
  getNullifierMembershipWitness(_blockNumber: number, _nullifier: Fr): Promise<NullifierMembershipWitness | undefined> {
116
100
  throw new OracleMethodNotAvailableError('getNullifierMembershipWitness');
117
101
  }
@@ -170,6 +154,10 @@ export abstract class TypedOracle {
170
154
  throw new OracleMethodNotAvailableError('notifyNullifiedNote');
171
155
  }
172
156
 
157
+ notifyCreatedNullifier(_innerNullifier: Fr): Promise<void> {
158
+ throw new OracleMethodNotAvailableError('notifyCreatedNullifier');
159
+ }
160
+
173
161
  checkNullifierExists(_innerNullifier: Fr): Promise<boolean> {
174
162
  throw new OracleMethodNotAvailableError('checkNullifierExists');
175
163
  }
@@ -248,4 +236,12 @@ export abstract class TypedOracle {
248
236
  syncNotes(): Promise<void> {
249
237
  throw new OracleMethodNotAvailableError('syncNotes');
250
238
  }
239
+
240
+ store(_contract: AztecAddress, _key: Fr, _values: Fr[]): Promise<void> {
241
+ throw new OracleMethodNotAvailableError('store');
242
+ }
243
+
244
+ load(_contract: AztecAddress, _key: Fr): Promise<Fr[] | null> {
245
+ throw new OracleMethodNotAvailableError('load');
246
+ }
251
247
  }
@@ -137,6 +137,7 @@ export class AvmSimulator {
137
137
  this.bytecode = bytecode;
138
138
 
139
139
  const { machineState } = this.context;
140
+ const callStartGas = machineState.gasLeft; // Save gas before executing instruction (for profiling)
140
141
  try {
141
142
  // Execute instruction pointed to by the current program counter
142
143
  // continuing until the machine state signifies a halt
@@ -180,6 +181,11 @@ export class AvmSimulator {
180
181
  const revertReason = reverted ? await revertReasonFromExplicitRevert(output, this.context) : undefined;
181
182
  const results = new AvmContractCallResult(reverted, output, machineState.gasLeft, revertReason);
182
183
  this.log.debug(`Context execution results: ${results.toString()}`);
184
+ const totalGasUsed: Gas = {
185
+ l2Gas: callStartGas.l2Gas - machineState.l2GasLeft,
186
+ daGas: callStartGas.daGas - machineState.daGasLeft,
187
+ };
188
+ this.log.debug(`Executed ${instrCounter} instructions and consumed ${totalGasUsed.l2Gas} L2 Gas`);
183
189
 
184
190
  this.tallyPrintFunction();
185
191
  // Return results for processing by calling context
@@ -1,4 +1,4 @@
1
- import { TxHash, isNoirCallStackUnresolved } from '@aztec/circuit-types';
1
+ import { isNoirCallStackUnresolved } from '@aztec/circuit-types';
2
2
  import { GasFees, GlobalVariables, MAX_L2_GAS_PER_TX_PUBLIC_PORTION } from '@aztec/circuits.js';
3
3
  import { type FunctionArtifact, FunctionSelector } from '@aztec/foundation/abi';
4
4
  import { AztecAddress } from '@aztec/foundation/aztec-address';
@@ -10,8 +10,9 @@ import { strict as assert } from 'assert';
10
10
  import { mock } from 'jest-mock-extended';
11
11
  import merge from 'lodash.merge';
12
12
 
13
- import { type WorldStateDB, resolveAssertionMessageFromRevertData, traverseCauseChain } from '../../index.js';
13
+ import { resolveAssertionMessageFromRevertData, traverseCauseChain } from '../../common.js';
14
14
  import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js';
15
+ import { type WorldStateDB } from '../../server.js';
15
16
  import { AvmContext } from '../avm_context.js';
16
17
  import { AvmExecutionEnvironment } from '../avm_execution_environment.js';
17
18
  import { AvmMachineState } from '../avm_machine_state.js';
@@ -45,7 +46,7 @@ export function initPersistableStateManager(overrides?: {
45
46
  nullifiers?: NullifierManager;
46
47
  doMerkleOperations?: boolean;
47
48
  merkleTrees?: AvmEphemeralForest;
48
- txHash?: TxHash;
49
+ firstNullifier?: Fr;
49
50
  }): AvmPersistableStateManager {
50
51
  const worldStateDB = overrides?.worldStateDB || mock<WorldStateDB>();
51
52
  return new AvmPersistableStateManager(
@@ -55,7 +56,7 @@ export function initPersistableStateManager(overrides?: {
55
56
  overrides?.nullifiers || new NullifierManager(worldStateDB),
56
57
  overrides?.doMerkleOperations || false,
57
58
  overrides?.merkleTrees || mock<AvmEphemeralForest>(),
58
- overrides?.txHash || new TxHash(new Fr(27)),
59
+ overrides?.firstNullifier || new Fr(27),
59
60
  );
60
61
  }
61
62
 
@@ -1,4 +1,4 @@
1
- import { MerkleTreeId, type TxHash } from '@aztec/circuit-types';
1
+ import { MerkleTreeId } from '@aztec/circuit-types';
2
2
  import {
3
3
  AztecAddress,
4
4
  CANONICAL_AUTH_REGISTRY_ADDRESS,
@@ -61,7 +61,7 @@ export class AvmPersistableStateManager {
61
61
  private readonly doMerkleOperations: boolean = false,
62
62
  /** Ephmeral forest for merkle tree operations */
63
63
  public merkleTrees: AvmEphemeralForest,
64
- public readonly txHash: TxHash,
64
+ public readonly firstNullifier: Fr,
65
65
  ) {}
66
66
 
67
67
  /**
@@ -71,7 +71,7 @@ export class AvmPersistableStateManager {
71
71
  worldStateDB: WorldStateDB,
72
72
  trace: PublicSideEffectTraceInterface,
73
73
  doMerkleOperations: boolean = false,
74
- txHash: TxHash,
74
+ firstNullifier: Fr,
75
75
  ) {
76
76
  const ephemeralForest = await AvmEphemeralForest.create(worldStateDB.getMerkleInterface());
77
77
  return new AvmPersistableStateManager(
@@ -81,7 +81,7 @@ export class AvmPersistableStateManager {
81
81
  /*nullifiers=*/ new NullifierManager(worldStateDB),
82
82
  /*doMerkleOperations=*/ doMerkleOperations,
83
83
  ephemeralForest,
84
- txHash,
84
+ firstNullifier,
85
85
  );
86
86
  }
87
87
 
@@ -96,7 +96,7 @@ export class AvmPersistableStateManager {
96
96
  this.nullifiers.fork(),
97
97
  this.doMerkleOperations,
98
98
  this.merkleTrees.fork(),
99
- this.txHash,
99
+ this.firstNullifier,
100
100
  );
101
101
  }
102
102
 
@@ -124,13 +124,14 @@ export class AvmPersistableStateManager {
124
124
  this.publicStorage.acceptAndMerge(forkedState.publicStorage);
125
125
  this.nullifiers.acceptAndMerge(forkedState.nullifiers);
126
126
  this.trace.merge(forkedState.trace, reverted);
127
- if (!reverted) {
128
- this.merkleTrees = forkedState.merkleTrees;
127
+ if (reverted) {
129
128
  if (this.doMerkleOperations) {
130
129
  this.log.debug(
131
130
  `Rolled back nullifier tree to root ${this.merkleTrees.treeMap.get(MerkleTreeId.NULLIFIER_TREE)!.getRoot()}`,
132
131
  );
133
132
  }
133
+ } else {
134
+ this.merkleTrees = forkedState.merkleTrees;
134
135
  }
135
136
  }
136
137
 
@@ -293,8 +294,7 @@ export class AvmPersistableStateManager {
293
294
  * @param noteHash - the non unique note hash to write
294
295
  */
295
296
  public writeSiloedNoteHash(noteHash: Fr): void {
296
- const txHash = Fr.fromBuffer(this.txHash.toBuffer());
297
- const nonce = computeNoteHashNonce(txHash, this.trace.getNoteHashCount());
297
+ const nonce = computeNoteHashNonce(this.firstNullifier, this.trace.getNoteHashCount());
298
298
  const uniqueNoteHash = computeUniqueNoteHash(nonce, noteHash);
299
299
 
300
300
  this.writeUniqueNoteHash(uniqueNoteHash);
@@ -1,6 +1,6 @@
1
1
  import { Fr } from '@aztec/foundation/fields';
2
2
 
3
- import type { CommitmentsDB } from '../../index.js';
3
+ import type { CommitmentsDB } from '../../server.js';
4
4
 
5
5
  /**
6
6
  * A class to manage new nullifier staging and existence checks during a contract call's AVM simulation.
@@ -1,7 +1,7 @@
1
1
  import { type AztecAddress } from '@aztec/circuits.js';
2
2
  import { Fr } from '@aztec/foundation/fields';
3
3
 
4
- import type { PublicStateDB } from '../../index.js';
4
+ import type { PublicStateDB } from '../../server.js';
5
5
 
6
6
  type PublicStorageReadResult = {
7
7
  value: Fr;
@@ -6,7 +6,7 @@ import {
6
6
  Note,
7
7
  NoteAndSlot,
8
8
  type NoteStatus,
9
- type PrivateExecutionResult,
9
+ type PrivateCallExecutionResult,
10
10
  PublicExecutionRequest,
11
11
  type UnencryptedL2Log,
12
12
  } from '@aztec/circuit-types';
@@ -26,7 +26,8 @@ import { Fr } from '@aztec/foundation/fields';
26
26
  import { createLogger } from '@aztec/foundation/log';
27
27
 
28
28
  import { type NoteData, toACVMWitness } from '../acvm/index.js';
29
- import { type PackedValuesCache } from '../common/packed_values_cache.js';
29
+ import { type HashedValuesCache } from '../common/hashed_values_cache.js';
30
+ import { type SimulationProvider } from '../server.js';
30
31
  import { type DBOracle } from './db_oracle.js';
31
32
  import { type ExecutionNoteCache } from './execution_note_cache.js';
32
33
  import { pickNotes } from './pick_notes.js';
@@ -57,7 +58,7 @@ export class ClientExecutionContext extends ViewDataOracle {
57
58
  private noteHashLeafIndexMap: Map<bigint, bigint> = new Map();
58
59
  private noteHashNullifierCounterMap: Map<number, number> = new Map();
59
60
  private contractClassLogs: CountedContractClassLog[] = [];
60
- private nestedExecutions: PrivateExecutionResult[] = [];
61
+ private nestedExecutions: PrivateCallExecutionResult[] = [];
61
62
  private enqueuedPublicFunctionCalls: CountedPublicExecutionRequest[] = [];
62
63
  private publicTeardownFunctionCall: PublicExecutionRequest = PublicExecutionRequest.empty();
63
64
 
@@ -69,10 +70,11 @@ export class ClientExecutionContext extends ViewDataOracle {
69
70
  protected readonly historicalHeader: BlockHeader,
70
71
  /** List of transient auth witnesses to be used during this simulation */
71
72
  authWitnesses: AuthWitness[],
72
- private readonly packedValuesCache: PackedValuesCache,
73
+ private readonly executionCache: HashedValuesCache,
73
74
  private readonly noteCache: ExecutionNoteCache,
74
75
  db: DBOracle,
75
76
  private node: AztecNode,
77
+ private provider: SimulationProvider,
76
78
  protected sideEffectCounter: number = 0,
77
79
  log = createLogger('simulator:client_execution_context'),
78
80
  scopes?: AztecAddress[],
@@ -90,7 +92,7 @@ export class ClientExecutionContext extends ViewDataOracle {
90
92
  public getInitialWitness(abi: FunctionAbi) {
91
93
  const argumentsSize = countArgumentsSize(abi);
92
94
 
93
- const args = this.packedValuesCache.unpack(this.argsHash);
95
+ const args = this.executionCache.getPreimage(this.argsHash);
94
96
 
95
97
  if (args.length !== argumentsSize) {
96
98
  throw new Error('Invalid arguments size');
@@ -159,27 +161,29 @@ export class ClientExecutionContext extends ViewDataOracle {
159
161
  }
160
162
 
161
163
  /**
162
- * Pack the given array of arguments.
163
- * @param args - Arguments to pack
164
+ * Store values in the execution cache.
165
+ * @param values - Values to store.
164
166
  */
165
- public override packArgumentsArray(args: Fr[]): Promise<Fr> {
166
- return Promise.resolve(this.packedValuesCache.pack(args));
167
+ public override storeArrayInExecutionCache(args: Fr[]): Promise<Fr> {
168
+ return Promise.resolve(this.executionCache.store(args));
167
169
  }
168
170
 
169
171
  /**
170
- * Pack the given returns.
171
- * @param returns - Returns to pack
172
+ * Store values in the execution cache.
173
+ * @param values - Values to store.
174
+ * @returns The hash of the values.
172
175
  */
173
- public override packReturns(returns: Fr[]): Promise<Fr> {
174
- return Promise.resolve(this.packedValuesCache.pack(returns));
176
+ public override storeInExecutionCache(values: Fr[]): Promise<Fr> {
177
+ return Promise.resolve(this.executionCache.store(values));
175
178
  }
176
179
 
177
180
  /**
178
- * Unpack the given returns.
179
- * @param returnsHash - Returns hash to unpack
181
+ * Gets values from the execution cache.
182
+ * @param hash - Hash of the values.
183
+ * @returns The values.
180
184
  */
181
- public override unpackReturns(returnsHash: Fr): Promise<Fr[]> {
182
- return Promise.resolve(this.packedValuesCache.unpack(returnsHash));
185
+ public override loadFromExecutionCache(hash: Fr): Promise<Fr[]> {
186
+ return Promise.resolve(this.executionCache.getPreimage(hash));
183
187
  }
184
188
 
185
189
  /**
@@ -307,6 +311,17 @@ export class ClientExecutionContext extends ViewDataOracle {
307
311
  return Promise.resolve();
308
312
  }
309
313
 
314
+ /**
315
+ * Adding a siloed nullifier into the current set of all pending nullifiers created
316
+ * within the current transaction/execution.
317
+ * @param innerNullifier - The pending nullifier to add in the list (not yet siloed by contract address).
318
+ * @param noteHash - A hash of the new note.
319
+ */
320
+ public override notifyCreatedNullifier(innerNullifier: Fr) {
321
+ this.noteCache.nullifierCreated(this.callContext.contractAddress, innerNullifier);
322
+ return Promise.resolve();
323
+ }
324
+
310
325
  /**
311
326
  * Emit a contract class unencrypted log.
312
327
  * This fn exists because sha hashing the preimage
@@ -323,7 +338,7 @@ export class ClientExecutionContext extends ViewDataOracle {
323
338
  return Fr.fromBuffer(log.hash());
324
339
  }
325
340
 
326
- #checkValidStaticCall(childExecutionResult: PrivateExecutionResult) {
341
+ #checkValidStaticCall(childExecutionResult: PrivateCallExecutionResult) {
327
342
  if (
328
343
  childExecutionResult.publicInputs.noteHashes.some(item => !item.isEmpty()) ||
329
344
  childExecutionResult.publicInputs.nullifiers.some(item => !item.isEmpty()) ||
@@ -339,7 +354,7 @@ export class ClientExecutionContext extends ViewDataOracle {
339
354
  * Calls a private function as a nested execution.
340
355
  * @param targetContractAddress - The address of the contract to call.
341
356
  * @param functionSelector - The function selector of the function to call.
342
- * @param argsHash - The packed arguments to pass to the function.
357
+ * @param argsHash - The arguments hash to pass to the function.
343
358
  * @param sideEffectCounter - The side effect counter at the start of the call.
344
359
  * @param isStaticCall - Whether the call is a static call.
345
360
  * @returns The execution result.
@@ -369,16 +384,18 @@ export class ClientExecutionContext extends ViewDataOracle {
369
384
  derivedCallContext,
370
385
  this.historicalHeader,
371
386
  this.authWitnesses,
372
- this.packedValuesCache,
387
+ this.executionCache,
373
388
  this.noteCache,
374
389
  this.db,
375
390
  this.node,
391
+ this.provider,
376
392
  sideEffectCounter,
377
393
  this.log,
378
394
  this.scopes,
379
395
  );
380
396
 
381
397
  const childExecutionResult = await executePrivateFunction(
398
+ this.provider,
382
399
  context,
383
400
  targetArtifact,
384
401
  targetContractAddress,
@@ -402,7 +419,7 @@ export class ClientExecutionContext extends ViewDataOracle {
402
419
  * Creates a PublicExecutionRequest object representing the request to call a public function.
403
420
  * @param targetContractAddress - The address of the contract to call.
404
421
  * @param functionSelector - The function selector of the function to call.
405
- * @param argsHash - The packed arguments to pass to the function.
422
+ * @param argsHash - The arguments hash to pass to the function.
406
423
  * @param sideEffectCounter - The side effect counter at the start of the call.
407
424
  * @param isStaticCall - Whether the call is a static call.
408
425
  * @returns The public call stack item with the request information.
@@ -417,7 +434,7 @@ export class ClientExecutionContext extends ViewDataOracle {
417
434
  ) {
418
435
  const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
419
436
  const derivedCallContext = this.deriveCallContext(targetContractAddress, targetArtifact, isStaticCall);
420
- const args = this.packedValuesCache.unpack(argsHash);
437
+ const args = this.executionCache.getPreimage(argsHash);
421
438
 
422
439
  this.log.verbose(
423
440
  `Created ${callType} public execution request to ${targetArtifact.name}@${targetContractAddress}`,
@@ -448,7 +465,7 @@ export class ClientExecutionContext extends ViewDataOracle {
448
465
  * of the execution are empty.
449
466
  * @param targetContractAddress - The address of the contract to call.
450
467
  * @param functionSelector - The function selector of the function to call.
451
- * @param argsHash - The packed arguments to pass to the function.
468
+ * @param argsHash - The arguments hash to pass to the function.
452
469
  * @param sideEffectCounter - The side effect counter at the start of the call.
453
470
  * @param isStaticCall - Whether the call is a static call.
454
471
  * @returns The public call stack item with the request information.
@@ -462,13 +479,13 @@ export class ClientExecutionContext extends ViewDataOracle {
462
479
  ): Promise<Fr> {
463
480
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this.
464
481
  // WARNING: This is insecure and should be temporary!
465
- // The oracle repacks the arguments and returns a new args_hash.
482
+ // The oracle re-hashes the arguments and returns a new args_hash.
466
483
  // new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function.
467
484
  // We don't validate or compute it in the circuit because a) it's harder to do with slices, and
468
485
  // b) this is only temporary.
469
- const newArgsHash = this.packedValuesCache.pack([
486
+ const newArgsHash = this.executionCache.store([
470
487
  functionSelector.toField(),
471
- ...this.packedValuesCache.unpack(argsHash),
488
+ ...this.executionCache.getPreimage(argsHash),
472
489
  ]);
473
490
  await this.createPublicExecutionRequest(
474
491
  'enqueued',
@@ -487,7 +504,7 @@ export class ClientExecutionContext extends ViewDataOracle {
487
504
  * of the execution are empty.
488
505
  * @param targetContractAddress - The address of the contract to call.
489
506
  * @param functionSelector - The function selector of the function to call.
490
- * @param argsHash - The packed arguments to pass to the function.
507
+ * @param argsHash - The arguments hash to pass to the function.
491
508
  * @param sideEffectCounter - The side effect counter at the start of the call.
492
509
  * @param isStaticCall - Whether the call is a static call.
493
510
  * @returns The public call stack item with the request information.
@@ -501,13 +518,13 @@ export class ClientExecutionContext extends ViewDataOracle {
501
518
  ): Promise<Fr> {
502
519
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8985): Fix this.
503
520
  // WARNING: This is insecure and should be temporary!
504
- // The oracle repacks the arguments and returns a new args_hash.
521
+ // The oracle rehashes the arguments and returns a new args_hash.
505
522
  // new_args = [selector, ...old_args], so as to make it suitable to call the public dispatch function.
506
523
  // We don't validate or compute it in the circuit because a) it's harder to do with slices, and
507
524
  // b) this is only temporary.
508
- const newArgsHash = this.packedValuesCache.pack([
525
+ const newArgsHash = this.executionCache.store([
509
526
  functionSelector.toField(),
510
- ...this.packedValuesCache.unpack(argsHash),
527
+ ...this.executionCache.getPreimage(argsHash),
511
528
  ]);
512
529
  await this.createPublicExecutionRequest(
513
530
  'teardown',
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  type L2Block,
3
- type L2BlockNumber,
4
3
  type MerkleTreeId,
5
4
  type NoteStatus,
6
5
  type NullifierMembershipWitness,
@@ -141,22 +140,13 @@ export interface DBOracle extends CommitmentsDB {
141
140
  getBlockHeader(): Promise<BlockHeader>;
142
141
 
143
142
  /**
144
- * Fetch the index of the leaf in the respective tree
145
- * @param blockNumber - The block number at which to get the leaf index.
146
- * @param treeId - The id of the tree to search.
147
- * @param leafValue - The leaf value buffer.
148
- * @returns - The index of the leaf. Undefined if it does not exist in the tree.
143
+ * Fetches the index and sibling path of a leaf at a given block from a given tree.
144
+ * @param blockNumber - The block number at which to get the membership witness.
145
+ * @param treeId - Id of the tree to get the sibling path from.
146
+ * @param leafValue - The leaf value
147
+ * @returns The index and sibling path concatenated [index, sibling_path]
149
148
  */
150
- findLeafIndex(blockNumber: L2BlockNumber, treeId: MerkleTreeId, leafValue: Fr): Promise<bigint | undefined>;
151
-
152
- /**
153
- * Fetch the sibling path of the leaf in the respective tree
154
- * @param blockNumber - The block number at which to get the sibling path.
155
- * @param treeId - The id of the tree to search.
156
- * @param leafIndex - The index of the leaf.
157
- * @returns - The sibling path of the leaf.
158
- */
159
- getSiblingPath(blockNumber: number, treeId: MerkleTreeId, leafIndex: bigint): Promise<Fr[]>;
149
+ getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[]>;
160
150
 
161
151
  /**
162
152
  * Returns a nullifier membership witness for a given nullifier at a given block.
@@ -224,7 +214,7 @@ export interface DBOracle extends CommitmentsDB {
224
214
  ): Promise<void>;
225
215
 
226
216
  /**
227
- * Synchronizes the logs tagged with the recipient's address and all the senders in the addressbook.
217
+ * Synchronizes the logs tagged with the recipient's address and all the senders in the address book.
228
218
  * Returns the unsynched logs and updates the indexes of the secrets used to tag them until there are no more logs to sync.
229
219
  * @param contractAddress - The address of the contract that the logs are tagged for
230
220
  * @param recipient - The address of the recipient
@@ -247,4 +237,22 @@ export interface DBOracle extends CommitmentsDB {
247
237
  * Removes all of a contract's notes that have been nullified from the note database.
248
238
  */
249
239
  removeNullifiedNotes(contractAddress: AztecAddress): Promise<void>;
240
+
241
+ /**
242
+ * Used by contracts during execution to store arbitrary data in the local PXE database. The data is siloed/scoped
243
+ * to a specific `contract`.
244
+ * @param contract - An address of a contract that is requesting to store the data.
245
+ * @param key - A field element representing the key to store the data under.
246
+ * @param values - An array of field elements representing the data to store.
247
+ */
248
+ store(contract: AztecAddress, key: Fr, values: Fr[]): Promise<void>;
249
+
250
+ /**
251
+ * Used by contracts during execution to load arbitrary data from the local PXE database. The data is siloed/scoped
252
+ * to a specific `contract`.
253
+ * @param contract - An address of a contract that is requesting to load the data.
254
+ * @param key - A field element representing the key under which to load the data..
255
+ * @returns An array of field elements representing the stored data or `null` if no data is stored under the key.
256
+ */
257
+ load(contract: AztecAddress, key: Fr): Promise<Fr[] | null>;
250
258
  }