@aztec/simulator 0.38.0 → 0.40.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 (143) hide show
  1. package/dest/acvm/oracle/oracle.d.ts +3 -5
  2. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  3. package/dest/acvm/oracle/oracle.js +13 -32
  4. package/dest/acvm/oracle/typed_oracle.d.ts +3 -3
  5. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/typed_oracle.js +7 -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 +5 -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/opcodes/index.d.ts +2 -0
  34. package/dest/avm/opcodes/index.d.ts.map +1 -1
  35. package/dest/avm/opcodes/index.js +3 -1
  36. package/dest/avm/opcodes/misc.d.ts +17 -0
  37. package/dest/avm/opcodes/misc.d.ts.map +1 -0
  38. package/dest/avm/opcodes/misc.js +45 -0
  39. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  40. package/dest/avm/serialization/bytecode_serialization.js +6 -2
  41. package/dest/avm/serialization/instruction_serialization.d.ts +6 -4
  42. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  43. package/dest/avm/serialization/instruction_serialization.js +9 -5
  44. package/dest/client/client_execution_context.d.ts +29 -1
  45. package/dest/client/client_execution_context.d.ts.map +1 -1
  46. package/dest/client/client_execution_context.js +54 -16
  47. package/dest/client/db_oracle.d.ts +1 -8
  48. package/dest/client/db_oracle.d.ts.map +1 -1
  49. package/dest/client/execution_result.d.ts +4 -1
  50. package/dest/client/execution_result.d.ts.map +1 -1
  51. package/dest/client/execution_result.js +16 -3
  52. package/dest/client/private_execution.d.ts.map +1 -1
  53. package/dest/client/private_execution.js +3 -1
  54. package/dest/client/simulator.d.ts +1 -31
  55. package/dest/client/simulator.d.ts.map +1 -1
  56. package/dest/client/simulator.js +3 -42
  57. package/dest/client/view_data_oracle.d.ts +0 -7
  58. package/dest/client/view_data_oracle.d.ts.map +1 -1
  59. package/dest/client/view_data_oracle.js +1 -10
  60. package/dest/common/errors.d.ts +5 -0
  61. package/dest/common/errors.d.ts.map +1 -1
  62. package/dest/common/errors.js +6 -1
  63. package/dest/index.d.ts +1 -0
  64. package/dest/index.d.ts.map +1 -1
  65. package/dest/index.js +2 -1
  66. package/dest/public/abstract_phase_manager.d.ts +8 -4
  67. package/dest/public/abstract_phase_manager.d.ts.map +1 -1
  68. package/dest/public/abstract_phase_manager.js +38 -14
  69. package/dest/public/app_logic_phase_manager.d.ts +1 -0
  70. package/dest/public/app_logic_phase_manager.d.ts.map +1 -1
  71. package/dest/public/app_logic_phase_manager.js +3 -3
  72. package/dest/public/executor.d.ts.map +1 -1
  73. package/dest/public/executor.js +1 -4
  74. package/dest/public/hints_builder.d.ts +3 -3
  75. package/dest/public/hints_builder.d.ts.map +1 -1
  76. package/dest/public/hints_builder.js +3 -3
  77. package/dest/public/public_execution_context.d.ts +1 -0
  78. package/dest/public/public_execution_context.d.ts.map +1 -1
  79. package/dest/public/public_execution_context.js +6 -2
  80. package/dest/public/public_processor.d.ts.map +1 -1
  81. package/dest/public/public_processor.js +5 -3
  82. package/dest/public/setup_phase_manager.d.ts +1 -0
  83. package/dest/public/setup_phase_manager.d.ts.map +1 -1
  84. package/dest/public/setup_phase_manager.js +3 -2
  85. package/dest/public/tail_phase_manager.d.ts +1 -0
  86. package/dest/public/tail_phase_manager.d.ts.map +1 -1
  87. package/dest/public/tail_phase_manager.js +2 -1
  88. package/dest/public/teardown_phase_manager.d.ts +1 -0
  89. package/dest/public/teardown_phase_manager.d.ts.map +1 -1
  90. package/dest/public/teardown_phase_manager.js +3 -2
  91. package/dest/public/transitional_adaptors.d.ts.map +1 -1
  92. package/dest/public/transitional_adaptors.js +1 -1
  93. package/dest/rollup/index.d.ts +2 -0
  94. package/dest/rollup/index.d.ts.map +1 -0
  95. package/dest/rollup/index.js +2 -0
  96. package/dest/rollup/rollup.d.ts +77 -0
  97. package/dest/rollup/rollup.d.ts.map +1 -0
  98. package/dest/rollup/rollup.js +78 -0
  99. package/dest/stats/index.d.ts +2 -0
  100. package/dest/stats/index.d.ts.map +1 -0
  101. package/dest/stats/index.js +2 -0
  102. package/dest/stats/stats.d.ts +4 -0
  103. package/dest/stats/stats.d.ts.map +1 -0
  104. package/dest/stats/stats.js +11 -0
  105. package/package.json +8 -8
  106. package/src/acvm/oracle/oracle.ts +27 -35
  107. package/src/acvm/oracle/typed_oracle.ts +16 -9
  108. package/src/avm/avm_execution_environment.ts +34 -42
  109. package/src/avm/avm_gas.ts +4 -0
  110. package/src/avm/avm_machine_state.ts +14 -25
  111. package/src/avm/avm_message_call_result.ts +3 -14
  112. package/src/avm/avm_simulator.ts +22 -12
  113. package/src/avm/errors.ts +94 -4
  114. package/src/avm/journal/journal.ts +3 -2
  115. package/src/avm/opcodes/conversion.ts +59 -0
  116. package/src/avm/opcodes/environment_getters.ts +13 -66
  117. package/src/avm/opcodes/external_calls.ts +11 -0
  118. package/src/avm/opcodes/index.ts +2 -0
  119. package/src/avm/opcodes/misc.ts +63 -0
  120. package/src/avm/serialization/bytecode_serialization.ts +7 -0
  121. package/src/avm/serialization/instruction_serialization.ts +4 -0
  122. package/src/client/client_execution_context.ts +92 -16
  123. package/src/client/db_oracle.ts +1 -9
  124. package/src/client/execution_result.ts +21 -2
  125. package/src/client/private_execution.ts +2 -0
  126. package/src/client/simulator.ts +2 -80
  127. package/src/client/view_data_oracle.ts +0 -10
  128. package/src/common/errors.ts +5 -0
  129. package/src/index.ts +1 -0
  130. package/src/public/abstract_phase_manager.ts +46 -18
  131. package/src/public/app_logic_phase_manager.ts +2 -1
  132. package/src/public/executor.ts +0 -4
  133. package/src/public/hints_builder.ts +5 -5
  134. package/src/public/public_execution_context.ts +6 -1
  135. package/src/public/public_processor.ts +8 -2
  136. package/src/public/setup_phase_manager.ts +16 -8
  137. package/src/public/tail_phase_manager.ts +6 -1
  138. package/src/public/teardown_phase_manager.ts +16 -8
  139. package/src/public/transitional_adaptors.ts +1 -0
  140. package/src/rollup/index.ts +1 -0
  141. package/src/rollup/rollup.ts +160 -0
  142. package/src/stats/index.ts +1 -0
  143. package/src/stats/stats.ts +20 -0
