@aztec/simulator 0.37.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 (181) hide show
  1. package/dest/acvm/acvm.d.ts +1 -1
  2. package/dest/acvm/acvm.d.ts.map +1 -1
  3. package/dest/acvm/acvm.js +2 -2
  4. package/dest/acvm/oracle/oracle.d.ts +6 -5
  5. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/oracle.js +26 -30
  7. package/dest/acvm/oracle/typed_oracle.d.ts +5 -5
  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_execution_environment.d.ts +4 -3
  11. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  12. package/dest/avm/avm_execution_environment.js +17 -11
  13. package/dest/avm/avm_gas.d.ts.map +1 -1
  14. package/dest/avm/avm_gas.js +4 -1
  15. package/dest/avm/avm_machine_state.d.ts +5 -8
  16. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  17. package/dest/avm/avm_machine_state.js +10 -22
  18. package/dest/avm/avm_memory_types.d.ts +1 -1
  19. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  20. package/dest/avm/avm_message_call_result.d.ts +5 -8
  21. package/dest/avm/avm_message_call_result.d.ts.map +1 -1
  22. package/dest/avm/avm_message_call_result.js +1 -4
  23. package/dest/avm/avm_simulator.d.ts.map +1 -1
  24. package/dest/avm/avm_simulator.js +19 -13
  25. package/dest/avm/errors.d.ts +43 -2
  26. package/dest/avm/errors.d.ts.map +1 -1
  27. package/dest/avm/errors.js +86 -4
  28. package/dest/avm/journal/journal.d.ts +20 -1
  29. package/dest/avm/journal/journal.d.ts.map +1 -1
  30. package/dest/avm/journal/journal.js +70 -9
  31. package/dest/avm/journal/nullifiers.d.ts +3 -1
  32. package/dest/avm/journal/nullifiers.d.ts.map +1 -1
  33. package/dest/avm/journal/nullifiers.js +14 -6
  34. package/dest/avm/journal/public_storage.d.ts +10 -1
  35. package/dest/avm/journal/public_storage.d.ts.map +1 -1
  36. package/dest/avm/journal/public_storage.js +17 -2
  37. package/dest/avm/journal/trace.d.ts +1 -4
  38. package/dest/avm/journal/trace.d.ts.map +1 -1
  39. package/dest/avm/journal/trace.js +4 -5
  40. package/dest/avm/journal/trace_types.d.ts +1 -0
  41. package/dest/avm/journal/trace_types.d.ts.map +1 -1
  42. package/dest/avm/journal/trace_types.js +1 -1
  43. package/dest/avm/opcodes/bitwise.d.ts +4 -1
  44. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  45. package/dest/avm/opcodes/bitwise.js +14 -2
  46. package/dest/avm/opcodes/conversion.d.ts +16 -0
  47. package/dest/avm/opcodes/conversion.d.ts.map +1 -0
  48. package/dest/avm/opcodes/conversion.js +48 -0
  49. package/dest/avm/opcodes/environment_getters.d.ts +16 -12
  50. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  51. package/dest/avm/opcodes/environment_getters.js +19 -48
  52. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  53. package/dest/avm/opcodes/external_calls.js +24 -13
  54. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  55. package/dest/avm/serialization/bytecode_serialization.js +6 -2
  56. package/dest/avm/serialization/instruction_serialization.d.ts +40 -38
  57. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  58. package/dest/avm/serialization/instruction_serialization.js +42 -39
  59. package/dest/client/client_execution_context.d.ts +59 -19
  60. package/dest/client/client_execution_context.d.ts.map +1 -1
  61. package/dest/client/client_execution_context.js +97 -45
  62. package/dest/client/db_oracle.d.ts +4 -11
  63. package/dest/client/db_oracle.d.ts.map +1 -1
  64. package/dest/client/execution_result.d.ts +22 -15
  65. package/dest/client/execution_result.d.ts.map +1 -1
  66. package/dest/client/execution_result.js +59 -13
  67. package/dest/client/logs_cache.d.ts +33 -0
  68. package/dest/client/logs_cache.d.ts.map +1 -0
  69. package/dest/client/logs_cache.js +59 -0
  70. package/dest/client/private_execution.d.ts +2 -2
  71. package/dest/client/private_execution.d.ts.map +1 -1
  72. package/dest/client/private_execution.js +5 -7
  73. package/dest/client/simulator.d.ts +4 -34
  74. package/dest/client/simulator.d.ts.map +1 -1
  75. package/dest/client/simulator.js +5 -43
  76. package/dest/client/unconstrained_execution.d.ts +2 -2
  77. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  78. package/dest/client/unconstrained_execution.js +1 -1
  79. package/dest/client/view_data_oracle.d.ts +0 -7
  80. package/dest/client/view_data_oracle.d.ts.map +1 -1
  81. package/dest/client/view_data_oracle.js +1 -10
  82. package/dest/common/errors.d.ts +5 -0
  83. package/dest/common/errors.d.ts.map +1 -1
  84. package/dest/common/errors.js +6 -1
  85. package/dest/index.d.ts +1 -0
  86. package/dest/index.d.ts.map +1 -1
  87. package/dest/index.js +2 -1
  88. package/dest/mocks/fixtures.d.ts.map +1 -1
  89. package/dest/mocks/fixtures.js +3 -1
  90. package/dest/public/abstract_phase_manager.d.ts +10 -4
  91. package/dest/public/abstract_phase_manager.d.ts.map +1 -1
  92. package/dest/public/abstract_phase_manager.js +50 -19
  93. package/dest/public/app_logic_phase_manager.d.ts +1 -0
  94. package/dest/public/app_logic_phase_manager.d.ts.map +1 -1
  95. package/dest/public/app_logic_phase_manager.js +3 -3
  96. package/dest/public/execution.d.ts +9 -0
  97. package/dest/public/execution.d.ts.map +1 -1
  98. package/dest/public/execution.js +1 -1
  99. package/dest/public/executor.d.ts +2 -2
  100. package/dest/public/executor.d.ts.map +1 -1
  101. package/dest/public/executor.js +34 -17
  102. package/dest/public/hints_builder.d.ts +3 -3
  103. package/dest/public/hints_builder.d.ts.map +1 -1
  104. package/dest/public/hints_builder.js +3 -3
  105. package/dest/public/public_execution_context.d.ts +10 -4
  106. package/dest/public/public_execution_context.d.ts.map +1 -1
  107. package/dest/public/public_execution_context.js +19 -6
  108. package/dest/public/public_processor.d.ts.map +1 -1
  109. package/dest/public/public_processor.js +5 -3
  110. package/dest/public/setup_phase_manager.d.ts +1 -0
  111. package/dest/public/setup_phase_manager.d.ts.map +1 -1
  112. package/dest/public/setup_phase_manager.js +3 -2
  113. package/dest/public/tail_phase_manager.d.ts +1 -1
  114. package/dest/public/tail_phase_manager.d.ts.map +1 -1
  115. package/dest/public/tail_phase_manager.js +4 -26
  116. package/dest/public/teardown_phase_manager.d.ts +1 -0
  117. package/dest/public/teardown_phase_manager.d.ts.map +1 -1
  118. package/dest/public/teardown_phase_manager.js +3 -2
  119. package/dest/public/transitional_adaptors.d.ts +4 -17
  120. package/dest/public/transitional_adaptors.d.ts.map +1 -1
  121. package/dest/public/transitional_adaptors.js +27 -119
  122. package/dest/rollup/index.d.ts +2 -0
  123. package/dest/rollup/index.d.ts.map +1 -0
  124. package/dest/rollup/index.js +2 -0
  125. package/dest/rollup/rollup.d.ts +77 -0
  126. package/dest/rollup/rollup.d.ts.map +1 -0
  127. package/dest/rollup/rollup.js +78 -0
  128. package/dest/stats/index.d.ts +2 -0
  129. package/dest/stats/index.d.ts.map +1 -0
  130. package/dest/stats/index.js +2 -0
  131. package/dest/stats/stats.d.ts +4 -0
  132. package/dest/stats/stats.d.ts.map +1 -0
  133. package/dest/stats/stats.js +11 -0
  134. package/package.json +8 -8
  135. package/src/acvm/acvm.ts +2 -2
  136. package/src/acvm/oracle/oracle.ts +62 -36
  137. package/src/acvm/oracle/typed_oracle.ts +19 -11
  138. package/src/avm/avm_execution_environment.ts +34 -42
  139. package/src/avm/avm_gas.ts +3 -0
  140. package/src/avm/avm_machine_state.ts +14 -25
  141. package/src/avm/avm_memory_types.ts +1 -1
  142. package/src/avm/avm_message_call_result.ts +3 -14
  143. package/src/avm/avm_simulator.ts +24 -12
  144. package/src/avm/errors.ts +94 -4
  145. package/src/avm/journal/journal.ts +134 -9
  146. package/src/avm/journal/nullifiers.ts +19 -8
  147. package/src/avm/journal/public_storage.ts +23 -2
  148. package/src/avm/journal/trace.ts +3 -4
  149. package/src/avm/journal/trace_types.ts +1 -0
  150. package/src/avm/opcodes/bitwise.ts +18 -7
  151. package/src/avm/opcodes/conversion.ts +59 -0
  152. package/src/avm/opcodes/environment_getters.ts +21 -65
  153. package/src/avm/opcodes/external_calls.ts +32 -16
  154. package/src/avm/serialization/bytecode_serialization.ts +5 -0
  155. package/src/avm/serialization/instruction_serialization.ts +3 -0
  156. package/src/client/client_execution_context.ts +142 -46
  157. package/src/client/db_oracle.ts +4 -18
  158. package/src/client/execution_result.ts +75 -25
  159. package/src/client/logs_cache.ts +65 -0
  160. package/src/client/private_execution.ts +6 -10
  161. package/src/client/simulator.ts +8 -84
  162. package/src/client/unconstrained_execution.ts +2 -2
  163. package/src/client/view_data_oracle.ts +0 -10
  164. package/src/common/errors.ts +5 -0
  165. package/src/index.ts +1 -0
  166. package/src/mocks/fixtures.ts +2 -0
  167. package/src/public/abstract_phase_manager.ts +59 -23
  168. package/src/public/app_logic_phase_manager.ts +2 -1
  169. package/src/public/execution.ts +9 -0
  170. package/src/public/executor.ts +47 -14
  171. package/src/public/hints_builder.ts +5 -5
  172. package/src/public/public_execution_context.ts +18 -4
  173. package/src/public/public_processor.ts +8 -2
  174. package/src/public/setup_phase_manager.ts +16 -8
  175. package/src/public/tail_phase_manager.ts +8 -35
  176. package/src/public/teardown_phase_manager.ts +16 -8
  177. package/src/public/transitional_adaptors.ts +39 -177
  178. package/src/rollup/index.ts +1 -0
  179. package/src/rollup/rollup.ts +160 -0
  180. package/src/stats/index.ts +1 -0
  181. package/src/stats/stats.ts +20 -0
