@aztec/simulator 0.24.0 → 0.26.1

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 (129) hide show
  1. package/dest/acvm/deserialize.d.ts +5 -0
  2. package/dest/acvm/deserialize.d.ts.map +1 -1
  3. package/dest/acvm/deserialize.js +8 -1
  4. package/dest/acvm/oracle/oracle.d.ts +5 -4
  5. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/oracle.js +24 -11
  7. package/dest/acvm/oracle/typed_oracle.d.ts +7 -9
  8. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  9. package/dest/acvm/oracle/typed_oracle.js +9 -9
  10. package/dest/avm/avm_context.d.ts +4 -4
  11. package/dest/avm/avm_context.d.ts.map +1 -1
  12. package/dest/avm/avm_context.js +6 -6
  13. package/dest/avm/avm_memory_types.d.ts +11 -2
  14. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  15. package/dest/avm/avm_memory_types.js +11 -1
  16. package/dest/avm/avm_simulator.d.ts +6 -4
  17. package/dest/avm/avm_simulator.d.ts.map +1 -1
  18. package/dest/avm/avm_simulator.js +17 -18
  19. package/dest/avm/fixtures/index.d.ts +17 -5
  20. package/dest/avm/fixtures/index.d.ts.map +1 -1
  21. package/dest/avm/fixtures/index.js +19 -8
  22. package/dest/avm/journal/host_storage.d.ts.map +1 -1
  23. package/dest/avm/journal/host_storage.js +1 -1
  24. package/dest/avm/journal/journal.d.ts +78 -50
  25. package/dest/avm/journal/journal.d.ts.map +1 -1
  26. package/dest/avm/journal/journal.js +125 -169
  27. package/dest/avm/journal/nullifiers.d.ts +85 -0
  28. package/dest/avm/journal/nullifiers.d.ts.map +1 -0
  29. package/dest/avm/journal/nullifiers.js +147 -0
  30. package/dest/avm/journal/public_storage.d.ts +88 -0
  31. package/dest/avm/journal/public_storage.d.ts.map +1 -0
  32. package/dest/avm/journal/public_storage.js +135 -0
  33. package/dest/avm/journal/trace.d.ts +43 -0
  34. package/dest/avm/journal/trace.d.ts.map +1 -0
  35. package/dest/avm/journal/trace.js +204 -0
  36. package/dest/avm/journal/trace_types.d.ts +26 -0
  37. package/dest/avm/journal/trace_types.d.ts.map +1 -0
  38. package/dest/avm/journal/trace_types.js +6 -0
  39. package/dest/avm/opcodes/accrued_substate.d.ts +37 -4
  40. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  41. package/dest/avm/opcodes/accrued_substate.js +109 -12
  42. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  43. package/dest/avm/opcodes/comparators.js +5 -8
  44. package/dest/avm/opcodes/environment_getters.d.ts +14 -13
  45. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  46. package/dest/avm/opcodes/environment_getters.js +1 -1
  47. package/dest/avm/opcodes/external_calls.js +5 -5
  48. package/dest/avm/opcodes/hashing.d.ts +48 -0
  49. package/dest/avm/opcodes/hashing.d.ts.map +1 -0
  50. package/dest/avm/opcodes/hashing.js +127 -0
  51. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  52. package/dest/avm/opcodes/memory.js +1 -1
  53. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  54. package/dest/avm/opcodes/storage.js +3 -3
  55. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  56. package/dest/avm/serialization/bytecode_serialization.js +12 -8
  57. package/dest/avm/serialization/instruction_serialization.d.ts +10 -7
  58. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  59. package/dest/avm/serialization/instruction_serialization.js +12 -9
  60. package/dest/avm/temporary_executor_migration.d.ts.map +1 -1
  61. package/dest/avm/temporary_executor_migration.js +5 -5
  62. package/dest/client/client_execution_context.d.ts +9 -5
  63. package/dest/client/client_execution_context.d.ts.map +1 -1
  64. package/dest/client/client_execution_context.js +46 -24
  65. package/dest/client/db_oracle.d.ts +7 -0
  66. package/dest/client/db_oracle.d.ts.map +1 -1
  67. package/dest/client/db_oracle.js +1 -1
  68. package/dest/client/execution_note_cache.js +1 -1
  69. package/dest/client/execution_result.d.ts +2 -2
  70. package/dest/client/execution_result.d.ts.map +1 -1
  71. package/dest/client/private_execution.d.ts.map +1 -1
  72. package/dest/client/private_execution.js +4 -4
  73. package/dest/client/simulator.d.ts +1 -1
  74. package/dest/client/simulator.d.ts.map +1 -1
  75. package/dest/client/simulator.js +3 -2
  76. package/dest/client/view_data_oracle.d.ts +9 -2
  77. package/dest/client/view_data_oracle.d.ts.map +1 -1
  78. package/dest/client/view_data_oracle.js +13 -5
  79. package/dest/public/db.d.ts +17 -4
  80. package/dest/public/db.d.ts.map +1 -1
  81. package/dest/public/execution.d.ts +9 -4
  82. package/dest/public/execution.d.ts.map +1 -1
  83. package/dest/public/execution.js +17 -4
  84. package/dest/public/executor.d.ts.map +1 -1
  85. package/dest/public/executor.js +18 -9
  86. package/dest/public/public_execution_context.d.ts +5 -4
  87. package/dest/public/public_execution_context.d.ts.map +1 -1
  88. package/dest/public/public_execution_context.js +23 -12
  89. package/dest/public/state_actions.js +2 -2
  90. package/dest/test/utils.js +4 -4
  91. package/dest/utils.js +2 -3
  92. package/package.json +6 -5
  93. package/src/acvm/deserialize.ts +8 -0
  94. package/src/acvm/oracle/oracle.ts +30 -6
  95. package/src/acvm/oracle/typed_oracle.ts +13 -5
  96. package/src/avm/avm_context.ts +5 -5
  97. package/src/avm/avm_memory_types.ts +18 -3
  98. package/src/avm/avm_simulator.ts +22 -24
  99. package/src/avm/fixtures/index.ts +34 -9
  100. package/src/avm/journal/host_storage.ts +5 -11
  101. package/src/avm/journal/journal.ts +147 -182
  102. package/src/avm/journal/nullifiers.ts +170 -0
  103. package/src/avm/journal/public_storage.ts +149 -0
  104. package/src/avm/journal/trace.ts +223 -0
  105. package/src/avm/journal/trace_types.ts +79 -0
  106. package/src/avm/opcodes/accrued_substate.ts +132 -10
  107. package/src/avm/opcodes/comparators.ts +4 -7
  108. package/src/avm/opcodes/environment_getters.ts +15 -13
  109. package/src/avm/opcodes/external_calls.ts +4 -4
  110. package/src/avm/opcodes/hashing.ts +170 -0
  111. package/src/avm/opcodes/memory.ts +1 -0
  112. package/src/avm/opcodes/storage.ts +5 -2
  113. package/src/avm/serialization/bytecode_serialization.ts +13 -6
  114. package/src/avm/serialization/instruction_serialization.ts +6 -3
  115. package/src/avm/temporary_executor_migration.ts +4 -3
  116. package/src/client/client_execution_context.ts +53 -23
  117. package/src/client/db_oracle.ts +8 -0
  118. package/src/client/execution_note_cache.ts +1 -1
  119. package/src/client/execution_result.ts +2 -2
  120. package/src/client/private_execution.ts +5 -4
  121. package/src/client/simulator.ts +2 -1
  122. package/src/client/view_data_oracle.ts +14 -4
  123. package/src/public/db.ts +19 -4
  124. package/src/public/execution.ts +30 -6
  125. package/src/public/executor.ts +29 -9
  126. package/src/public/public_execution_context.ts +36 -12
  127. package/src/public/state_actions.ts +1 -1
  128. package/src/test/utils.ts +3 -3
  129. package/src/utils.ts +1 -1
