@aztec/simulator 0.38.0 → 0.39.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 (131) hide show
  1. package/dest/acvm/oracle/oracle.d.ts +1 -1
  2. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  3. package/dest/acvm/oracle/oracle.js +8 -23
  4. package/dest/acvm/oracle/typed_oracle.d.ts +2 -3
  5. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/typed_oracle.js +4 -7
  7. package/dest/avm/avm_execution_environment.d.ts +4 -3
  8. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  9. package/dest/avm/avm_execution_environment.js +17 -11
  10. package/dest/avm/avm_gas.d.ts.map +1 -1
  11. package/dest/avm/avm_gas.js +3 -1
  12. package/dest/avm/avm_machine_state.d.ts +5 -8
  13. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  14. package/dest/avm/avm_machine_state.js +10 -22
  15. package/dest/avm/avm_message_call_result.d.ts +5 -8
  16. package/dest/avm/avm_message_call_result.d.ts.map +1 -1
  17. package/dest/avm/avm_message_call_result.js +1 -4
  18. package/dest/avm/avm_simulator.d.ts.map +1 -1
  19. package/dest/avm/avm_simulator.js +17 -13
  20. package/dest/avm/errors.d.ts +43 -2
  21. package/dest/avm/errors.d.ts.map +1 -1
  22. package/dest/avm/errors.js +86 -4
  23. package/dest/avm/journal/journal.d.ts.map +1 -1
  24. package/dest/avm/journal/journal.js +4 -3
  25. package/dest/avm/opcodes/conversion.d.ts +16 -0
  26. package/dest/avm/opcodes/conversion.d.ts.map +1 -0
  27. package/dest/avm/opcodes/conversion.js +48 -0
  28. package/dest/avm/opcodes/environment_getters.d.ts +12 -13
  29. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  30. package/dest/avm/opcodes/environment_getters.js +13 -49
  31. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  32. package/dest/avm/opcodes/external_calls.js +11 -1
  33. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  34. package/dest/avm/serialization/bytecode_serialization.js +4 -1
  35. package/dest/avm/serialization/instruction_serialization.d.ts +2 -1
  36. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  37. package/dest/avm/serialization/instruction_serialization.js +3 -1
  38. package/dest/client/client_execution_context.d.ts +28 -1
  39. package/dest/client/client_execution_context.d.ts.map +1 -1
  40. package/dest/client/client_execution_context.js +50 -15
  41. package/dest/client/db_oracle.d.ts +1 -8
  42. package/dest/client/db_oracle.d.ts.map +1 -1
  43. package/dest/client/execution_result.d.ts +4 -1
  44. package/dest/client/execution_result.d.ts.map +1 -1
  45. package/dest/client/execution_result.js +16 -3
  46. package/dest/client/private_execution.d.ts.map +1 -1
  47. package/dest/client/private_execution.js +3 -1
  48. package/dest/client/simulator.d.ts +1 -31
  49. package/dest/client/simulator.d.ts.map +1 -1
  50. package/dest/client/simulator.js +3 -42
  51. package/dest/client/view_data_oracle.d.ts +0 -7
  52. package/dest/client/view_data_oracle.d.ts.map +1 -1
  53. package/dest/client/view_data_oracle.js +1 -10
  54. package/dest/common/errors.d.ts +5 -0
  55. package/dest/common/errors.d.ts.map +1 -1
  56. package/dest/common/errors.js +6 -1
  57. package/dest/index.d.ts +1 -0
  58. package/dest/index.d.ts.map +1 -1
  59. package/dest/index.js +2 -1
  60. package/dest/public/abstract_phase_manager.d.ts +8 -4
  61. package/dest/public/abstract_phase_manager.d.ts.map +1 -1
  62. package/dest/public/abstract_phase_manager.js +38 -14
  63. package/dest/public/app_logic_phase_manager.d.ts +1 -0
  64. package/dest/public/app_logic_phase_manager.d.ts.map +1 -1
  65. package/dest/public/app_logic_phase_manager.js +3 -3
  66. package/dest/public/executor.d.ts.map +1 -1
  67. package/dest/public/executor.js +1 -4
  68. package/dest/public/hints_builder.d.ts +3 -3
  69. package/dest/public/hints_builder.d.ts.map +1 -1
  70. package/dest/public/hints_builder.js +3 -3
  71. package/dest/public/public_processor.d.ts.map +1 -1
  72. package/dest/public/public_processor.js +5 -3
  73. package/dest/public/setup_phase_manager.d.ts +1 -0
  74. package/dest/public/setup_phase_manager.d.ts.map +1 -1
  75. package/dest/public/setup_phase_manager.js +3 -2
  76. package/dest/public/tail_phase_manager.d.ts +1 -0
  77. package/dest/public/tail_phase_manager.d.ts.map +1 -1
  78. package/dest/public/tail_phase_manager.js +2 -1
  79. package/dest/public/teardown_phase_manager.d.ts +1 -0
  80. package/dest/public/teardown_phase_manager.d.ts.map +1 -1
  81. package/dest/public/teardown_phase_manager.js +3 -2
  82. package/dest/public/transitional_adaptors.d.ts.map +1 -1
  83. package/dest/public/transitional_adaptors.js +1 -1
  84. package/dest/rollup/index.d.ts +2 -0
  85. package/dest/rollup/index.d.ts.map +1 -0
  86. package/dest/rollup/index.js +2 -0
  87. package/dest/rollup/rollup.d.ts +77 -0
  88. package/dest/rollup/rollup.d.ts.map +1 -0
  89. package/dest/rollup/rollup.js +78 -0
  90. package/dest/stats/index.d.ts +2 -0
  91. package/dest/stats/index.d.ts.map +1 -0
  92. package/dest/stats/index.js +2 -0
  93. package/dest/stats/stats.d.ts +4 -0
  94. package/dest/stats/stats.d.ts.map +1 -0
  95. package/dest/stats/stats.js +11 -0
  96. package/package.json +8 -8
  97. package/src/acvm/oracle/oracle.ts +23 -27
  98. package/src/acvm/oracle/typed_oracle.ts +12 -9
  99. package/src/avm/avm_execution_environment.ts +34 -42
  100. package/src/avm/avm_gas.ts +2 -0
  101. package/src/avm/avm_machine_state.ts +14 -25
  102. package/src/avm/avm_message_call_result.ts +3 -14
  103. package/src/avm/avm_simulator.ts +22 -12
  104. package/src/avm/errors.ts +94 -4
  105. package/src/avm/journal/journal.ts +3 -2
  106. package/src/avm/opcodes/conversion.ts +59 -0
  107. package/src/avm/opcodes/environment_getters.ts +13 -66
  108. package/src/avm/opcodes/external_calls.ts +11 -0
  109. package/src/avm/serialization/bytecode_serialization.ts +3 -0
  110. package/src/avm/serialization/instruction_serialization.ts +2 -0
  111. package/src/client/client_execution_context.ts +87 -15
  112. package/src/client/db_oracle.ts +1 -9
  113. package/src/client/execution_result.ts +21 -2
  114. package/src/client/private_execution.ts +2 -0
  115. package/src/client/simulator.ts +2 -80
  116. package/src/client/view_data_oracle.ts +0 -10
  117. package/src/common/errors.ts +5 -0
  118. package/src/index.ts +1 -0
  119. package/src/public/abstract_phase_manager.ts +46 -18
  120. package/src/public/app_logic_phase_manager.ts +2 -1
  121. package/src/public/executor.ts +0 -4
  122. package/src/public/hints_builder.ts +5 -5
  123. package/src/public/public_processor.ts +8 -2
  124. package/src/public/setup_phase_manager.ts +16 -8
  125. package/src/public/tail_phase_manager.ts +6 -1
  126. package/src/public/teardown_phase_manager.ts +16 -8
  127. package/src/public/transitional_adaptors.ts +1 -0
  128. package/src/rollup/index.ts +1 -0
  129. package/src/rollup/rollup.ts +160 -0
  130. package/src/stats/index.ts +1 -0
  131. package/src/stats/stats.ts +20 -0