@@ -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];
@@ -246,8 +262,10 @@ export abstract class AbstractPhaseManager {
246
262
  while (executionStack.length) {
247
263
  const current = executionStack.pop()!;
248
264
  const isExecutionRequest = !isPublicExecutionResult(current);
265
+ // TODO(6052): Extract correct new counter from nested calls
249
266
  const sideEffectCounter = lastSideEffectCounter(tx) + 1;
250
- const availableGas = this.getAvailableGas(tx, previousPublicKernelOutput);
267
+ const availableGas = this.getAvailableGas(tx, kernelOutput);
268
+ const pendingNullifiers = this.getSiloedPendingNullifiers(kernelOutput);
251
269
 
252
270
  const result = isExecutionRequest
253
271
  ? await this.publicExecutor.simulate(
@@ -255,12 +273,24 @@ export abstract class AbstractPhaseManager {
255
273
  this.globalVariables,
256
274
  availableGas,
257
275
  tx.data.constants.txContext,
276
+ pendingNullifiers,
258
277
  transactionFee,
259
278
  sideEffectCounter,
260
279
  )
261
280
  : current;
262
281
 
282
+ // Sanity check for a current upstream assumption.
283
+ // Consumers of the result seem to expect "reverted <=> revertReason !== undefined".
263
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
+
264
294
  if (result.reverted && !PhaseIsRevertible[this.phase]) {
265
295
  this.log.debug(
266
296
  `Simulation error on ${result.execution.contractAddress.toString()}:${functionSelector} with reason: ${
@@ -270,7 +300,9 @@ export abstract class AbstractPhaseManager {
270
300
  throw result.revertReason;
271
301
  }
272
302
 
273
- newUnencryptedFunctionLogs.push(result.unencryptedLogs);
303
+ if (isExecutionRequest) {
304
+ newUnencryptedFunctionLogs.push(result.allUnencryptedLogs);
305
+ }
274
306
 
275
307
  this.log.debug(
276
308
  `Running public kernel circuit for ${result.execution.contractAddress.toString()}:${functionSelector}`,
@@ -301,7 +333,8 @@ export abstract class AbstractPhaseManager {
301
333
  result.revertReason
302
334
  }`,
303
335
  );
304
- 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];
305
338
  }
306
339
 
307
340
  if (!enqueuedExecutionResult) {
@@ -317,7 +350,12 @@ export abstract class AbstractPhaseManager {
317
350
  // TODO(#3675): This should be done in a public kernel circuit
318
351
  removeRedundantPublicDataWrites(kernelOutput, this.phase);
319
352
 
320
- return [publicKernelInputs, kernelOutput, kernelProof, newUnencryptedFunctionLogs, undefined, returns];
353
+ return [publicKernelInputs, kernelOutput, kernelProof, newUnencryptedFunctionLogs, undefined, returns, gasUsed];
354
+ }
355
+
356
+ /** Returns all pending private and public nullifiers. */
357
+ private getSiloedPendingNullifiers(ko: PublicKernelCircuitPublicInputs) {
358
+ return [...ko.end.newNullifiers, ...ko.endNonRevertibleData.newNullifiers].filter(n => !n.isEmpty());
321
359
  }
322
360
 
323
361
  protected getAvailableGas(tx: Tx, previousPublicKernelOutput: PublicKernelCircuitPublicInputs) {
@@ -382,8 +420,6 @@ export abstract class AbstractPhaseManager {
382
420
  MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
383
421
  );
384
422
 
385
- const unencryptedLogPreimagesLength = new Fr(result.unencryptedLogs.getSerializedLength());
386
-
387
423
  const publicCircuitPublicInputs = PublicCircuitPublicInputs.from({
388
424
  callContext: result.execution.callContext,
389
425
  proverAddress: AztecAddress.ZERO,
@@ -420,7 +456,7 @@ export abstract class AbstractPhaseManager {
420
456
  SideEffect.empty(),
421
457
  MAX_UNENCRYPTED_LOGS_PER_CALL,
422
458
  ),
423
- unencryptedLogPreimagesLength,
459
+ unencryptedLogPreimagesLength: result.unencryptedLogPreimagesLength,
424
460
  historicalHeader: this.historicalHeader,
425
461
  globalVariables: this.globalVariables,
426
462
  startGasLeft: Gas.from(result.startGasLeft),
@@ -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
  }
@@ -54,6 +54,15 @@ export interface PublicExecutionResult {
54
54
  * Note: These are preimages to `unencryptedLogsHashes`.
55
55
  */
56
56
  unencryptedLogs: UnencryptedFunctionL2Logs;
57
+ /**
58
+ * Length of the unencrypted log preimages emitted in this function call.
59
+ */
60
+ unencryptedLogPreimagesLength: Fr;
61
+ /**
62
+ * Unencrypted logs emitted during this call AND any nested calls.
63
+ * Useful for maintaining correct ordering in ts.
64
+ */
65
+ allUnencryptedLogs: UnencryptedFunctionL2Logs;
57
66
  /**
58
67
  * Whether the execution reverted.
59
68
  */
@@ -4,6 +4,7 @@ import {
4
4
  Gas,
5
5
  type GlobalVariables,
6
6
  type Header,
7
+ type Nullifier,
7
8
  PublicCircuitPublicInputs,
8
9
  type TxContext,
9
10
  } from '@aztec/circuits.js';
@@ -26,7 +27,7 @@ import { PackedValuesCache } from '../common/packed_values_cache.js';
26
27
  import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db.js';
27
28
  import { type PublicExecution, type PublicExecutionResult, checkValidStaticCall } from './execution.js';
28
29
  import { PublicExecutionContext } from './public_execution_context.js';
29
- import { convertAvmResults, createAvmExecutionEnvironment, isAvmBytecode } from './transitional_adaptors.js';
30
+ import { convertAvmResultsToPxResult, createAvmExecutionEnvironment, isAvmBytecode } from './transitional_adaptors.js';
30
31
 
31
32
  /**
32
33
  * Execute a public function and return the execution result.
@@ -46,15 +47,23 @@ export async function executePublicFunction(
46
47
  }
47
48
 
48
49
  if (isAvmBytecode(bytecode)) {
49
- return await executePublicFunctionAvm(context);
50
+ return await executeTopLevelPublicFunctionAvm(context, bytecode);
50
51
  } else {
51
52
  return await executePublicFunctionAcvm(context, bytecode, nested);
52
53
  }
53
54
  }
54
55
 
55
- async function executePublicFunctionAvm(executionContext: PublicExecutionContext): Promise<PublicExecutionResult> {
56
+ /**
57
+ * Execute a top-level public function call (the first call in an enqueued-call/execution-request) in the AVM.
58
+ * Translate the results back to the PublicExecutionResult format.
59
+ */
60
+ async function executeTopLevelPublicFunctionAvm(
61
+ executionContext: PublicExecutionContext,
62
+ bytecode: Buffer,
63
+ ): Promise<PublicExecutionResult> {
56
64
  const address = executionContext.execution.contractAddress;
57
65
  const selector = executionContext.execution.functionData.selector;
66
+ const startGas = executionContext.availableGas;
58
67
  const log = createDebugLogger('aztec:simulator:public_execution');
59
68
  log.verbose(`[AVM] Executing public external function ${address.toString()}:${selector}.`);
60
69
 
@@ -65,7 +74,15 @@ async function executePublicFunctionAvm(executionContext: PublicExecutionContext
65
74
  executionContext.contractsDb,
66
75
  executionContext.commitmentsDb,
67
76
  );
77
+
78
+ // TODO(6207): add sideEffectCounter to persistableState construction
79
+ // or modify the PersistableStateManager to manage rollbacks across enqueued-calls and transactions.
68
80
  const worldStateJournal = new AvmPersistableStateManager(hostStorage);
81
+ const startSideEffectCounter = executionContext.execution.callContext.sideEffectCounter;
82
+ for (const nullifier of executionContext.pendingNullifiers) {
83
+ worldStateJournal.nullifiers.cache.appendSiloed(nullifier.value);
84
+ }
85
+ worldStateJournal.trace.accessCounter = startSideEffectCounter;
69
86
 
70
87
  const executionEnv = createAvmExecutionEnvironment(
71
88
  executionContext.execution,
@@ -75,18 +92,30 @@ async function executePublicFunctionAvm(executionContext: PublicExecutionContext
75
92
  executionContext.transactionFee,
76
93
  );
77
94
 
78
- const machineState = new AvmMachineState(executionContext.availableGas);
79
- const context = new AvmContext(worldStateJournal, executionEnv, machineState);
80
- const simulator = new AvmSimulator(context);
95
+ const machineState = new AvmMachineState(startGas);
96
+ const avmContext = new AvmContext(worldStateJournal, executionEnv, machineState);
97
+ const simulator = new AvmSimulator(avmContext);
98
+
99
+ const avmResult = await simulator.executeBytecode(bytecode);
81
100
 
82
- const result = await simulator.execute();
83
- const newWorldState = context.persistableState.flush();
101
+ // Commit the journals state to the DBs since this is a top-level execution.
102
+ // Observe that this will write all the state changes to the DBs, not only the latest for each slot.
103
+ // However, the underlying DB keep a cache and will only write the latest state to disk.
104
+ await avmContext.persistableState.publicStorage.commitToDB();
84
105
 
85
106
  log.verbose(
86
- `[AVM] ${address.toString()}:${selector} returned, reverted: ${result.reverted}, reason: ${result.revertReason}.`,
107
+ `[AVM] ${address.toString()}:${selector} returned, reverted: ${avmResult.reverted}, reason: ${
108
+ avmResult.revertReason
109
+ }.`,
87
110
  );
88
111
 
89
- return await convertAvmResults(executionContext, newWorldState, result, machineState);
112
+ return convertAvmResultsToPxResult(
113
+ avmResult,
114
+ startSideEffectCounter,
115
+ executionContext.execution,
116
+ startGas,
117
+ avmContext,
118
+ );
90
119
  }
91
120
 
92
121
  async function executePublicFunctionAcvm(
@@ -139,10 +168,6 @@ async function executePublicFunctionAcvm(
139
168
  })();
140
169
 
141
170
  if (reverted) {
142
- if (!revertReason) {
143
- throw new Error('Reverted but no revert reason');
144
- }
145
-
146
171
  return {
147
172
  execution,
148
173
  returnValues: [],
@@ -159,6 +184,8 @@ async function executePublicFunctionAcvm(
159
184
  nestedExecutions: [],
160
185
  unencryptedLogsHashes: [],
161
186
  unencryptedLogs: UnencryptedFunctionL2Logs.empty(),
187
+ unencryptedLogPreimagesLength: new Fr(4n), // empty logs have len 4
188
+ allUnencryptedLogs: UnencryptedFunctionL2Logs.empty(),
162
189
  reverted,
163
190
  revertReason,
164
191
  startGasLeft: context.availableGas,
@@ -182,6 +209,7 @@ async function executePublicFunctionAcvm(
182
209
  startSideEffectCounter,
183
210
  endSideEffectCounter,
184
211
  unencryptedLogsHashes: unencryptedLogsHashesPadded,
212
+ unencryptedLogPreimagesLength,
185
213
  } = PublicCircuitPublicInputs.fromFields(returnWitness);
186
214
  const returnValues = await context.unpackReturns(returnsHash);
187
215
 
@@ -207,6 +235,7 @@ async function executePublicFunctionAcvm(
207
235
 
208
236
  const nestedExecutions = context.getNestedExecutions();
209
237
  const unencryptedLogs = context.getUnencryptedLogs();
238
+ const allUnencryptedLogs = context.getAllUnencryptedLogs();
210
239
 
211
240
  // TODO(palla/gas): We should be loading these values from the returned PublicCircuitPublicInputs
212
241
  const startGasLeft = context.availableGas;
@@ -227,6 +256,8 @@ async function executePublicFunctionAcvm(
227
256
  nestedExecutions,
228
257
  unencryptedLogsHashes,
229
258
  unencryptedLogs,
259
+ unencryptedLogPreimagesLength,
260
+ allUnencryptedLogs,
230
261
  reverted: false,
231
262
  revertReason: undefined,
232
263
  startGasLeft,
@@ -258,6 +289,7 @@ export class PublicExecutor {
258
289
  globalVariables: GlobalVariables,
259
290
  availableGas: Gas,
260
291
  txContext: TxContext,
292
+ pendingNullifiers: Nullifier[],
261
293
  transactionFee: Fr = Fr.ZERO,
262
294
  sideEffectCounter: number = 0,
263
295
  ): Promise<PublicExecutionResult> {
@@ -277,6 +309,7 @@ export class PublicExecutor {
277
309
  availableGas,
278
310
  transactionFee,
279
311
  txContext.gasSettings,
312
+ pendingNullifiers,
280
313
  );
281
314
 
282
315
  const executionResult = await executePublicFunction(context, /*nested=*/ false);
@@ -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);
@@ -7,6 +7,7 @@ import {
7
7
  type GasSettings,
8
8
  type GlobalVariables,
9
9
  type Header,
10
+ type Nullifier,
10
11
  PublicContextInputs,
11
12
  } from '@aztec/circuits.js';
12
13
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
@@ -37,13 +38,18 @@ export class PublicExecutionContext extends TypedOracle {
37
38
  public readonly header: Header,
38
39
  public readonly globalVariables: GlobalVariables,
39
40
  private readonly packedValuesCache: PackedValuesCache,
40
- private readonly sideEffectCounter: SideEffectCounter,
41
+ // TRANSITIONAL: once AVM-ACVM interoperability is removed (fully functional AVM), sideEffectCounter can be made private
42
+ public readonly sideEffectCounter: SideEffectCounter,
41
43
  public readonly stateDb: PublicStateDB,
42
44
  public readonly contractsDb: PublicContractsDB,
43
45
  public readonly commitmentsDb: CommitmentsDB,
44
46
  public readonly availableGas: Gas,
45
47
  public readonly transactionFee: Fr,
46
48
  public readonly gasSettings: GasSettings,
49
+ public readonly pendingNullifiers: Nullifier[],
50
+ // Unencrypted logs emitted during this call AND any nested calls
51
+ // Useful for maintaining correct ordering in ts
52
+ private allUnencryptedLogs: UnencryptedL2Log[] = [],
47
53
  private log = createDebugLogger('aztec:simulator:public_execution_context'),
48
54
  ) {
49
55
  super();
@@ -87,6 +93,13 @@ export class PublicExecutionContext extends TypedOracle {
87
93
  return new UnencryptedFunctionL2Logs(this.unencryptedLogs);
88
94
  }
89
95
 
96
+ /**
97
+ * Return the encrypted logs emitted during this execution, including nested calls.
98
+ */
99
+ public getAllUnencryptedLogs() {
100
+ return new UnencryptedFunctionL2Logs(this.allUnencryptedLogs);
101
+ }
102
+
90
103
  /**
91
104
  * Return the data read and updated during this execution.
92
105
  */
@@ -135,11 +148,10 @@ export class PublicExecutionContext extends TypedOracle {
135
148
  * Emit an unencrypted log.
136
149
  * @param log - The unencrypted log to be emitted.
137
150
  */
138
- public override emitUnencryptedLog(log: UnencryptedL2Log) {
139
- // TODO(https://github.com/AztecProtocol/aztec-packages/issues/885)
151
+ public override emitUnencryptedLog(log: UnencryptedL2Log, _counter: number) {
140
152
  this.unencryptedLogs.push(log);
153
+ this.allUnencryptedLogs.push(log);
141
154
  this.log.verbose(`Emitted unencrypted log: "${log.toHumanReadable()}"`);
142
- return Fr.fromBuffer(log.hash());
143
155
  }
144
156
 
145
157
  /**
@@ -229,6 +241,8 @@ export class PublicExecutionContext extends TypedOracle {
229
241
  this.availableGas,
230
242
  this.transactionFee,
231
243
  this.gasSettings,
244
+ /*pendingNullifiers=*/ [],
245
+ this.allUnencryptedLogs,
232
246
  this.log,
233
247
  );
234
248
 
@@ -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',
@@ -35,14 +35,21 @@ export class SetupPhaseManager extends AbstractPhaseManager {
35
35
  previousPublicKernelProof: Proof,
36
36
  ) {
37
37
  this.log.verbose(`Processing tx ${tx.getTxHash()}`);
38
- const [kernelInputs, publicKernelOutput, publicKernelProof, newUnencryptedFunctionLogs, revertReason] =
39
- await this.processEnqueuedPublicCalls(tx, previousPublicKernelOutput, previousPublicKernelProof).catch(
40
- // the abstract phase manager throws if simulation gives error in a non-revertible phase
41
- async err => {
42
- await this.publicStateDB.rollbackToCommit();
43
- throw err;
44
- },
45
- );
38
+ const [
39
+ kernelInputs,
40
+ publicKernelOutput,
41
+ publicKernelProof,
42
+ newUnencryptedFunctionLogs,
43
+ revertReason,
44
+ _returnValues,
45
+ gasUsed,
46
+ ] = await this.processEnqueuedPublicCalls(tx, previousPublicKernelOutput, previousPublicKernelProof).catch(
47
+ // the abstract phase manager throws if simulation gives error in a non-revertible phase
48
+ async err => {
49
+ await this.publicStateDB.rollbackToCommit();
50
+ throw err;
51
+ },
52
+ );
46
53
  tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
47
54
  await this.publicStateDB.checkpoint();
48
55
 
@@ -61,6 +68,7 @@ export class SetupPhaseManager extends AbstractPhaseManager {
61
68
  publicKernelProof,
62
69
  revertReason,
63
70
  returnValues: undefined,
71
+ gasUsed,
64
72
  };
65
73
  }
66
74
  }
@@ -1,10 +1,4 @@
1
- import {
2
- type PublicKernelRequest,
3
- PublicKernelType,
4
- type Tx,
5
- UnencryptedFunctionL2Logs,
6
- type UnencryptedL2Log,
7
- } from '@aztec/circuit-types';
1
+ import { type PublicKernelRequest, PublicKernelType, type Tx } from '@aztec/circuit-types';
8
2
  import {
9
3
  Fr,
10
4
  type GlobalVariables,
@@ -45,7 +39,11 @@ export class TailPhaseManager extends AbstractPhaseManager {
45
39
  super(db, publicExecutor, publicKernel, globalVariables, historicalHeader, phase);
46
40
  }
47
41
 
48
- async handle(tx: Tx, previousPublicKernelOutput: PublicKernelCircuitPublicInputs, previousPublicKernelProof: Proof) {
42
+ override async handle(
43
+ tx: Tx,
44
+ previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
45
+ previousPublicKernelProof: Proof,
46
+ ) {
49
47
  this.log.verbose(`Processing tx ${tx.getTxHash()}`);
50
48
  const [inputs, finalKernelOutput] = await this.runTailKernelCircuit(
51
49
  previousPublicKernelOutput,
@@ -57,8 +55,6 @@ export class TailPhaseManager extends AbstractPhaseManager {
57
55
  throw err;
58
56
  },
59
57
  );
60
- // Temporary hack. Should sort them in the tail circuit.
61
- this.patchLogsOrdering(tx, previousPublicKernelOutput);
62
58
  // commit the state updates from this transaction
63
59
  await this.publicStateDB.commit();
64
60
 
@@ -75,6 +71,7 @@ export class TailPhaseManager extends AbstractPhaseManager {
75
71
  publicKernelProof: makeEmptyProof(),
76
72
  revertReason: undefined,
77
73
  returnValues: undefined,
74
+ gasUsed: undefined,
78
75
  };
79
76
  }
80
77
 
@@ -163,33 +160,9 @@ export class TailPhaseManager extends AbstractPhaseManager {
163
160
  }
164
161
 
165
162
  private sortLogsHashes<N extends number>(unencryptedLogsHashes: Tuple<SideEffect, N>): Tuple<SideEffect, N> {
163
+ // TODO(6052): logs here may have duplicate counters from nested calls
166
164
  return sortByCounter(
167
165
  unencryptedLogsHashes.map(n => ({ ...n, counter: n.counter.toNumber(), isEmpty: () => n.isEmpty() })),
168
166
  ).map(h => new SideEffect(h.value, new Fr(h.counter))) as Tuple<SideEffect, N>;
169
167
  }
170
-
171
- // As above, this is a hack for unencrypted logs ordering, now they are sorted. Since the public kernel
172
- // cannot keep track of side effects that happen after or before a nested call, we override the gathered logs.
173
- // As a sanity check, we at least verify that the elements are the same, so we are only tweaking their ordering.
174
- // See same fn in pxe_service.ts
175
- // Added as part of resolving #5017
176
- private patchLogsOrdering(tx: Tx, publicInputs: PublicKernelCircuitPublicInputs) {
177
- const unencLogs = tx.unencryptedLogs.unrollLogs();
178
- const sortedUnencLogs = publicInputs.end.unencryptedLogsHashes;
179
-
180
- const finalUnencLogs: UnencryptedL2Log[] = [];
181
- sortedUnencLogs.forEach((sideEffect: SideEffect) => {
182
- if (!sideEffect.isEmpty()) {
183
- const isLog = (log: UnencryptedL2Log) => Fr.fromBuffer(log.hash()).equals(sideEffect.value);
184
- const thisLogIndex = unencLogs.findIndex(isLog);
185
- finalUnencLogs.push(unencLogs[thisLogIndex]);
186
- }
187
- });
188
- const unencryptedLogs = new UnencryptedFunctionL2Logs(finalUnencLogs);
189
-
190
- tx.unencryptedLogs.functionLogs[0] = unencryptedLogs;
191
- for (let i = 1; i < tx.unencryptedLogs.functionLogs.length; i++) {
192
- tx.unencryptedLogs.functionLogs[i] = UnencryptedFunctionL2Logs.empty();
193
- }
194
- }
195
168
  }