@@ -5,6 +5,7 @@ import {
5
5
  L1NotePayload,
6
6
  Note,
7
7
  NoteStatus,
8
+ TaggedNote,
8
9
  UnencryptedL2Log,
9
10
  } from '@aztec/circuit-types';
10
11
  import {
@@ -13,13 +14,13 @@ import {
13
14
  FunctionData,
14
15
  FunctionSelector,
15
16
  Header,
17
+ NoteHashReadRequestMembershipWitness,
16
18
  PublicCallRequest,
17
- ReadRequestMembershipWitness,
18
19
  SideEffect,
19
20
  TxContext,
20
21
  } from '@aztec/circuits.js';
21
- import { computePublicDataTreeLeafSlot, computeUniqueCommitment, siloCommitment } from '@aztec/circuits.js/abis';
22
22
  import { Grumpkin } from '@aztec/circuits.js/barretenberg';
23
+ import { computePublicDataTreeLeafSlot, computeUniqueCommitment, siloNoteHash } from '@aztec/circuits.js/hash';
23
24
  import { FunctionAbi, FunctionArtifact, countArgumentsSize } from '@aztec/foundation/abi';
24
25
  import { AztecAddress } from '@aztec/foundation/aztec-address';
25
26
  import { Fr, Point } from '@aztec/foundation/fields';
@@ -118,17 +119,17 @@ export class ClientExecutionContext extends ViewDataOracle {
118
119
  * or to flag non-transient reads with their leafIndex.
119
120
  * The KernelProver will use this to fully populate witnesses and provide hints to
120
121
  * the kernel regarding which commitments each transient read request corresponds to.
121
- * @param readRequests - SideEffect containing Note hashed of the notes being read and counter.
122
+ * @param noteHashReadRequests - SideEffect containing Note hashed of the notes being read and counter.
122
123
  * @returns An array of partially filled in read request membership witnesses.
123
124
  */
124
- public getReadRequestPartialWitnesses(readRequests: SideEffect[]) {
125
- return readRequests
125
+ public getNoteHashReadRequestPartialWitnesses(noteHashReadRequests: SideEffect[]) {
126
+ return noteHashReadRequests
126
127
  .filter(r => !r.isEmpty())
127
128
  .map(r => {
128
129
  const index = this.gotNotes.get(r.value.toBigInt());
129
130
  return index !== undefined
130
- ? ReadRequestMembershipWitness.empty(index)
131
- : ReadRequestMembershipWitness.emptyTransient();
131
+ ? NoteHashReadRequestMembershipWitness.empty(index)
132
+ : NoteHashReadRequestMembershipWitness.emptyTransient();
132
133
  });
133
134
  }
134
135
 
@@ -209,10 +210,10 @@ export class ClientExecutionContext extends ViewDataOracle {
209
210
  status: NoteStatus,
210
211
  ): Promise<NoteData[]> {
211
212
  // Nullified pending notes are already removed from the list.
212
- const pendingNotes = this.noteCache.getNotes(this.contractAddress, storageSlot);
213
+ const pendingNotes = this.noteCache.getNotes(this.callContext.storageContractAddress, storageSlot);
213
214
 
214
- const pendingNullifiers = this.noteCache.getNullifiers(this.contractAddress);
215
- const dbNotes = await this.db.getNotes(this.contractAddress, storageSlot, status);
215
+ const pendingNullifiers = this.noteCache.getNullifiers(this.callContext.storageContractAddress);
216
+ const dbNotes = await this.db.getNotes(this.callContext.storageContractAddress, storageSlot, status);
216
217
  const dbNotesFiltered = dbNotes.filter(n => !pendingNullifiers.has((n.siloedNullifier as Fr).value));
217
218
 
218
219
  const notes = pickNotes<NoteData>([...dbNotesFiltered, ...pendingNotes], {
@@ -225,14 +226,14 @@ export class ClientExecutionContext extends ViewDataOracle {
225
226
  });
226
227
 
227
228
  this.log(
228
- `Returning ${notes.length} notes for ${this.contractAddress} at ${storageSlot}: ${notes
229
+ `Returning ${notes.length} notes for ${this.callContext.storageContractAddress} at ${storageSlot}: ${notes
229
230
  .map(n => `${n.nonce.toString()}:[${n.note.items.map(i => i.toString()).join(',')}]`)
230
231
  .join(', ')}`,
231
232
  );
232
233
 
233
234
  notes.forEach(n => {
234
235
  if (n.index !== undefined) {
235
- const siloedNoteHash = siloCommitment(n.contractAddress, n.innerNoteHash);
236
+ const siloedNoteHash = siloNoteHash(n.contractAddress, n.innerNoteHash);
236
237
  const uniqueSiloedNoteHash = computeUniqueCommitment(n.nonce, siloedNoteHash);
237
238
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386)
238
239
  // Should always be uniqueSiloedNoteHash when publicly created notes include nonces.
@@ -257,7 +258,7 @@ export class ClientExecutionContext extends ViewDataOracle {
257
258
  public notifyCreatedNote(storageSlot: Fr, noteTypeId: Fr, noteItems: Fr[], innerNoteHash: Fr) {
258
259
  const note = new Note(noteItems);
259
260
  this.noteCache.addNewNote({
260
- contractAddress: this.contractAddress,
261
+ contractAddress: this.callContext.storageContractAddress,
261
262
  storageSlot,
262
263
  nonce: Fr.ZERO, // Nonce cannot be known during private execution.
263
264
  note,
@@ -278,7 +279,7 @@ export class ClientExecutionContext extends ViewDataOracle {
278
279
  * @param innerNoteHash - The inner note hash of the new note.
279
280
  */
280
281
  public notifyNullifiedNote(innerNullifier: Fr, innerNoteHash: Fr) {
281
- this.noteCache.nullifyNote(this.contractAddress, innerNullifier, innerNoteHash);
282
+ this.noteCache.nullifyNote(this.callContext.storageContractAddress, innerNullifier, innerNoteHash);
282
283
  return Promise.resolve();
283
284
  }
284
285
 
@@ -293,7 +294,8 @@ export class ClientExecutionContext extends ViewDataOracle {
293
294
  public emitEncryptedLog(contractAddress: AztecAddress, storageSlot: Fr, noteTypeId: Fr, publicKey: Point, log: Fr[]) {
294
295
  const note = new Note(log);
295
296
  const l1NotePayload = new L1NotePayload(note, contractAddress, storageSlot, noteTypeId);
296
- const encryptedNote = l1NotePayload.toEncryptedBuffer(publicKey, this.curve);
297
+ const taggedNote = new TaggedNote(l1NotePayload);
298
+ const encryptedNote = taggedNote.toEncryptedBuffer(publicKey, this.curve);
297
299
  this.encryptedLogs.push(encryptedNote);
298
300
  }
299
301
 
@@ -307,12 +309,26 @@ export class ClientExecutionContext extends ViewDataOracle {
307
309
  this.log(`Emitted unencrypted log: "${text.length > 100 ? text.slice(0, 100) + '...' : text}"`);
308
310
  }
309
311
 
312
+ #checkValidStaticCall(childExecutionResult: ExecutionResult) {
313
+ if (
314
+ childExecutionResult.callStackItem.publicInputs.newNoteHashes.some(item => !item.isEmpty()) ||
315
+ childExecutionResult.callStackItem.publicInputs.newNullifiers.some(item => !item.isEmpty()) ||
316
+ childExecutionResult.callStackItem.publicInputs.newL2ToL1Msgs.some(item => !item.isEmpty()) ||
317
+ !childExecutionResult.callStackItem.publicInputs.encryptedLogPreimagesLength.equals(new Fr(4)) ||
318
+ !childExecutionResult.callStackItem.publicInputs.unencryptedLogPreimagesLength.equals(new Fr(4))
319
+ ) {
320
+ throw new Error(`Static call cannot create new notes, emit L2->L1 messages or generate logs`);
321
+ }
322
+ }
323
+
310
324
  /**
311
325
  * Calls a private function as a nested execution.
312
326
  * @param targetContractAddress - The address of the contract to call.
313
327
  * @param functionSelector - The function selector of the function to call.
314
328
  * @param argsHash - The packed arguments to pass to the function.
315
329
  * @param sideEffectCounter - The side effect counter at the start of the call.
330
+ * @param isStaticCall - Whether the call is a static call.
331
+ * @param isStaticCall - Whether the call is a delegate call.
316
332
  * @returns The execution result.
317
333
  */
318
334
  async callPrivateFunction(
@@ -320,11 +336,15 @@ export class ClientExecutionContext extends ViewDataOracle {
320
336
  functionSelector: FunctionSelector,
321
337
  argsHash: Fr,
322
338
  sideEffectCounter: number,
339
+ isStaticCall: boolean,
340
+ isDelegateCall: boolean,
323
341
  ) {
324
342
  this.log(
325
343
  `Calling private function ${this.contractAddress}:${functionSelector} from ${this.callContext.storageContractAddress}`,
326
344
  );
327
345
 
346
+ isStaticCall = isStaticCall || this.callContext.isStaticCall;
347
+
328
348
  const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
329
349
  const targetFunctionData = FunctionData.fromAbi(targetArtifact);
330
350
 
@@ -341,8 +361,8 @@ export class ClientExecutionContext extends ViewDataOracle {
341
361
  targetContractAddress,
342
362
  targetArtifact,
343
363
  sideEffectCounter,
344
- false,
345
- false,
364
+ isDelegateCall,
365
+ isStaticCall,
346
366
  );
347
367
 
348
368
  const context = new ClientExecutionContext(
@@ -366,6 +386,10 @@ export class ClientExecutionContext extends ViewDataOracle {
366
386
  targetFunctionData,
367
387
  );
368
388
 
389
+ if (isStaticCall) {
390
+ this.#checkValidStaticCall(childExecutionResult);
391
+ }
392
+
369
393
  this.nestedExecutions.push(childExecutionResult);
370
394
 
371
395
  return childExecutionResult.callStackItem;
@@ -379,6 +403,7 @@ export class ClientExecutionContext extends ViewDataOracle {
379
403
  * @param functionSelector - The function selector of the function to call.
380
404
  * @param argsHash - The packed arguments to pass to the function.
381
405
  * @param sideEffectCounter - The side effect counter at the start of the call.
406
+ * @param isStaticCall - Whether the call is a static call.
382
407
  * @returns The public call stack item with the request information.
383
408
  */
384
409
  public async enqueuePublicFunctionCall(
@@ -386,19 +411,24 @@ export class ClientExecutionContext extends ViewDataOracle {
386
411
  functionSelector: FunctionSelector,
387
412
  argsHash: Fr,
388
413
  sideEffectCounter: number,
414
+ isStaticCall: boolean,
415
+ isDelegateCall: boolean,
389
416
  ): Promise<PublicCallRequest> {
417
+ isStaticCall = isStaticCall || this.callContext.isStaticCall;
418
+
390
419
  const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
391
420
  const derivedCallContext = await this.deriveCallContext(
392
421
  targetContractAddress,
393
422
  targetArtifact,
394
423
  sideEffectCounter,
395
- false,
396
- false,
424
+ isDelegateCall,
425
+ isStaticCall,
397
426
  );
398
427
  const args = this.packedArgsCache.unpack(argsHash);
399
428
  const enqueuedRequest = PublicCallRequest.from({
400
429
  args,
401
430
  callContext: derivedCallContext,
431
+ parentCallContext: this.callContext,
402
432
  functionData: FunctionData.fromAbi(targetArtifact),
403
433
  contractAddress: targetContractAddress,
404
434
  });
@@ -408,7 +438,7 @@ export class ClientExecutionContext extends ViewDataOracle {
408
438
  // side-effects occurred in the TX. Ultimately the private kernel should
409
439
  // just output everything in the proper order without any counters.
410
440
  this.log(
411
- `Enqueued call to public function (with side-effect counter #${sideEffectCounter}) ${targetContractAddress}:${functionSelector}`,
441
+ `Enqueued call to public function (with side-effect counter #${sideEffectCounter}) ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`,
412
442
  );
413
443
 
414
444
  this.enqueuedPublicFunctionCalls.push(enqueuedRequest);
@@ -434,8 +464,8 @@ export class ClientExecutionContext extends ViewDataOracle {
434
464
  ) {
435
465
  const portalContractAddress = await this.db.getPortalContractAddress(targetContractAddress);
436
466
  return new CallContext(
437
- this.contractAddress,
438
- targetContractAddress,
467
+ isDelegateCall ? this.callContext.msgSender : this.contractAddress,
468
+ isDelegateCall ? this.contractAddress : targetContractAddress,
439
469
  portalContractAddress,
440
470
  FunctionSelector.fromNameAndParameters(targetArtifact.name, targetArtifact.parameters),
441
471
  isDelegateCall,
@@ -458,7 +488,7 @@ export class ClientExecutionContext extends ViewDataOracle {
458
488
  const values = [];
459
489
  for (let i = 0n; i < numberOfElements; i++) {
460
490
  const storageSlot = new Fr(startStorageSlot.value + i);
461
- const leafSlot = computePublicDataTreeLeafSlot(this.contractAddress, storageSlot);
491
+ const leafSlot = computePublicDataTreeLeafSlot(this.callContext.storageContractAddress, storageSlot);
462
492
  const witness = await this.db.getPublicDataTreeWitness(bn, leafSlot);
463
493
  if (!witness) {
464
494
  throw new Error(`No witness for slot ${storageSlot.toString()}`);
@@ -4,6 +4,7 @@ import { FunctionArtifactWithDebugMetadata, FunctionSelector } from '@aztec/foun
4
4
  import { AztecAddress } from '@aztec/foundation/aztec-address';
5
5
  import { EthAddress } from '@aztec/foundation/eth-address';
6
6
  import { Fr } from '@aztec/foundation/fields';
7
+ import { ContractInstance } from '@aztec/types/contracts';
7
8
 
8
9
  import { KeyPair, NoteData } from '../acvm/index.js';
9
10
  import { CommitmentsDB } from '../public/db.js';
@@ -30,6 +31,13 @@ export class ContractClassNotFoundError extends Error {
30
31
  * The database oracle interface.
31
32
  */
32
33
  export interface DBOracle extends CommitmentsDB {
34
+ /**
35
+ * Returns a contract instance associated with an address, if available.
36
+ * @param address - Address.
37
+ * @returns A contract instance.
38
+ */
39
+ getContractInstance(address: AztecAddress): Promise<ContractInstance>;
40
+
33
41
  /**
34
42
  * Retrieve the complete address associated to a given address.
35
43
  * @param address - Address to fetch the pubkey for.
@@ -1,4 +1,4 @@
1
- import { siloNullifier } from '@aztec/circuits.js/abis';
1
+ import { siloNullifier } from '@aztec/circuits.js/hash';
2
2
  import { AztecAddress } from '@aztec/foundation/aztec-address';
3
3
  import { Fr } from '@aztec/foundation/fields';
4
4
 
@@ -1,5 +1,5 @@
1
1
  import { FunctionL2Logs, Note } from '@aztec/circuit-types';
2
- import { PrivateCallStackItem, PublicCallRequest, ReadRequestMembershipWitness } from '@aztec/circuits.js';
2
+ import { NoteHashReadRequestMembershipWitness, PrivateCallStackItem, PublicCallRequest } from '@aztec/circuits.js';
3
3
  import { DecodedReturn } from '@aztec/foundation/abi';
4
4
  import { Fr } from '@aztec/foundation/fields';
5
5
 
@@ -32,7 +32,7 @@ export interface ExecutionResult {
32
32
  /** The call stack item. */
33
33
  callStackItem: PrivateCallStackItem;
34
34
  /** The partially filled-in read request membership witnesses for commitments being read. */
35
- readRequestPartialWitnesses: ReadRequestMembershipWitness[];
35
+ noteHashReadRequestPartialWitnesses: NoteHashReadRequestMembershipWitness[];
36
36
  // Needed when we enable chained txs. The new notes can be cached and used in a later transaction.
37
37
  /** The notes created in the executed function. */
38
38
  newNotes: NoteAndSlot[];
@@ -23,8 +23,7 @@ export async function executePrivateFunction(
23
23
  log = createDebugLogger('aztec:simulator:secret_execution'),
24
24
  ): Promise<ExecutionResult> {
25
25
  const functionSelector = functionData.selector;
26
- log(`Executing external function ${contractAddress}:${functionSelector}`);
27
-
26
+ log(`Executing external function ${contractAddress}:${functionSelector}(${artifact.name})`);
28
27
  const acir = Buffer.from(artifact.bytecode, 'base64');
29
28
  const initialWitness = context.getInitialWitness(artifact);
30
29
  const acvmCallback = new Oracle(context);
@@ -55,7 +54,9 @@ export async function executePrivateFunction(
55
54
 
56
55
  const callStackItem = new PrivateCallStackItem(contractAddress, functionData, publicInputs);
57
56
  const returnValues = decodeReturnValues(artifact, publicInputs.returnValues);
58
- const readRequestPartialWitnesses = context.getReadRequestPartialWitnesses(publicInputs.readRequests);
57
+ const noteHashReadRequestPartialWitnesses = context.getNoteHashReadRequestPartialWitnesses(
58
+ publicInputs.noteHashReadRequests,
59
+ );
59
60
  const newNotes = context.getNewNotes();
60
61
  const nestedExecutions = context.getNestedExecutions();
61
62
  const enqueuedPublicFunctionCalls = context.getEnqueuedPublicFunctionCalls();
@@ -67,7 +68,7 @@ export async function executePrivateFunction(
67
68
  partialWitness,
68
69
  callStackItem,
69
70
  returnValues,
70
- readRequestPartialWitnesses,
71
+ noteHashReadRequestPartialWitnesses,
71
72
  newNotes,
72
73
  vk: Buffer.from(artifact.verificationKey!, 'hex'),
73
74
  nestedExecutions,
@@ -94,7 +94,8 @@ export class AcirSimulator {
94
94
  false,
95
95
  request.functionData.isConstructor,
96
96
  // TODO: when contract deployment is done in-app, we should only reserve one counter for the tx hash
97
- 2, // 2 counters are reserved for tx hash and contract deployment nullifier
97
+ // 2 counters are reserved for tx hash and contract deployment nullifier
98
+ request.txContext.isContractDeploymentTx ? 2 : 1,
98
99
  );
99
100
  const context = new ClientExecutionContext(
100
101
  contractAddress,
@@ -8,10 +8,11 @@ import {
8
8
  PublicDataWitness,
9
9
  } from '@aztec/circuit-types';
10
10
  import { Header } from '@aztec/circuits.js';
11
- import { siloNullifier } from '@aztec/circuits.js/abis';
11
+ import { siloNullifier } from '@aztec/circuits.js/hash';
12
12
  import { AztecAddress } from '@aztec/foundation/aztec-address';
13
13
  import { Fr } from '@aztec/foundation/fields';
14
14
  import { createDebugLogger } from '@aztec/foundation/log';
15
+ import { ContractInstance } from '@aztec/types/contracts';
15
16
 
16
17
  import { NoteData, TypedOracle } from '../acvm/index.js';
17
18
  import { DBOracle } from './db_oracle.js';
@@ -129,6 +130,15 @@ export class ViewDataOracle extends TypedOracle {
129
130
  return this.db.getCompleteAddress(address);
130
131
  }
131
132
 
133
+ /**
134
+ * Returns a contract instance associated with an address or throws if not found.
135
+ * @param address - Address.
136
+ * @returns A contract instance.
137
+ */
138
+ public getContractInstance(address: AztecAddress): Promise<ContractInstance> {
139
+ return this.db.getContractInstance(address);
140
+ }
141
+
132
142
  /**
133
143
  * Returns an auth witness for the given message hash. Checks on the list of transient witnesses
134
144
  * for this transaction first, and falls back to the local database if not found.
@@ -207,11 +217,11 @@ export class ViewDataOracle extends TypedOracle {
207
217
 
208
218
  /**
209
219
  * Fetches the a message from the db, given its key.
210
- * @param msgKey - A buffer representing the message key.
220
+ * @param entryKey - A buffer representing the entry key.
211
221
  * @returns The l1 to l2 message data
212
222
  */
213
- public async getL1ToL2Message(msgKey: Fr) {
214
- return await this.db.getL1ToL2Message(msgKey);
223
+ public async getL1ToL2MembershipWitness(entryKey: Fr) {
224
+ return await this.db.getL1ToL2MembershipWitness(entryKey);
215
225
  }
216
226
 
217
227
  /**
package/src/public/db.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { NullifierMembershipWitness } from '@aztec/circuit-types';
1
2
  import { EthAddress, FunctionSelector, L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/circuits.js';
2
3
  import { AztecAddress } from '@aztec/foundation/aztec-address';
3
4
  import { Fr } from '@aztec/foundation/fields';
@@ -66,15 +67,15 @@ export interface PublicContractsDB {
66
67
  getPortalContractAddress(address: AztecAddress): Promise<EthAddress | undefined>;
67
68
  }
68
69
 
69
- /** Database interface for providing access to commitment tree and l1 to l2 message tree (append only data trees). */
70
+ /** Database interface for providing access to commitment tree, l1 to l2 message tree, and nullifier tree. */
70
71
  export interface CommitmentsDB {
71
72
  /**
72
- * Gets a confirmed L1 to L2 message for the given message key.
73
+ * Gets a confirmed L1 to L2 message for the given entry key.
73
74
  * TODO(Maddiaa): Can be combined with aztec-node method that does the same thing.
74
- * @param msgKey - The message Key.
75
+ * @param entryKey - The entry key.
75
76
  * @returns - The l1 to l2 message object
76
77
  */
77
- getL1ToL2Message(msgKey: Fr): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>>;
78
+ getL1ToL2MembershipWitness(entryKey: Fr): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>>;
78
79
 
79
80
  /**
80
81
  * Gets the index of a commitment in the note hash tree.
@@ -82,4 +83,18 @@ export interface CommitmentsDB {
82
83
  * @returns - The index of the commitment. Undefined if it does not exist in the tree.
83
84
  */
84
85
  getCommitmentIndex(commitment: Fr): Promise<bigint | undefined>;
86
+
87
+ /**
88
+ * Gets the index of a nullifier in the nullifier tree.
89
+ * @param nullifier - The nullifier.
90
+ * @returns - The index of the nullifier. Undefined if it does not exist in the tree.
91
+ */
92
+ getNullifierIndex(nullifier: Fr): Promise<bigint | undefined>;
93
+
94
+ /**
95
+ * Returns a nullifier membership witness for the given nullifier or undefined if not found.
96
+ * REFACTOR: Same as getL1ToL2MembershipWitness, can be combined with aztec-node method that does almost the same thing.
97
+ * @param nullifier - Nullifier we're looking for.
98
+ */
99
+ getNullifierMembershipWitnessAtLatestBlock(nullifier: Fr): Promise<NullifierMembershipWitness | undefined>;
85
100
  }
@@ -6,12 +6,13 @@ import {
6
6
  ContractStorageUpdateRequest,
7
7
  Fr,
8
8
  FunctionData,
9
+ L2ToL1Message,
9
10
  PublicDataRead,
10
11
  PublicDataUpdateRequest,
11
12
  SideEffect,
12
13
  SideEffectLinkedToNoteHash,
13
14
  } from '@aztec/circuits.js';
14
- import { computePublicDataTreeLeafSlot, computePublicDataTreeValue } from '@aztec/circuits.js/abis';
15
+ import { computePublicDataTreeLeafSlot, computePublicDataTreeValue } from '@aztec/circuits.js/hash';
15
16
 
16
17
  /**
17
18
  * The public function execution result.
@@ -21,10 +22,10 @@ export interface PublicExecutionResult {
21
22
  execution: PublicExecution;
22
23
  /** The return values of the function. */
23
24
  returnValues: Fr[];
24
- /** The new commitments to be inserted into the commitments tree. */
25
- newCommitments: SideEffect[];
25
+ /** The new note hashes to be inserted into the note hashes tree. */
26
+ newNoteHashes: SideEffect[];
26
27
  /** The new l2 to l1 messages generated in this call. */
27
- newL2ToL1Messages: Fr[];
28
+ newL2ToL1Messages: L2ToL1Message[];
28
29
  /** The new nullifiers to be inserted into the nullifier tree. */
29
30
  newNullifiers: SideEffectLinkedToNoteHash[];
30
31
  /** The contract storage reads performed by the function. */
@@ -73,7 +74,7 @@ export function isPublicExecutionResult(
73
74
  */
74
75
  export function collectPublicDataReads(execResult: PublicExecutionResult): PublicDataRead[] {
75
76
  // HACK(#1622): part of temporary hack - may be able to remove this function after public state ordering is fixed
76
- const contractAddress = execResult.execution.contractAddress;
77
+ const contractAddress = execResult.execution.callContext.storageContractAddress;
77
78
 
78
79
  const thisExecPublicDataReads = execResult.contractStorageReads.map(read =>
79
80
  contractStorageReadToPublicDataRead(read, contractAddress),
@@ -93,7 +94,7 @@ export function collectPublicDataReads(execResult: PublicExecutionResult): Publi
93
94
  */
94
95
  export function collectPublicDataUpdateRequests(execResult: PublicExecutionResult): PublicDataUpdateRequest[] {
95
96
  // HACK(#1622): part of temporary hack - may be able to remove this function after public state ordering is fixed
96
- const contractAddress = execResult.execution.contractAddress;
97
+ const contractAddress = execResult.execution.callContext.storageContractAddress;
97
98
 
98
99
  const thisExecPublicDataUpdateRequests = execResult.contractStorageUpdateRequests.map(update =>
99
100
  contractStorageUpdateRequestToPublicDataUpdateRequest(update, contractAddress),
@@ -135,3 +136,26 @@ function contractStorageUpdateRequestToPublicDataUpdateRequest(
135
136
  update.sideEffectCounter!,
136
137
  );
137
138
  }
139
+
140
+ /**
141
+ * Checks whether the child execution result is valid for a static call (no state modifications).
142
+ * @param executionResult - The execution result of a public function
143
+ */
144
+
145
+ export function checkValidStaticCall(
146
+ newNoteHashes: SideEffect[],
147
+ newNullifiers: SideEffectLinkedToNoteHash[],
148
+ contractStorageUpdateRequests: ContractStorageUpdateRequest[],
149
+ newL2ToL1Messages: L2ToL1Message[],
150
+ unencryptedLogs: FunctionL2Logs,
151
+ ) {
152
+ if (
153
+ contractStorageUpdateRequests.length > 0 ||
154
+ newNoteHashes.length > 0 ||
155
+ newNullifiers.length > 0 ||
156
+ newL2ToL1Messages.length > 0 ||
157
+ unencryptedLogs.logs.length > 0
158
+ ) {
159
+ throw new Error('Static call cannot update the state, emit L2->L1 messages or generate logs');
160
+ }
161
+ }
@@ -6,7 +6,7 @@ import { AvmContext } from '../avm/avm_context.js';
6
6
  import { AvmMachineState } from '../avm/avm_machine_state.js';
7
7
  import { AvmSimulator } from '../avm/avm_simulator.js';
8
8
  import { HostStorage } from '../avm/journal/host_storage.js';
9
- import { AvmWorldStateJournal } from '../avm/journal/index.js';
9
+ import { AvmPersistableStateManager } from '../avm/journal/index.js';
10
10
  import {
11
11
  temporaryConvertAvmResults,
12
12
  temporaryCreateAvmExecutionEnvironment,
@@ -16,7 +16,7 @@ import { SideEffectCounter } from '../common/index.js';
16
16
  import { PackedArgsCache } from '../common/packed_args_cache.js';
17
17
  import { AcirSimulator } from '../index.js';
18
18
  import { CommitmentsDB, PublicContractsDB, PublicStateDB } from './db.js';
19
- import { PublicExecution, PublicExecutionResult } from './execution.js';
19
+ import { PublicExecution, PublicExecutionResult, checkValidStaticCall } from './execution.js';
20
20
  import { PublicExecutionContext } from './public_execution_context.js';
21
21
 
22
22
  /**
@@ -52,27 +52,33 @@ export async function executePublicFunction(
52
52
  const {
53
53
  returnValues,
54
54
  newL2ToL1Msgs,
55
- newCommitments: newCommitmentsPadded,
55
+ newNoteHashes: newNoteHashesPadded,
56
56
  newNullifiers: newNullifiersPadded,
57
57
  } = PublicCircuitPublicInputs.fromFields(returnWitness);
58
58
 
59
- const newL2ToL1Messages = newL2ToL1Msgs.filter(v => !v.isZero());
60
- const newCommitments = newCommitmentsPadded.filter(v => !v.isEmpty());
59
+ const newL2ToL1Messages = newL2ToL1Msgs.filter(v => !v.isEmpty());
60
+ const newNoteHashes = newNoteHashesPadded.filter(v => !v.isEmpty());
61
61
  const newNullifiers = newNullifiersPadded.filter(v => !v.isEmpty());
62
62
 
63
63
  const { contractStorageReads, contractStorageUpdateRequests } = context.getStorageActionData();
64
+
64
65
  log(
65
66
  `Contract storage reads: ${contractStorageReads
66
67
  .map(r => r.toFriendlyJSON() + ` - sec: ${r.sideEffectCounter}`)
67
68
  .join(', ')}`,
68
69
  );
70
+ log(
71
+ `Contract storage update requests: ${contractStorageUpdateRequests
72
+ .map(r => r.toFriendlyJSON() + ` - sec: ${r.sideEffectCounter}`)
73
+ .join(', ')}`,
74
+ );
69
75
 
70
76
  const nestedExecutions = context.getNestedExecutions();
71
77
  const unencryptedLogs = context.getUnencryptedLogs();
72
78
 
73
79
  return {
74
80
  execution,
75
- newCommitments,
81
+ newNoteHashes,
76
82
  newL2ToL1Messages,
77
83
  newNullifiers,
78
84
  contractStorageReads,
@@ -124,11 +130,25 @@ export class PublicExecutor {
124
130
  this.commitmentsDb,
125
131
  );
126
132
 
133
+ let executionResult;
134
+
127
135
  try {
128
- return await executePublicFunction(context, acir);
136
+ executionResult = await executePublicFunction(context, acir);
129
137
  } catch (err) {
130
138
  throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during public execution'));
131
139
  }
140
+
141
+ if (executionResult.execution.callContext.isStaticCall) {
142
+ checkValidStaticCall(
143
+ executionResult.newNoteHashes,
144
+ executionResult.newNullifiers,
145
+ executionResult.contractStorageUpdateRequests,
146
+ executionResult.newL2ToL1Messages,
147
+ executionResult.unencryptedLogs,
148
+ );
149
+ }
150
+
151
+ return executionResult;
132
152
  }
133
153
 
134
154
  /**
@@ -144,7 +164,7 @@ export class PublicExecutor {
144
164
  // Temporary code to construct the AVM context
145
165
  // These data structures will permiate across the simulator when the public executor is phased out
146
166
  const hostStorage = new HostStorage(this.stateDb, this.contractsDb, this.commitmentsDb);
147
- const worldStateJournal = new AvmWorldStateJournal(hostStorage);
167
+ const worldStateJournal = new AvmPersistableStateManager(hostStorage);
148
168
  const executionEnv = temporaryCreateAvmExecutionEnvironment(execution, globalVariables);
149
169
  const machineState = new AvmMachineState(0, 0, 0);
150
170
 
@@ -152,7 +172,7 @@ export class PublicExecutor {
152
172
  const simulator = new AvmSimulator(context);
153
173
 
154
174
  const result = await simulator.execute();
155
- const newWorldState = context.worldState.flush();
175
+ const newWorldState = context.persistableState.flush();
156
176
  return temporaryConvertAvmResults(execution, newWorldState, result);
157
177
  }
158
178
  }