@@ -63,6 +63,7 @@ export class ClientExecutionContext extends ViewDataOracle {
63
63
  private unencryptedLogs: CountedLog<UnencryptedL2Log>[] = [];
64
64
  private nestedExecutions: ExecutionResult[] = [];
65
65
  private enqueuedPublicFunctionCalls: PublicCallRequest[] = [];
66
+ private publicTeardownFunctionCall: PublicCallRequest = PublicCallRequest.empty();
66
67
 
67
68
  constructor(
68
69
  contractAddress: AztecAddress,
@@ -173,6 +174,13 @@ export class ClientExecutionContext extends ViewDataOracle {
173
174
  return this.enqueuedPublicFunctionCalls;
174
175
  }
175
176
 
177
+ /**
178
+ * Return the public teardown function call set during this execution.
179
+ */
180
+ public getPublicTeardownFunctionCall() {
181
+ return this.publicTeardownFunctionCall;
182
+ }
183
+
176
184
  /**
177
185
  * Pack the given array of arguments.
178
186
  * @param args - Arguments to pack
@@ -262,11 +270,11 @@ export class ClientExecutionContext extends ViewDataOracle {
262
270
 
263
271
  notes.forEach(n => {
264
272
  if (n.index !== undefined) {
265
- const siloedNoteHash = siloNoteHash(n.contractAddress, n.innerNoteHash);
266
- const uniqueSiloedNoteHash = computeUniqueNoteHash(n.nonce, siloedNoteHash);
267
273
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/1386)
268
- // Should always be uniqueSiloedNoteHash when publicly created notes include nonces.
269
- const noteHashForReadRequest = n.nonce.isZero() ? siloedNoteHash : uniqueSiloedNoteHash;
274
+ // Should always call computeUniqueNoteHash when publicly created notes include nonces.
275
+ const uniqueNoteHash = n.nonce.isZero() ? n.innerNoteHash : computeUniqueNoteHash(n.nonce, n.innerNoteHash);
276
+ const siloedNoteHash = siloNoteHash(n.contractAddress, uniqueNoteHash);
277
+ const noteHashForReadRequest = siloedNoteHash;
270
278
  this.noteHashLeafIndexMap.set(noteHashForReadRequest.toBigInt(), n.index);
271
279
  }
272
280
  });
@@ -465,9 +473,7 @@ export class ClientExecutionContext extends ViewDataOracle {
465
473
  }
466
474
 
467
475
  /**
468
- * Creates a PublicCallStackItem object representing the request to call a public function. No function
469
- * is actually called, since that must happen on the sequencer side. All the fields related to the result
470
- * of the execution are empty.
476
+ * Creates a PublicCallStackItem object representing the request to call a public function.
471
477
  * @param targetContractAddress - The address of the contract to call.
472
478
  * @param functionSelector - The function selector of the function to call.
473
479
  * @param argsHash - The packed arguments to pass to the function.
@@ -475,7 +481,8 @@ export class ClientExecutionContext extends ViewDataOracle {
475
481
  * @param isStaticCall - Whether the call is a static call.
476
482
  * @returns The public call stack item with the request information.
477
483
  */
478
- public override async enqueuePublicFunctionCall(
484
+ protected async createPublicCallRequest(
485
+ callType: 'enqueued' | 'teardown',
479
486
  targetContractAddress: AztecAddress,
480
487
  functionSelector: FunctionSelector,
481
488
  argsHash: Fr,
@@ -494,20 +501,51 @@ export class ClientExecutionContext extends ViewDataOracle {
494
501
  isStaticCall,
495
502
  );
496
503
  const args = this.packedValuesCache.unpack(argsHash);
497
- const enqueuedRequest = PublicCallRequest.from({
504
+
505
+ // TODO($846): if enqueued public calls are associated with global
506
+ // side-effect counter, that will leak info about how many other private
507
+ // side-effects occurred in the TX. Ultimately the private kernel should
508
+ // just output everything in the proper order without any counters.
509
+ this.log.verbose(
510
+ `Created PublicCallRequest of type [${callType}], side-effect counter [${sideEffectCounter}] to ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`,
511
+ );
512
+
513
+ return PublicCallRequest.from({
498
514
  args,
499
515
  callContext: derivedCallContext,
500
516
  parentCallContext: this.callContext,
501
517
  functionData: FunctionData.fromAbi(targetArtifact),
502
518
  contractAddress: targetContractAddress,
503
519
  });
520
+ }
504
521
 
505
- // TODO($846): if enqueued public calls are associated with global
506
- // side-effect counter, that will leak info about how many other private
507
- // side-effects occurred in the TX. Ultimately the private kernel should
508
- // just output everything in the proper order without any counters.
509
- this.log.verbose(
510
- `Enqueued call to public function (with side-effect counter #${sideEffectCounter}) ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`,
522
+ /**
523
+ * Creates and enqueues a PublicCallStackItem object representing the request to call a public function. No function
524
+ * is actually called, since that must happen on the sequencer side. All the fields related to the result
525
+ * of the execution are empty.
526
+ * @param targetContractAddress - The address of the contract to call.
527
+ * @param functionSelector - The function selector of the function to call.
528
+ * @param argsHash - The packed arguments to pass to the function.
529
+ * @param sideEffectCounter - The side effect counter at the start of the call.
530
+ * @param isStaticCall - Whether the call is a static call.
531
+ * @returns The public call stack item with the request information.
532
+ */
533
+ public override async enqueuePublicFunctionCall(
534
+ targetContractAddress: AztecAddress,
535
+ functionSelector: FunctionSelector,
536
+ argsHash: Fr,
537
+ sideEffectCounter: number,
538
+ isStaticCall: boolean,
539
+ isDelegateCall: boolean,
540
+ ): Promise<PublicCallRequest> {
541
+ const enqueuedRequest = await this.createPublicCallRequest(
542
+ 'enqueued',
543
+ targetContractAddress,
544
+ functionSelector,
545
+ argsHash,
546
+ sideEffectCounter,
547
+ isStaticCall,
548
+ isDelegateCall,
511
549
  );
512
550
 
513
551
  this.enqueuedPublicFunctionCalls.push(enqueuedRequest);
@@ -515,6 +553,40 @@ export class ClientExecutionContext extends ViewDataOracle {
515
553
  return enqueuedRequest;
516
554
  }
517
555
 
556
+ /**
557
+ * Creates a PublicCallStackItem and sets it as the public teardown function. No function
558
+ * is actually called, since that must happen on the sequencer side. All the fields related to the result
559
+ * of the execution are empty.
560
+ * @param targetContractAddress - The address of the contract to call.
561
+ * @param functionSelector - The function selector of the function to call.
562
+ * @param argsHash - The packed arguments to pass to the function.
563
+ * @param sideEffectCounter - The side effect counter at the start of the call.
564
+ * @param isStaticCall - Whether the call is a static call.
565
+ * @returns The public call stack item with the request information.
566
+ */
567
+ public override async setPublicTeardownFunctionCall(
568
+ targetContractAddress: AztecAddress,
569
+ functionSelector: FunctionSelector,
570
+ argsHash: Fr,
571
+ sideEffectCounter: number,
572
+ isStaticCall: boolean,
573
+ isDelegateCall: boolean,
574
+ ): Promise<PublicCallRequest> {
575
+ const publicTeardownFunctionCall = await this.createPublicCallRequest(
576
+ 'teardown',
577
+ targetContractAddress,
578
+ functionSelector,
579
+ argsHash,
580
+ sideEffectCounter,
581
+ isStaticCall,
582
+ isDelegateCall,
583
+ );
584
+
585
+ this.publicTeardownFunctionCall = publicTeardownFunctionCall;
586
+
587
+ return publicTeardownFunctionCall;
588
+ }
589
+
518
590
  /**
519
591
  * Derives the call context for a nested execution.
520
592
  * @param targetContractAddress - The address of the contract being called.
@@ -8,7 +8,7 @@ import {
8
8
  import { type CompleteAddress, type Header } from '@aztec/circuits.js';
9
9
  import { type FunctionArtifact, type FunctionSelector } from '@aztec/foundation/abi';
10
10
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
11
- import { type Fr, type Point } from '@aztec/foundation/fields';
11
+ import { type Fr } from '@aztec/foundation/fields';
12
12
  import { type ContractInstance } from '@aztec/types/contracts';
13
13
 
14
14
  import { type NoteData, type NullifierKeys } from '../acvm/index.js';
@@ -64,14 +64,6 @@ export interface DBOracle extends CommitmentsDB {
64
64
  */
65
65
  popCapsule(): Promise<Fr[]>;
66
66
 
67
- /**
68
- * Gets public keys for an address.
69
- * @param The address to look up
70
- * @returns The public keys for a specific address
71
- * TODO(#5834): Replace with `getCompleteAddress`.
72
- */
73
- getPublicKeysForAddress(address: AztecAddress): Promise<Point[]>;
74
-
75
67
  /**
76
68
  * Retrieve nullifier keys associated with a specific account and app/contract address.
77
69
  *
@@ -5,7 +5,7 @@ import {
5
5
  UnencryptedFunctionL2Logs,
6
6
  type UnencryptedL2Log,
7
7
  } from '@aztec/circuit-types';
8
- import { type IsEmpty, type PrivateCallStackItem, type PublicCallRequest, sortByCounter } from '@aztec/circuits.js';
8
+ import { type IsEmpty, type PrivateCallStackItem, PublicCallRequest, sortByCounter } from '@aztec/circuits.js';
9
9
  import { type Fr } from '@aztec/foundation/fields';
10
10
 
11
11
  import { type ACVMField } from '../acvm/index.js';
@@ -56,6 +56,8 @@ export interface ExecutionResult {
56
56
  nestedExecutions: this[];
57
57
  /** Enqueued public function execution requests to be picked up by the sequencer. */
58
58
  enqueuedPublicFunctionCalls: PublicCallRequest[];
59
+ /** Public function execution requested for teardown */
60
+ publicTeardownFunctionCall: PublicCallRequest;
59
61
  /**
60
62
  * Encrypted logs emitted during execution of this function call.
61
63
  * Note: These are preimages to `encryptedLogsHashes`.
@@ -130,6 +132,23 @@ export function collectEnqueuedPublicFunctionCalls(execResult: ExecutionResult):
130
132
  // as the kernel processes it like a stack, popping items off and pushing them to output
131
133
  return [
132
134
  ...execResult.enqueuedPublicFunctionCalls,
133
- ...[...execResult.nestedExecutions].flatMap(collectEnqueuedPublicFunctionCalls),
135
+ ...execResult.nestedExecutions.flatMap(collectEnqueuedPublicFunctionCalls),
134
136
  ].sort((a, b) => b.callContext.sideEffectCounter - a.callContext.sideEffectCounter);
135
137
  }
138
+
139
+ export function collectPublicTeardownFunctionCall(execResult: ExecutionResult): PublicCallRequest {
140
+ const teardownCalls = [
141
+ execResult.publicTeardownFunctionCall,
142
+ ...execResult.nestedExecutions.flatMap(collectPublicTeardownFunctionCall),
143
+ ].filter(call => !call.isEmpty());
144
+
145
+ if (teardownCalls.length === 1) {
146
+ return teardownCalls[0];
147
+ }
148
+
149
+ if (teardownCalls.length > 1) {
150
+ throw new Error('Multiple public teardown calls detected');
151
+ }
152
+
153
+ return PublicCallRequest.empty();
154
+ }
@@ -54,6 +54,7 @@ export async function executePrivateFunction(
54
54
  const nullifiedNoteHashCounters = context.getNullifiedNoteHashCounters();
55
55
  const nestedExecutions = context.getNestedExecutions();
56
56
  const enqueuedPublicFunctionCalls = context.getEnqueuedPublicFunctionCalls();
57
+ const publicTeardownFunctionCall = context.getPublicTeardownFunctionCall();
57
58
 
58
59
  log.debug(`Returning from call to ${contractAddress.toString()}:${functionSelector}`);
59
60
 
@@ -68,6 +69,7 @@ export async function executePrivateFunction(
68
69
  vk: Buffer.from(artifact.verificationKey!, 'hex'),
69
70
  nestedExecutions,
70
71
  enqueuedPublicFunctionCalls,
72
+ publicTeardownFunctionCall,
71
73
  encryptedLogs,
72
74
  unencryptedLogs,
73
75
  };
@@ -200,7 +200,7 @@ export class AcirSimulator {
200
200
  args: encodeArguments(artifact, [contractAddress, nonce, storageSlot, noteTypeId, extendedNoteItems]),
201
201
  };
202
202
 
203
- const [innerNoteHash, siloedNoteHash, uniqueSiloedNoteHash, innerNullifier] = (await this.runUnconstrained(
203
+ const [innerNoteHash, uniqueNoteHash, siloedNoteHash, innerNullifier] = (await this.runUnconstrained(
204
204
  execRequest,
205
205
  artifact,
206
206
  contractAddress,
@@ -208,8 +208,8 @@ export class AcirSimulator {
208
208
 
209
209
  return {
210
210
  innerNoteHash: new Fr(innerNoteHash),
211
+ uniqueNoteHash: new Fr(uniqueNoteHash),
211
212
  siloedNoteHash: new Fr(siloedNoteHash),
212
- uniqueSiloedNoteHash: new Fr(uniqueSiloedNoteHash),
213
213
  innerNullifier: new Fr(innerNullifier),
214
214
  };
215
215
  }
@@ -232,82 +232,4 @@ export class AcirSimulator {
232
232
  );
233
233
  return innerNoteHash;
234
234
  }
235
-
236
- /**
237
- * Computes the unique note hash of a note.
238
- * @param contractAddress - The address of the contract.
239
- * @param nonce - The nonce of the note hash.
240
- * @param storageSlot - The storage slot.
241
- * @param noteTypeId - The note type identifier.
242
- * @param note - The note.
243
- * @returns The note hash.
244
- */
245
- public async computeUniqueSiloedNoteHash(
246
- contractAddress: AztecAddress,
247
- nonce: Fr,
248
- storageSlot: Fr,
249
- noteTypeId: Fr,
250
- note: Note,
251
- ) {
252
- const { uniqueSiloedNoteHash } = await this.computeNoteHashAndNullifier(
253
- contractAddress,
254
- nonce,
255
- storageSlot,
256
- noteTypeId,
257
- note,
258
- );
259
- return uniqueSiloedNoteHash;
260
- }
261
-
262
- /**
263
- * Computes the siloed note hash of a note.
264
- * @param contractAddress - The address of the contract.
265
- * @param nonce - The nonce of the note hash.
266
- * @param storageSlot - The storage slot.
267
- * @param noteTypeId - The note type identifier.
268
- * @param note - The note.
269
- * @returns The note hash.
270
- */
271
- public async computeSiloedNoteHash(
272
- contractAddress: AztecAddress,
273
- nonce: Fr,
274
- storageSlot: Fr,
275
- noteTypeId: Fr,
276
- note: Note,
277
- ) {
278
- const { siloedNoteHash } = await this.computeNoteHashAndNullifier(
279
- contractAddress,
280
- nonce,
281
- storageSlot,
282
- noteTypeId,
283
- note,
284
- );
285
- return siloedNoteHash;
286
- }
287
-
288
- /**
289
- * Computes the inner note hash of a note, which contains storage slot and the custom note hash.
290
- * @param contractAddress - The address of the contract.
291
- * @param nonce - The nonce of the unique note hash.
292
- * @param storageSlot - The storage slot.
293
- * @param noteTypeId - The note type identifier.
294
- * @param note - The note.
295
- * @returns The note hash.
296
- */
297
- public async computeInnerNullifier(
298
- contractAddress: AztecAddress,
299
- nonce: Fr,
300
- storageSlot: Fr,
301
- noteTypeId: Fr,
302
- note: Note,
303
- ) {
304
- const { innerNullifier } = await this.computeNoteHashAndNullifier(
305
- contractAddress,
306
- nonce,
307
- storageSlot,
308
- noteTypeId,
309
- note,
310
- );
311
- return innerNullifier;
312
- }
313
235
  }
@@ -166,16 +166,6 @@ export class ViewDataOracle extends TypedOracle {
166
166
  return this.db.popCapsule();
167
167
  }
168
168
 
169
- /**
170
- * Gets public keys for an address.
171
- * @param The address to look up
172
- * @returns The public keys for a specific address
173
- * TODO(#5834): Replace with `getCompleteAddress`.
174
- */
175
- public override getPublicKeysForAddress(address: AztecAddress) {
176
- return this.db.getPublicKeysForAddress(address);
177
- }
178
-
179
169
  /**
180
170
  * Gets some notes for a contract address and storage slot.
181
171
  * Returns a flattened array containing filtered notes.
@@ -2,6 +2,11 @@ import { type FailingFunction, type NoirCallStack, SimulationError } from '@azte
2
2
 
3
3
  /**
4
4
  * An error that occurred during the execution of a function.
5
+ * @param message - the error message
6
+ * @param failingFunction - the Aztec function that failed
7
+ * @param noirCallStack - the internal call stack of the function that failed (within the failing Aztec function)
8
+ * @param options - additional error options (an optional "cause" entry allows for a recursive error stack where
9
+ * an error's cause may be an ExecutionError itself)
5
10
  */
6
11
  export class ExecutionError extends Error {
7
12
  constructor(
package/src/index.ts CHANGED
@@ -4,3 +4,4 @@ export * from './common/index.js';
4
4
  export * from './public/index.js';
5
5
  export * from './simulator/index.js';
6
6
  export * from './mocks/index.js';
7
+ export * from './stats/index.js';
@@ -2,6 +2,7 @@ import {
2
2
  MerkleTreeId,
3
3
  type ProcessReturnValues,
4
4
  type PublicKernelRequest,
5
+ PublicKernelType,
5
6
  type SimulationError,
6
7
  type Tx,
7
8
  type UnencryptedFunctionL2Logs,
@@ -31,7 +32,6 @@ import {
31
32
  MembershipWitness,
32
33
  NoteHash,
33
34
  Nullifier,
34
- type PrivateKernelTailCircuitPublicInputs,
35
35
  type Proof,
36
36
  PublicCallData,
37
37
  type PublicCallRequest,
@@ -81,6 +81,20 @@ export const PhaseIsRevertible: Record<PublicKernelPhase, boolean> = {
81
81
  [PublicKernelPhase.TAIL]: false,
82
82
  };
83
83
 
84
+ // REFACTOR: Unify both enums and move to types or circuit-types.
85
+ export function publicKernelPhaseToKernelType(phase: PublicKernelPhase): PublicKernelType {
86
+ switch (phase) {
87
+ case PublicKernelPhase.SETUP:
88
+ return PublicKernelType.SETUP;
89
+ case PublicKernelPhase.APP_LOGIC:
90
+ return PublicKernelType.APP_LOGIC;
91
+ case PublicKernelPhase.TEARDOWN:
92
+ return PublicKernelType.TEARDOWN;
93
+ case PublicKernelPhase.TAIL:
94
+ return PublicKernelType.TAIL;
95
+ }
96
+ }
97
+
84
98
  export abstract class AbstractPhaseManager {
85
99
  protected hintsBuilder: HintsBuilder;
86
100
  protected log: DebugLogger;
@@ -127,13 +141,12 @@ export abstract class AbstractPhaseManager {
127
141
  */
128
142
  revertReason: SimulationError | undefined;
129
143
  returnValues: ProcessReturnValues;
144
+ /** Gas used during the execution this particular phase. */
145
+ gasUsed: Gas | undefined;
130
146
  }>;
131
147
 
132
- public static extractEnqueuedPublicCallsByPhase(
133
- publicInputs: PrivateKernelTailCircuitPublicInputs,
134
- enqueuedPublicFunctionCalls: PublicCallRequest[],
135
- ): Record<PublicKernelPhase, PublicCallRequest[]> {
136
- const data = publicInputs.forPublic;
148
+ public static extractEnqueuedPublicCallsByPhase(tx: Tx): Record<PublicKernelPhase, PublicCallRequest[]> {
149
+ const data = tx.data.forPublic;
137
150
  if (!data) {
138
151
  return {
139
152
  [PublicKernelPhase.SETUP]: [],
@@ -142,7 +155,7 @@ export abstract class AbstractPhaseManager {
142
155
  [PublicKernelPhase.TAIL]: [],
143
156
  };
144
157
  }
145
- const publicCallsStack = enqueuedPublicFunctionCalls.slice().reverse();
158
+ const publicCallsStack = tx.enqueuedPublicFunctionCalls.slice().reverse();
146
159
  const nonRevertibleCallStack = data.endNonRevertibleData.publicCallStack.filter(i => !i.isEmpty());
147
160
  const revertibleCallStack = data.end.publicCallStack.filter(i => !i.isEmpty());
148
161
 
@@ -169,39 +182,40 @@ export abstract class AbstractPhaseManager {
169
182
  c => revertibleCallStack.findIndex(p => p.equals(c)) !== -1,
170
183
  );
171
184
 
185
+ const teardownCallStack = tx.publicTeardownFunctionCall.isEmpty() ? [] : [tx.publicTeardownFunctionCall];
186
+
172
187
  if (firstRevertibleCallIndex === 0) {
173
188
  return {
174
189
  [PublicKernelPhase.SETUP]: [],
175
190
  [PublicKernelPhase.APP_LOGIC]: publicCallsStack,
176
- [PublicKernelPhase.TEARDOWN]: [],
191
+ [PublicKernelPhase.TEARDOWN]: teardownCallStack,
177
192
  [PublicKernelPhase.TAIL]: [],
178
193
  };
179
194
  } else if (firstRevertibleCallIndex === -1) {
180
195
  // there's no app logic, split the functions between setup (many) and teardown (just one function call)
181
196
  return {
182
- [PublicKernelPhase.SETUP]: publicCallsStack.slice(0, -1),
197
+ [PublicKernelPhase.SETUP]: publicCallsStack,
183
198
  [PublicKernelPhase.APP_LOGIC]: [],
184
- [PublicKernelPhase.TEARDOWN]: [publicCallsStack[publicCallsStack.length - 1]],
199
+ [PublicKernelPhase.TEARDOWN]: teardownCallStack,
185
200
  [PublicKernelPhase.TAIL]: [],
186
201
  };
187
202
  } else {
188
203
  return {
189
- [PublicKernelPhase.SETUP]: publicCallsStack.slice(0, firstRevertibleCallIndex - 1),
204
+ [PublicKernelPhase.SETUP]: publicCallsStack.slice(0, firstRevertibleCallIndex),
190
205
  [PublicKernelPhase.APP_LOGIC]: publicCallsStack.slice(firstRevertibleCallIndex),
191
- [PublicKernelPhase.TEARDOWN]: [publicCallsStack[firstRevertibleCallIndex - 1]],
206
+ [PublicKernelPhase.TEARDOWN]: teardownCallStack,
192
207
  [PublicKernelPhase.TAIL]: [],
193
208
  };
194
209
  }
195
210
  }
196
211
 
197
212
  protected extractEnqueuedPublicCalls(tx: Tx): PublicCallRequest[] {
198
- const calls = AbstractPhaseManager.extractEnqueuedPublicCallsByPhase(tx.data, tx.enqueuedPublicFunctionCalls)[
199
- this.phase
200
- ];
213
+ const calls = AbstractPhaseManager.extractEnqueuedPublicCallsByPhase(tx)[this.phase];
201
214
 
202
215
  return calls;
203
216
  }
204
217
 
218
+ // REFACTOR: Do not return an array and instead return a struct with similar shape to that returned by `handle`
205
219
  protected async processEnqueuedPublicCalls(
206
220
  tx: Tx,
207
221
  previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
@@ -214,6 +228,7 @@ export abstract class AbstractPhaseManager {
214
228
  UnencryptedFunctionL2Logs[],
215
229
  SimulationError | undefined,
216
230
  ProcessReturnValues,
231
+ Gas,
217
232
  ]
218
233
  > {
219
234
  let kernelOutput = previousPublicKernelOutput;
@@ -223,7 +238,7 @@ export abstract class AbstractPhaseManager {
223
238
  const enqueuedCalls = this.extractEnqueuedPublicCalls(tx);
224
239
 
225
240
  if (!enqueuedCalls || !enqueuedCalls.length) {
226
- return [[], kernelOutput, kernelProof, [], undefined, undefined];
241
+ return [[], kernelOutput, kernelProof, [], undefined, undefined, Gas.empty()];
227
242
  }
228
243
 
229
244
  const newUnencryptedFunctionLogs: UnencryptedFunctionL2Logs[] = [];
@@ -236,6 +251,7 @@ export abstract class AbstractPhaseManager {
236
251
  // and submitted separately to the base rollup?
237
252
 
238
253
  let returns: ProcessReturnValues = undefined;
254
+ let gasUsed = Gas.empty();
239
255
 
240
256
  for (const enqueuedCall of enqueuedCalls) {
241
257
  const executionStack: (PublicExecution | PublicExecutionResult)[] = [enqueuedCall];
@@ -263,7 +279,18 @@ export abstract class AbstractPhaseManager {
263
279
  )
264
280
  : current;
265
281
 
282
+ // Sanity check for a current upstream assumption.
283
+ // Consumers of the result seem to expect "reverted <=> revertReason !== undefined".
266
284
  const functionSelector = result.execution.functionData.selector.toString();
285
+ if (result.reverted && !result.revertReason) {
286
+ throw new Error(
287
+ `Simulation of ${result.execution.contractAddress.toString()}:${functionSelector} reverted with no reason.`,
288
+ );
289
+ }
290
+
291
+ // Accumulate gas used in this execution
292
+ gasUsed = gasUsed.add(Gas.from(result.startGasLeft).sub(Gas.from(result.endGasLeft)));
293
+
267
294
  if (result.reverted && !PhaseIsRevertible[this.phase]) {
268
295
  this.log.debug(
269
296
  `Simulation error on ${result.execution.contractAddress.toString()}:${functionSelector} with reason: ${
@@ -306,7 +333,8 @@ export abstract class AbstractPhaseManager {
306
333
  result.revertReason
307
334
  }`,
308
335
  );
309
- return [[], kernelOutput, kernelProof, [], result.revertReason, undefined];
336
+ // TODO(@spalladino): Check gasUsed is correct. The AVM should take care of setting gasLeft to zero upon a revert.
337
+ return [[], kernelOutput, kernelProof, [], result.revertReason, undefined, gasUsed];
310
338
  }
311
339
 
312
340
  if (!enqueuedExecutionResult) {
@@ -322,7 +350,7 @@ export abstract class AbstractPhaseManager {
322
350
  // TODO(#3675): This should be done in a public kernel circuit
323
351
  removeRedundantPublicDataWrites(kernelOutput, this.phase);
324
352
 
325
- return [publicKernelInputs, kernelOutput, kernelProof, newUnencryptedFunctionLogs, undefined, returns];
353
+ return [publicKernelInputs, kernelOutput, kernelProof, newUnencryptedFunctionLogs, undefined, returns, gasUsed];
326
354
  }
327
355
 
328
356
  /** Returns all pending private and public nullifiers. */
@@ -47,6 +47,7 @@ export class AppLogicPhaseManager extends AbstractPhaseManager {
47
47
  newUnencryptedFunctionLogs,
48
48
  revertReason,
49
49
  returnValues,
50
+ gasUsed,
50
51
  ] = await this.processEnqueuedPublicCalls(tx, previousPublicKernelOutput, previousPublicKernelProof).catch(
51
52
  // if we throw for any reason other than simulation, we need to rollback and drop the TX
52
53
  async err => {
@@ -71,6 +72,6 @@ export class AppLogicPhaseManager extends AbstractPhaseManager {
71
72
  };
72
73
  return request;
73
74
  });
74
- return { kernelRequests, publicKernelOutput, publicKernelProof, revertReason, returnValues };
75
+ return { kernelRequests, publicKernelOutput, publicKernelProof, revertReason, returnValues, gasUsed };
75
76
  }
76
77
  }
@@ -168,10 +168,6 @@ async function executePublicFunctionAcvm(
168
168
  })();
169
169
 
170
170
  if (reverted) {
171
- if (!revertReason) {
172
- throw new Error('Reverted but no revert reason');
173
- }
174
-
175
171
  return {
176
172
  execution,
177
173
  returnValues: [],
@@ -15,11 +15,11 @@ import {
15
15
  type PublicDataRead,
16
16
  type PublicDataTreeLeafPreimage,
17
17
  type PublicDataUpdateRequest,
18
- type ReadRequestContext,
18
+ type ScopedReadRequest,
19
19
  buildNullifierNonExistentReadRequestHints,
20
- buildNullifierReadRequestHints,
21
20
  buildPublicDataHints,
22
21
  buildPublicDataReadRequestHints,
22
+ buildSiloedNullifierReadRequestHints,
23
23
  } from '@aztec/circuits.js';
24
24
  import { type Tuple } from '@aztec/foundation/serialize';
25
25
  import { type IndexedTreeId, type MerkleTreeOperations } from '@aztec/world-state';
@@ -28,14 +28,14 @@ export class HintsBuilder {
28
28
  constructor(private db: MerkleTreeOperations) {}
29
29
 
30
30
  getNullifierReadRequestHints(
31
- nullifierReadRequests: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>,
31
+ nullifierReadRequests: Tuple<ScopedReadRequest, typeof MAX_NULLIFIER_READ_REQUESTS_PER_TX>,
32
32
  pendingNullifiers: Tuple<Nullifier, typeof MAX_NEW_NULLIFIERS_PER_TX>,
33
33
  ) {
34
- return buildNullifierReadRequestHints(this, nullifierReadRequests, pendingNullifiers);
34
+ return buildSiloedNullifierReadRequestHints(this, nullifierReadRequests, pendingNullifiers);
35
35
  }
36
36
 
37
37
  getNullifierNonExistentReadRequestHints(
38
- nullifierNonExistentReadRequests: Tuple<ReadRequestContext, typeof MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX>,
38
+ nullifierNonExistentReadRequests: Tuple<ScopedReadRequest, typeof MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX>,
39
39
  pendingNullifiers: Tuple<Nullifier, typeof MAX_NEW_NULLIFIERS_PER_TX>,
40
40
  ) {
41
41
  return buildNullifierNonExistentReadRequestHints(this, nullifierNonExistentReadRequests, pendingNullifiers);
@@ -20,7 +20,11 @@ import { PublicExecutor, type PublicStateDB, type SimulationProvider } from '@az
20
20
  import { type ContractDataSource } from '@aztec/types/contracts';
21
21
  import { type MerkleTreeOperations } from '@aztec/world-state';
22
22
 
23
- import { type AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
23
+ import {
24
+ type AbstractPhaseManager,
25
+ PublicKernelPhase,
26
+ publicKernelPhaseToKernelType,
27
+ } from './abstract_phase_manager.js';
24
28
  import { PhaseManagerFactory } from './phase_manager_factory.js';
25
29
  import { ContractsDataSourcePublicDB, WorldStateDB, WorldStatePublicDB } from './public_executor.js';
26
30
  import { RealPublicKernelCircuitSimulator } from './public_kernel.js';
@@ -169,8 +173,10 @@ export class PublicProcessor {
169
173
  let finalKernelOutput: KernelCircuitPublicInputs | undefined;
170
174
  let revertReason: SimulationError | undefined;
171
175
  const timer = new Timer();
176
+ const gasUsed: ProcessedTx['gasUsed'] = {};
172
177
  while (phase) {
173
178
  const output = await phase.handle(tx, publicKernelPublicInput, proof);
179
+ gasUsed[publicKernelPhaseToKernelType(phase.phase)] = output.gasUsed;
174
180
  if (phase.phase === PublicKernelPhase.APP_LOGIC) {
175
181
  returnValues = output.returnValues;
176
182
  }
@@ -196,7 +202,7 @@ export class PublicProcessor {
196
202
  throw new Error('Final public kernel was not executed.');
197
203
  }
198
204
 
199
- const processedTx = makeProcessedTx(tx, finalKernelOutput, proof, publicRequests, revertReason);
205
+ const processedTx = makeProcessedTx(tx, finalKernelOutput, proof, publicRequests, revertReason, gasUsed);
200
206
 
201
207
  this.log.debug(`Processed public part of ${tx.getTxHash()}`, {
202
208
  eventName: 'tx-sequencer-processing',