@@ -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);
@@ -12,7 +12,7 @@ import {
12
12
  } from '@aztec/circuits.js';
13
13
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
14
14
  import { Fr } from '@aztec/foundation/fields';
15
- import { createDebugLogger } from '@aztec/foundation/log';
15
+ import { applyStringFormatting, createDebugLogger } from '@aztec/foundation/log';
16
16
  import { type ContractInstance } from '@aztec/types/contracts';
17
17
 
18
18
  import { TypedOracle, toACVMWitness } from '../acvm/index.js';
@@ -281,4 +281,9 @@ export class PublicExecutionContext extends TypedOracle {
281
281
  }
282
282
  return instance;
283
283
  }
284
+
285
+ public override debugLog(message: string, fields: Fr[]): void {
286
+ const formattedStr = applyStringFormatting(message, fields);
287
+ this.log.verbose(`debug_log ${formattedStr}`);
288
+ }
284
289
  }
@@ -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
  }
@@ -39,7 +39,11 @@ export class TailPhaseManager extends AbstractPhaseManager {
39
39
  super(db, publicExecutor, publicKernel, globalVariables, historicalHeader, phase);
40
40
  }
41
41
 
42
- async handle(tx: Tx, previousPublicKernelOutput: PublicKernelCircuitPublicInputs, previousPublicKernelProof: Proof) {
42
+ override async handle(
43
+ tx: Tx,
44
+ previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
45
+ previousPublicKernelProof: Proof,
46
+ ) {
43
47
  this.log.verbose(`Processing tx ${tx.getTxHash()}`);
44
48
  const [inputs, finalKernelOutput] = await this.runTailKernelCircuit(
45
49
  previousPublicKernelOutput,
@@ -67,6 +71,7 @@ export class TailPhaseManager extends AbstractPhaseManager {
67
71
  publicKernelProof: makeEmptyProof(),
68
72
  revertReason: undefined,
69
73
  returnValues: undefined,
74
+ gasUsed: undefined,
70
75
  };
71
76
  }
72
77
 
@@ -39,14 +39,21 @@ export class TeardownPhaseManager extends AbstractPhaseManager {
39
39
  previousPublicKernelProof: Proof,
40
40
  ) {
41
41
  this.log.verbose(`Processing tx ${tx.getTxHash()}`);
42
- const [kernelInputs, publicKernelOutput, publicKernelProof, newUnencryptedFunctionLogs, revertReason] =
43
- await this.processEnqueuedPublicCalls(tx, previousPublicKernelOutput, previousPublicKernelProof).catch(
44
- // the abstract phase manager throws if simulation gives error in a non-revertible phase
45
- async err => {
46
- await this.publicStateDB.rollbackToCommit();
47
- throw err;
48
- },
49
- );
42
+ const [
43
+ kernelInputs,
44
+ publicKernelOutput,
45
+ publicKernelProof,
46
+ newUnencryptedFunctionLogs,
47
+ revertReason,
48
+ _returnValues,
49
+ gasUsed,
50
+ ] = await this.processEnqueuedPublicCalls(tx, previousPublicKernelOutput, previousPublicKernelProof).catch(
51
+ // the abstract phase manager throws if simulation gives error in a non-revertible phase
52
+ async err => {
53
+ await this.publicStateDB.rollbackToCommit();
54
+ throw err;
55
+ },
56
+ );
50
57
  tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
51
58
  await this.publicStateDB.checkpoint();
52
59
 
@@ -65,6 +72,7 @@ export class TeardownPhaseManager extends AbstractPhaseManager {
65
72
  publicKernelProof,
66
73
  revertReason,
67
74
  returnValues: undefined,
75
+ gasUsed,
68
76
  };
69
77
  }
70
78
 
@@ -81,6 +81,7 @@ export function convertAvmResultsToPxResult(
81
81
  ): PublicExecutionResult {
82
82
  const endPersistableState = endAvmContext.persistableState;
83
83
  const endMachineState = endAvmContext.machineState;
84
+
84
85
  return {
85
86
  ...endPersistableState.transitionalExecutionResult, // includes nestedExecutions
86
87
  execution: fromPx,
@@ -0,0 +1 @@
1
+ export * from './rollup.js';
@@ -0,0 +1,160 @@
1
+ import { type CircuitSimulationStats } from '@aztec/circuit-types/stats';
2
+ import {
3
+ type BaseOrMergeRollupPublicInputs,
4
+ type BaseParityInputs,
5
+ type BaseRollupInputs,
6
+ type MergeRollupInputs,
7
+ type ParityPublicInputs,
8
+ type RootParityInputs,
9
+ type RootRollupInputs,
10
+ type RootRollupPublicInputs,
11
+ } from '@aztec/circuits.js';
12
+ import { createDebugLogger } from '@aztec/foundation/log';
13
+ import { elapsed } from '@aztec/foundation/timer';
14
+ import {
15
+ BaseParityArtifact,
16
+ MergeRollupArtifact,
17
+ RootParityArtifact,
18
+ RootRollupArtifact,
19
+ SimulatedBaseRollupArtifact,
20
+ convertBaseParityInputsToWitnessMap,
21
+ convertBaseParityOutputsFromWitnessMap,
22
+ convertMergeRollupInputsToWitnessMap,
23
+ convertMergeRollupOutputsFromWitnessMap,
24
+ convertRootParityInputsToWitnessMap,
25
+ convertRootParityOutputsFromWitnessMap,
26
+ convertRootRollupInputsToWitnessMap,
27
+ convertRootRollupOutputsFromWitnessMap,
28
+ convertSimulatedBaseRollupInputsToWitnessMap,
29
+ convertSimulatedBaseRollupOutputsFromWitnessMap,
30
+ } from '@aztec/noir-protocol-circuits-types';
31
+ import { type SimulationProvider, WASMSimulator } from '@aztec/simulator';
32
+
33
+ /**
34
+ * Circuit simulator for the rollup circuits.
35
+ */
36
+ export interface RollupSimulator {
37
+ /**
38
+ * Simulates the base parity circuit from its inputs.
39
+ * @param inputs - Inputs to the circuit.
40
+ * @returns The public inputs of the parity circuit.
41
+ */
42
+ baseParityCircuit(inputs: BaseParityInputs): Promise<ParityPublicInputs>;
43
+ /**
44
+ * Simulates the root parity circuit from its inputs.
45
+ * @param inputs - Inputs to the circuit.
46
+ * @returns The public inputs of the parity circuit.
47
+ */
48
+ rootParityCircuit(inputs: RootParityInputs): Promise<ParityPublicInputs>;
49
+ /**
50
+ * Simulates the base rollup circuit from its inputs.
51
+ * @param input - Inputs to the circuit.
52
+ * @returns The public inputs as outputs of the simulation.
53
+ */
54
+ baseRollupCircuit(input: BaseRollupInputs): Promise<BaseOrMergeRollupPublicInputs>;
55
+ /**
56
+ * Simulates the merge rollup circuit from its inputs.
57
+ * @param input - Inputs to the circuit.
58
+ * @returns The public inputs as outputs of the simulation.
59
+ */
60
+ mergeRollupCircuit(input: MergeRollupInputs): Promise<BaseOrMergeRollupPublicInputs>;
61
+ /**
62
+ * Simulates the root rollup circuit from its inputs.
63
+ * @param input - Inputs to the circuit.
64
+ * @returns The public inputs as outputs of the simulation.
65
+ */
66
+ rootRollupCircuit(input: RootRollupInputs): Promise<RootRollupPublicInputs>;
67
+ }
68
+
69
+ /**
70
+ * Implements the rollup circuit simulator.
71
+ */
72
+ export class RealRollupCircuitSimulator implements RollupSimulator {
73
+ private log = createDebugLogger('aztec:rollup-simulator');
74
+
75
+ // Some circuits are so small it is faster to use WASM
76
+ private wasmSimulator: WASMSimulator = new WASMSimulator();
77
+
78
+ constructor(private simulationProvider: SimulationProvider) {}
79
+
80
+ /**
81
+ * Simulates the base parity circuit from its inputs.
82
+ * @param inputs - Inputs to the circuit.
83
+ * @returns The public inputs of the parity circuit.
84
+ */
85
+ public async baseParityCircuit(inputs: BaseParityInputs): Promise<ParityPublicInputs> {
86
+ const witnessMap = convertBaseParityInputsToWitnessMap(inputs);
87
+
88
+ const witness = await this.simulationProvider.simulateCircuit(witnessMap, BaseParityArtifact);
89
+
90
+ const result = convertBaseParityOutputsFromWitnessMap(witness);
91
+
92
+ return Promise.resolve(result);
93
+ }
94
+
95
+ /**
96
+ * Simulates the root parity circuit from its inputs.
97
+ * @param inputs - Inputs to the circuit.
98
+ * @returns The public inputs of the parity circuit.
99
+ */
100
+ public async rootParityCircuit(inputs: RootParityInputs): Promise<ParityPublicInputs> {
101
+ const witnessMap = convertRootParityInputsToWitnessMap(inputs);
102
+
103
+ const witness = await this.simulationProvider.simulateCircuit(witnessMap, RootParityArtifact);
104
+
105
+ const result = convertRootParityOutputsFromWitnessMap(witness);
106
+
107
+ return Promise.resolve(result);
108
+ }
109
+
110
+ /**
111
+ * Simulates the base rollup circuit from its inputs.
112
+ * @param input - Inputs to the circuit.
113
+ * @returns The public inputs as outputs of the simulation.
114
+ */
115
+ public async baseRollupCircuit(input: BaseRollupInputs): Promise<BaseOrMergeRollupPublicInputs> {
116
+ const witnessMap = convertSimulatedBaseRollupInputsToWitnessMap(input);
117
+
118
+ const witness = await this.simulationProvider.simulateCircuit(witnessMap, SimulatedBaseRollupArtifact);
119
+
120
+ const result = convertSimulatedBaseRollupOutputsFromWitnessMap(witness);
121
+
122
+ return Promise.resolve(result);
123
+ }
124
+ /**
125
+ * Simulates the merge rollup circuit from its inputs.
126
+ * @param input - Inputs to the circuit.
127
+ * @returns The public inputs as outputs of the simulation.
128
+ */
129
+ public async mergeRollupCircuit(input: MergeRollupInputs): Promise<BaseOrMergeRollupPublicInputs> {
130
+ const witnessMap = convertMergeRollupInputsToWitnessMap(input);
131
+
132
+ const witness = await this.wasmSimulator.simulateCircuit(witnessMap, MergeRollupArtifact);
133
+
134
+ const result = convertMergeRollupOutputsFromWitnessMap(witness);
135
+
136
+ return result;
137
+ }
138
+
139
+ /**
140
+ * Simulates the root rollup circuit from its inputs.
141
+ * @param input - Inputs to the circuit.
142
+ * @returns The public inputs as outputs of the simulation.
143
+ */
144
+ public async rootRollupCircuit(input: RootRollupInputs): Promise<RootRollupPublicInputs> {
145
+ const witnessMap = convertRootRollupInputsToWitnessMap(input);
146
+
147
+ const [duration, witness] = await elapsed(() => this.wasmSimulator.simulateCircuit(witnessMap, RootRollupArtifact));
148
+
149
+ const result = convertRootRollupOutputsFromWitnessMap(witness);
150
+
151
+ this.log.debug(`Simulated root rollup circuit`, {
152
+ eventName: 'circuit-simulation',
153
+ circuitName: 'root-rollup',
154
+ duration,
155
+ inputSize: input.toBuffer().length,
156
+ outputSize: result.toBuffer().length,
157
+ } satisfies CircuitSimulationStats);
158
+ return result;
159
+ }
160
+ }
@@ -0,0 +1 @@
1
+ export * from './stats.js';
@@ -0,0 +1,20 @@
1
+ import { type CircuitName, type CircuitSimulationStats } from '@aztec/circuit-types/stats';
2
+ import { type Logger } from '@aztec/foundation/log';
3
+
4
+ export function emitCircuitSimulationStats(
5
+ circuitName: CircuitName,
6
+ duration: number,
7
+ inputSize: number,
8
+ outputSize: number,
9
+ logger: Logger,
10
+ ) {
11
+ const stats: CircuitSimulationStats = {
12
+ eventName: 'circuit-simulation',
13
+ circuitName,
14
+ inputSize,
15
+ outputSize,
16
+ duration,
17
+ };
18
+
19
+ logger.debug('Circuit simulation stats', stats);
20
+ }