@aztec/simulator 0.32.1 → 0.34.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 (160) hide show
  1. package/README.md +5 -3
  2. package/dest/acvm/acvm.js +2 -2
  3. package/dest/acvm/oracle/index.d.ts +0 -1
  4. package/dest/acvm/oracle/index.d.ts.map +1 -1
  5. package/dest/acvm/oracle/index.js +1 -2
  6. package/dest/acvm/oracle/oracle.d.ts +1 -1
  7. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  8. package/dest/acvm/oracle/oracle.js +4 -5
  9. package/dest/avm/avm_context.d.ts +4 -14
  10. package/dest/avm/avm_context.d.ts.map +1 -1
  11. package/dest/avm/avm_context.js +10 -22
  12. package/dest/avm/avm_execution_environment.d.ts +4 -3
  13. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  14. package/dest/avm/avm_execution_environment.js +8 -7
  15. package/dest/avm/avm_gas.d.ts +71 -0
  16. package/dest/avm/avm_gas.d.ts.map +1 -0
  17. package/dest/avm/avm_gas.js +161 -0
  18. package/dest/avm/avm_machine_state.d.ts +4 -2
  19. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  20. package/dest/avm/avm_machine_state.js +8 -2
  21. package/dest/avm/avm_memory_types.d.ts +53 -1
  22. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  23. package/dest/avm/avm_memory_types.js +99 -6
  24. package/dest/avm/avm_simulator.d.ts.map +1 -1
  25. package/dest/avm/avm_simulator.js +15 -13
  26. package/dest/avm/fixtures/index.d.ts.map +1 -1
  27. package/dest/avm/fixtures/index.js +3 -3
  28. package/dest/avm/journal/journal.d.ts +14 -13
  29. package/dest/avm/journal/journal.d.ts.map +1 -1
  30. package/dest/avm/journal/journal.js +5 -5
  31. package/dest/avm/journal/trace.d.ts +8 -19
  32. package/dest/avm/journal/trace.d.ts.map +1 -1
  33. package/dest/avm/journal/trace.js +48 -116
  34. package/dest/avm/journal/trace_types.d.ts +23 -4
  35. package/dest/avm/journal/trace_types.d.ts.map +1 -1
  36. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  37. package/dest/avm/opcodes/accrued_substate.js +45 -17
  38. package/dest/avm/opcodes/addressing_mode.d.ts +5 -3
  39. package/dest/avm/opcodes/addressing_mode.d.ts.map +1 -1
  40. package/dest/avm/opcodes/addressing_mode.js +5 -1
  41. package/dest/avm/opcodes/arithmetic.d.ts +7 -3
  42. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  43. package/dest/avm/opcodes/arithmetic.js +27 -16
  44. package/dest/avm/opcodes/bitwise.d.ts +21 -20
  45. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  46. package/dest/avm/opcodes/bitwise.js +43 -65
  47. package/dest/avm/opcodes/comparators.d.ts +12 -9
  48. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  49. package/dest/avm/opcodes/comparators.js +22 -32
  50. package/dest/avm/opcodes/context_getters.d.ts +20 -0
  51. package/dest/avm/opcodes/context_getters.d.ts.map +1 -0
  52. package/dest/avm/opcodes/context_getters.js +26 -0
  53. package/dest/avm/opcodes/contract.d.ts +14 -0
  54. package/dest/avm/opcodes/contract.d.ts.map +1 -0
  55. package/dest/avm/opcodes/contract.js +49 -0
  56. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  57. package/dest/avm/opcodes/control_flow.js +12 -2
  58. package/dest/avm/opcodes/environment_getters.d.ts +30 -33
  59. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  60. package/dest/avm/opcodes/environment_getters.js +34 -43
  61. package/dest/avm/opcodes/external_calls.d.ts +13 -19
  62. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  63. package/dest/avm/opcodes/external_calls.js +69 -72
  64. package/dest/avm/opcodes/hashing.d.ts +2 -1
  65. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  66. package/dest/avm/opcodes/hashing.js +37 -18
  67. package/dest/avm/opcodes/index.d.ts +1 -0
  68. package/dest/avm/opcodes/index.d.ts.map +1 -1
  69. package/dest/avm/opcodes/index.js +2 -1
  70. package/dest/avm/opcodes/instruction.d.ts +10 -15
  71. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  72. package/dest/avm/opcodes/instruction.js +12 -22
  73. package/dest/avm/opcodes/instruction_impl.d.ts +14 -0
  74. package/dest/avm/opcodes/instruction_impl.d.ts.map +1 -1
  75. package/dest/avm/opcodes/instruction_impl.js +37 -16
  76. package/dest/avm/opcodes/memory.d.ts +4 -3
  77. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  78. package/dest/avm/opcodes/memory.js +38 -19
  79. package/dest/avm/opcodes/storage.d.ts +5 -0
  80. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  81. package/dest/avm/opcodes/storage.js +21 -7
  82. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  83. package/dest/avm/serialization/bytecode_serialization.js +7 -5
  84. package/dest/avm/serialization/instruction_serialization.d.ts +12 -11
  85. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  86. package/dest/avm/serialization/instruction_serialization.js +13 -12
  87. package/dest/client/client_execution_context.d.ts +2 -2
  88. package/dest/client/client_execution_context.d.ts.map +1 -1
  89. package/dest/client/client_execution_context.js +6 -6
  90. package/dest/client/private_execution.d.ts +1 -1
  91. package/dest/client/private_execution.d.ts.map +1 -1
  92. package/dest/client/private_execution.js +8 -4
  93. package/dest/client/unconstrained_execution.d.ts +1 -1
  94. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  95. package/dest/client/unconstrained_execution.js +2 -2
  96. package/dest/client/view_data_oracle.d.ts +2 -2
  97. package/dest/client/view_data_oracle.d.ts.map +1 -1
  98. package/dest/client/view_data_oracle.js +2 -2
  99. package/dest/public/executor.d.ts +2 -8
  100. package/dest/public/executor.d.ts.map +1 -1
  101. package/dest/public/executor.js +101 -69
  102. package/dest/public/index.d.ts +1 -1
  103. package/dest/public/index.d.ts.map +1 -1
  104. package/dest/public/public_execution_context.d.ts +6 -6
  105. package/dest/public/public_execution_context.d.ts.map +1 -1
  106. package/dest/public/public_execution_context.js +8 -12
  107. package/dest/public/transitional_adaptors.d.ts +32 -0
  108. package/dest/public/transitional_adaptors.d.ts.map +1 -0
  109. package/dest/public/transitional_adaptors.js +161 -0
  110. package/package.json +15 -9
  111. package/src/acvm/acvm.ts +1 -1
  112. package/src/acvm/oracle/index.ts +0 -1
  113. package/src/acvm/oracle/oracle.ts +3 -4
  114. package/src/avm/avm_context.ts +11 -33
  115. package/src/avm/avm_execution_environment.ts +9 -17
  116. package/src/avm/{avm_gas_cost.ts → avm_gas.ts} +75 -21
  117. package/src/avm/avm_machine_state.ts +9 -2
  118. package/src/avm/avm_memory_types.ts +134 -6
  119. package/src/avm/avm_simulator.ts +14 -12
  120. package/src/avm/fixtures/index.ts +2 -1
  121. package/src/avm/journal/journal.ts +24 -17
  122. package/src/avm/journal/trace.ts +59 -121
  123. package/src/avm/journal/trace_types.ts +39 -39
  124. package/src/avm/opcodes/accrued_substate.ts +58 -23
  125. package/src/avm/opcodes/addressing_mode.ts +8 -3
  126. package/src/avm/opcodes/arithmetic.ts +32 -22
  127. package/src/avm/opcodes/bitwise.ts +49 -83
  128. package/src/avm/opcodes/comparators.ts +28 -43
  129. package/src/avm/opcodes/context_getters.ts +32 -0
  130. package/src/avm/opcodes/contract.ts +58 -0
  131. package/src/avm/opcodes/control_flow.ts +23 -5
  132. package/src/avm/opcodes/environment_getters.ts +35 -44
  133. package/src/avm/opcodes/external_calls.ts +90 -89
  134. package/src/avm/opcodes/hashing.ts +45 -22
  135. package/src/avm/opcodes/index.ts +1 -0
  136. package/src/avm/opcodes/instruction.ts +14 -26
  137. package/src/avm/opcodes/instruction_impl.ts +45 -15
  138. package/src/avm/opcodes/memory.ts +48 -28
  139. package/src/avm/opcodes/storage.ts +26 -12
  140. package/src/avm/serialization/bytecode_serialization.ts +6 -3
  141. package/src/avm/serialization/instruction_serialization.ts +1 -0
  142. package/src/client/client_execution_context.ts +5 -5
  143. package/src/client/private_execution.ts +10 -4
  144. package/src/client/unconstrained_execution.ts +1 -1
  145. package/src/client/view_data_oracle.ts +1 -1
  146. package/src/public/executor.ts +123 -75
  147. package/src/public/index.ts +2 -2
  148. package/src/public/public_execution_context.ts +14 -19
  149. package/src/public/transitional_adaptors.ts +240 -0
  150. package/dest/acvm/oracle/debug.d.ts +0 -19
  151. package/dest/acvm/oracle/debug.d.ts.map +0 -1
  152. package/dest/acvm/oracle/debug.js +0 -95
  153. package/dest/avm/avm_gas_cost.d.ts +0 -322
  154. package/dest/avm/avm_gas_cost.d.ts.map +0 -1
  155. package/dest/avm/avm_gas_cost.js +0 -118
  156. package/dest/avm/temporary_executor_migration.d.ts +0 -25
  157. package/dest/avm/temporary_executor_migration.d.ts.map +0 -1
  158. package/dest/avm/temporary_executor_migration.js +0 -83
  159. package/src/acvm/oracle/debug.ts +0 -109
  160. package/src/avm/temporary_executor_migration.ts +0 -122
@@ -257,7 +257,7 @@ export class ViewDataOracle extends TypedOracle {
257
257
  const storageSlot = new Fr(startStorageSlot.value + i);
258
258
  const value = await this.aztecNode.getPublicStorageAt(this.contractAddress, storageSlot);
259
259
 
260
- this.log(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`);
260
+ this.log.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`);
261
261
  values.push(value);
262
262
  }
263
263
  return values;
@@ -12,10 +12,6 @@ import { AvmMachineState } from '../avm/avm_machine_state.js';
12
12
  import { AvmSimulator } from '../avm/avm_simulator.js';
13
13
  import { HostStorage } from '../avm/journal/host_storage.js';
14
14
  import { AvmPersistableStateManager } from '../avm/journal/index.js';
15
- import {
16
- temporaryConvertAvmResults,
17
- temporaryCreateAvmExecutionEnvironment,
18
- } from '../avm/temporary_executor_migration.js';
19
15
  import { AcirSimulator } from '../client/simulator.js';
20
16
  import { ExecutionError, createSimulationError } from '../common/errors.js';
21
17
  import { SideEffectCounter } from '../common/index.js';
@@ -23,35 +19,92 @@ import { PackedArgsCache } from '../common/packed_args_cache.js';
23
19
  import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db.js';
24
20
  import { type PublicExecution, type PublicExecutionResult, checkValidStaticCall } from './execution.js';
25
21
  import { PublicExecutionContext } from './public_execution_context.js';
22
+ import { convertAvmResults, createAvmExecutionEnvironment, isAvmBytecode } from './transitional_adaptors.js';
26
23
 
27
24
  /**
28
25
  * Execute a public function and return the execution result.
29
26
  */
30
27
  export async function executePublicFunction(
28
+ context: PublicExecutionContext,
29
+ nested: boolean,
30
+ ): Promise<PublicExecutionResult> {
31
+ const bytecode = await context.contractsDb.getBytecode(
32
+ context.execution.contractAddress,
33
+ context.execution.functionData.selector,
34
+ );
35
+ if (!bytecode) {
36
+ throw new Error(
37
+ `Bytecode not found for ${context.execution.contractAddress}:${context.execution.functionData.selector}`,
38
+ );
39
+ }
40
+
41
+ if (isAvmBytecode(bytecode)) {
42
+ return await executePublicFunctionAvm(context);
43
+ } else {
44
+ return await executePublicFunctionAcvm(context, bytecode, nested);
45
+ }
46
+ }
47
+
48
+ async function executePublicFunctionAvm(executionContext: PublicExecutionContext): Promise<PublicExecutionResult> {
49
+ const address = executionContext.execution.contractAddress;
50
+ const selector = executionContext.execution.functionData.selector;
51
+ const log = createDebugLogger('aztec:simulator:public_execution');
52
+ log.verbose(`[AVM] Executing public external function ${address.toString()}:${selector}.`);
53
+
54
+ // Temporary code to construct the AVM context
55
+ // These data structures will permeate across the simulator when the public executor is phased out
56
+ const hostStorage = new HostStorage(
57
+ executionContext.stateDb,
58
+ executionContext.contractsDb,
59
+ executionContext.commitmentsDb,
60
+ );
61
+ const worldStateJournal = new AvmPersistableStateManager(hostStorage);
62
+
63
+ const executionEnv = createAvmExecutionEnvironment(
64
+ executionContext.execution,
65
+ executionContext.header,
66
+ executionContext.globalVariables,
67
+ );
68
+
69
+ // TODO(@spalladino) Load initial gas from the public execution request
70
+ const machineState = new AvmMachineState(1e7, 1e7, 1e7);
71
+
72
+ const context = new AvmContext(worldStateJournal, executionEnv, machineState);
73
+ const simulator = new AvmSimulator(context);
74
+
75
+ const result = await simulator.execute();
76
+ const newWorldState = context.persistableState.flush();
77
+
78
+ log.verbose(`[AVM] ${address.toString()}:${selector} returned, reverted: ${result.reverted}.`);
79
+
80
+ // TODO(@spalladino) Read gas left from machineState and return it
81
+ return await convertAvmResults(executionContext, newWorldState, result);
82
+ }
83
+
84
+ async function executePublicFunctionAcvm(
31
85
  context: PublicExecutionContext,
32
86
  acir: Buffer,
33
87
  nested: boolean,
34
- log = createDebugLogger('aztec:simulator:public_execution'),
35
88
  ): Promise<PublicExecutionResult> {
36
89
  const execution = context.execution;
37
90
  const { contractAddress, functionData } = execution;
38
91
  const selector = functionData.selector;
39
- log(`Executing public external function ${contractAddress.toString()}:${selector}`);
92
+ const log = createDebugLogger('aztec:simulator:public_execution');
93
+ log.verbose(`[ACVM] Executing public external function ${contractAddress.toString()}:${selector}.`);
40
94
 
41
95
  const initialWitness = context.getInitialWitness();
42
96
  const acvmCallback = new Oracle(context);
43
- const { partialWitness, reverted, revertReason } = await acvm(
44
- await AcirSimulator.getSolver(),
45
- acir,
46
- initialWitness,
47
- acvmCallback,
48
- )
49
- .then(result => ({
50
- partialWitness: result.partialWitness,
51
- reverted: false,
52
- revertReason: undefined,
53
- }))
54
- .catch((err: Error) => {
97
+
98
+ const { partialWitness, reverted, revertReason } = await (async () => {
99
+ try {
100
+ const result = await acvm(await AcirSimulator.getSolver(), acir, initialWitness, acvmCallback);
101
+ return {
102
+ partialWitness: result.partialWitness,
103
+ reverted: false,
104
+ revertReason: undefined,
105
+ };
106
+ } catch (err_) {
107
+ const err = err_ as Error;
55
108
  const ee = new ExecutionError(
56
109
  err.message,
57
110
  {
@@ -72,7 +125,9 @@ export async function executePublicFunction(
72
125
  revertReason: createSimulationError(ee),
73
126
  };
74
127
  }
75
- });
128
+ }
129
+ })();
130
+
76
131
  if (reverted) {
77
132
  if (!revertReason) {
78
133
  throw new Error('Reverted but no revert reason');
@@ -122,12 +177,12 @@ export async function executePublicFunction(
122
177
 
123
178
  const { contractStorageReads, contractStorageUpdateRequests } = context.getStorageActionData();
124
179
 
125
- log(
180
+ log.debug(
126
181
  `Contract storage reads: ${contractStorageReads
127
182
  .map(r => r.toFriendlyJSON() + ` - sec: ${r.sideEffectCounter}`)
128
183
  .join(', ')}`,
129
184
  );
130
- log(
185
+ log.debug(
131
186
  `Contract storage update requests: ${contractStorageUpdateRequests
132
187
  .map(r => r.toFriendlyJSON() + ` - sec: ${r.sideEffectCounter}`)
133
188
  .join(', ')}`,
@@ -166,6 +221,7 @@ export class PublicExecutor {
166
221
  private readonly header: Header,
167
222
  ) {}
168
223
 
224
+ private readonly log = createDebugLogger('aztec:simulator:public_executor');
169
225
  /**
170
226
  * Executes a public execution request.
171
227
  * @param execution - The execution to run.
@@ -177,12 +233,6 @@ export class PublicExecutor {
177
233
  globalVariables: GlobalVariables,
178
234
  sideEffectCounter: number = 0,
179
235
  ): Promise<PublicExecutionResult> {
180
- const selector = execution.functionData.selector;
181
- const acir = await this.contractsDb.getBytecode(execution.contractAddress, selector);
182
- if (!acir) {
183
- throw new Error(`Bytecode not found for ${execution.contractAddress}:${selector}`);
184
- }
185
-
186
236
  // Functions can request to pack arguments before calling other functions.
187
237
  // We use this cache to hold the packed arguments.
188
238
  const packedArgs = PackedArgsCache.create([]);
@@ -198,7 +248,7 @@ export class PublicExecutor {
198
248
  this.commitmentsDb,
199
249
  );
200
250
 
201
- const executionResult = await executePublicFunction(context, acir, false /** nested */);
251
+ const executionResult = await executePublicFunction(context, /*nested=*/ false);
202
252
 
203
253
  if (executionResult.execution.callContext.isStaticCall) {
204
254
  checkValidStaticCall(
@@ -213,34 +263,6 @@ export class PublicExecutor {
213
263
  return executionResult;
214
264
  }
215
265
 
216
- /**
217
- * Executes a public execution request in the avm.
218
- * @param execution - The execution to run.
219
- * @param globalVariables - The global variables to use.
220
- * @returns The result of the run plus all nested runs.
221
- */
222
- public async simulateAvm(
223
- execution: PublicExecution,
224
- globalVariables: GlobalVariables,
225
- _sideEffectCounter = 0,
226
- ): Promise<PublicExecutionResult> {
227
- // Temporary code to construct the AVM context
228
- // These data structures will permeate across the simulator when the public executor is phased out
229
- const hostStorage = new HostStorage(this.stateDb, this.contractsDb, this.commitmentsDb);
230
- const worldStateJournal = new AvmPersistableStateManager(hostStorage);
231
- const executionEnv = temporaryCreateAvmExecutionEnvironment(execution, globalVariables);
232
- // TODO(@spalladino) Load initial gas from the public execution request
233
- const machineState = new AvmMachineState(100_000, 100_000, 100_000);
234
-
235
- const context = new AvmContext(worldStateJournal, executionEnv, machineState);
236
- const simulator = new AvmSimulator(context);
237
-
238
- const result = await simulator.execute();
239
- const newWorldState = context.persistableState.flush();
240
- // TODO(@spalladino) Read gas left from machineState and return it
241
- return temporaryConvertAvmResults(execution, newWorldState, result);
242
- }
243
-
244
266
  /**
245
267
  * These functions are currently housed in the temporary executor as it relies on access to
246
268
  * oracles like the contractsDB and this is the least intrusive way to achieve this.
@@ -260,6 +282,7 @@ export class PublicExecutor {
260
282
  const artifactsPath = path.resolve('target');
261
283
 
262
284
  // Create the directory if it does not exist
285
+ await fs.rm(artifactsPath, { recursive: true, force: true });
263
286
  await fs.mkdir(artifactsPath, { recursive: true });
264
287
 
265
288
  const calldataPath = path.join(artifactsPath, 'calldata.bin');
@@ -269,34 +292,54 @@ export class PublicExecutor {
269
292
  const { args, functionData, contractAddress } = avmExecution;
270
293
  const bytecode = await this.contractsDb.getBytecode(contractAddress, functionData.selector);
271
294
  // Write call data and bytecode to files.
272
- await Promise.all([
273
- fs.writeFile(
274
- calldataPath,
275
- args.map(c => c.toBuffer()),
276
- ),
277
- fs.writeFile(bytecodePath, bytecode!),
278
- ]);
279
-
280
- const bbBinary = spawn(path.join(bbPath, 'build', 'bin', 'bb'), [
281
- 'avm_prove',
282
- '-b',
283
- bytecodePath,
284
- '-d',
295
+ await fs.writeFile(
285
296
  calldataPath,
286
- '-o',
287
- proofPath,
288
- ]);
297
+ args.map(c => c.toBuffer()),
298
+ );
299
+ await fs.writeFile(bytecodePath, bytecode!);
300
+
301
+ const bbExec = path.join(bbPath, 'build', 'bin', 'bb');
302
+ const bbArgs = ['avm_prove', '-b', bytecodePath, '-d', calldataPath, '-o', proofPath];
303
+ this.log.debug(`calling '${bbExec} ${bbArgs.join(' ')}'`);
304
+ const bbBinary = spawn(bbExec, bbArgs);
305
+
289
306
  // The binary writes the proof and the verification key to the write path.
290
307
  return new Promise((resolve, reject) => {
308
+ let stdout: string = '';
309
+ let stderr: string = '';
310
+
291
311
  bbBinary.on('close', () => {
292
- resolve(Promise.all([fs.readFile(proofPath), fs.readFile(path.join(artifactsPath, 'vk'))]));
312
+ this.log.verbose(`Proof generation complete. Reading proof and vk from ${proofPath}.`);
313
+ return resolve(Promise.all([fs.readFile(proofPath), fs.readFile(path.join(artifactsPath, 'vk'))]));
314
+ });
315
+
316
+ // Catch stdout.
317
+ bbBinary.stdout.on('data', (data: Buffer) => {
318
+ stdout += data.toString();
319
+ });
320
+ bbBinary.stdout.on('end', () => {
321
+ if (stdout.length > 0) {
322
+ this.log.debug(`stdout: ${stdout}`);
323
+ }
293
324
  });
325
+
326
+ // Catch stderr.
327
+ bbBinary.stderr.on('data', (data: Buffer) => {
328
+ stderr += data.toString();
329
+ });
330
+ bbBinary.stderr.on('end', () => {
331
+ if (stderr.length > 0) {
332
+ this.log.warn(`stderr: ${stderr}`);
333
+ }
334
+ });
335
+
294
336
  // Catch and propagate errors from spawning
295
337
  bbBinary.on('error', err => {
296
338
  reject(err);
297
339
  });
298
340
  });
299
341
  }
342
+
300
343
  /**
301
344
  * Verifies an AVM proof. This function is currently only used for testing purposes, as verification
302
345
  * is not fully complete in the AVM yet.
@@ -313,9 +356,14 @@ export class PublicExecutor {
313
356
  const proofPath = path.join(artifactsPath, 'proof');
314
357
 
315
358
  // Write the verification key and the proof to files.
316
- await Promise.all([fs.writeFile(vkPath, vk), fs.writeFile(proofPath, proof)]);
359
+ await fs.writeFile(vkPath, vk);
360
+ await fs.writeFile(proofPath, proof);
361
+
362
+ const bbExec = path.join(bbPath, 'build', 'bin', 'bb');
363
+ const bbArgs = ['avm_verify', '-p', proofPath];
364
+ this.log.debug(`calling '${bbPath} ${bbArgs.join(' ')}'`);
365
+ const bbBinary = spawn(bbExec, bbArgs);
317
366
 
318
- const bbBinary = spawn(path.join(bbPath, 'build', 'bin', 'bb'), ['avm_verify', '-p', proofPath]);
319
367
  // The binary prints to stdout 1 if the proof is valid and 0 if it is not.
320
368
  return new Promise((resolve, reject) => {
321
369
  let result = Buffer.alloc(0);
@@ -1,7 +1,7 @@
1
1
  export * from './db.js';
2
2
  export {
3
- PublicExecution,
4
- PublicExecutionResult,
3
+ type PublicExecution,
4
+ type PublicExecutionResult,
5
5
  isPublicExecutionResult,
6
6
  collectPublicDataReads,
7
7
  collectPublicDataUpdateRequests,
@@ -36,13 +36,13 @@ export class PublicExecutionContext extends TypedOracle {
36
36
  * Data for this execution.
37
37
  */
38
38
  public readonly execution: PublicExecution,
39
- private readonly header: Header,
40
- private readonly globalVariables: GlobalVariables,
39
+ public readonly header: Header,
40
+ public readonly globalVariables: GlobalVariables,
41
41
  private readonly packedArgsCache: PackedArgsCache,
42
42
  private readonly sideEffectCounter: SideEffectCounter,
43
- private readonly stateDb: PublicStateDB,
44
- private readonly contractsDb: PublicContractsDB,
45
- private readonly commitmentsDb: CommitmentsDB,
43
+ public readonly stateDb: PublicStateDB,
44
+ public readonly contractsDb: PublicContractsDB,
45
+ public readonly commitmentsDb: CommitmentsDB,
46
46
  private log = createDebugLogger('aztec:simulator:public_execution_context'),
47
47
  ) {
48
48
  super();
@@ -120,7 +120,7 @@ export class PublicExecutionContext extends TypedOracle {
120
120
  public emitUnencryptedLog(log: UnencryptedL2Log) {
121
121
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/885)
122
122
  this.unencryptedLogs.push(log);
123
- this.log(`Emitted unencrypted log: "${log.toHumanReadable()}"`);
123
+ this.log.verbose(`Emitted unencrypted log: "${log.toHumanReadable()}"`);
124
124
  }
125
125
 
126
126
  /**
@@ -144,7 +144,7 @@ export class PublicExecutionContext extends TypedOracle {
144
144
  const storageSlot = new Fr(startStorageSlot.value + BigInt(i));
145
145
  const sideEffectCounter = this.sideEffectCounter.count();
146
146
  const value = await this.storageActions.read(storageSlot, sideEffectCounter);
147
- this.log(`Oracle storage read: slot=${storageSlot.toString()} value=${value.toString()}`);
147
+ this.log.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value.toString()}`);
148
148
  values.push(value);
149
149
  }
150
150
  return values;
@@ -163,7 +163,7 @@ export class PublicExecutionContext extends TypedOracle {
163
163
  const sideEffectCounter = this.sideEffectCounter.count();
164
164
  this.storageActions.write(storageSlot, newValue, sideEffectCounter);
165
165
  await this.stateDb.storageWrite(this.execution.callContext.storageContractAddress, storageSlot, newValue);
166
- this.log(`Oracle storage write: slot=${storageSlot.toString()} value=${newValue.toString()}`);
166
+ this.log.debug(`Oracle storage write: slot=${storageSlot.toString()} value=${newValue.toString()}`);
167
167
  newValues.push(newValue);
168
168
  }
169
169
  return newValues;
@@ -187,17 +187,12 @@ export class PublicExecutionContext extends TypedOracle {
187
187
  isStaticCall = isStaticCall || this.execution.callContext.isStaticCall;
188
188
 
189
189
  const args = this.packedArgsCache.unpack(argsHash);
190
- this.log(`Public function call: addr=${targetContractAddress} selector=${functionSelector} args=${args.join(',')}`);
190
+ this.log.verbose(
191
+ `Public function call: addr=${targetContractAddress} selector=${functionSelector} args=${args.join(',')}`,
192
+ );
191
193
 
192
194
  const portalAddress = (await this.contractsDb.getPortalContractAddress(targetContractAddress)) ?? EthAddress.ZERO;
193
-
194
- const acir = await this.contractsDb.getBytecode(targetContractAddress, functionSelector);
195
- if (!acir) {
196
- throw new Error(`Bytecode not found for ${targetContractAddress}:${functionSelector}`);
197
- }
198
-
199
- const functionData = new FunctionData(functionSelector, false);
200
-
195
+ const functionData = new FunctionData(functionSelector, /*isPrivate=*/ false);
201
196
  const callContext = CallContext.from({
202
197
  msgSender: isDelegateCall ? this.execution.callContext.msgSender : this.execution.contractAddress,
203
198
  storageContractAddress: isDelegateCall ? this.execution.contractAddress : targetContractAddress,
@@ -227,7 +222,7 @@ export class PublicExecutionContext extends TypedOracle {
227
222
  this.log,
228
223
  );
229
224
 
230
- const childExecutionResult = await executePublicFunction(context, acir, true /** nested */);
225
+ const childExecutionResult = await executePublicFunction(context, /*nested=*/ true);
231
226
 
232
227
  if (isStaticCall) {
233
228
  checkValidStaticCall(
@@ -240,7 +235,7 @@ export class PublicExecutionContext extends TypedOracle {
240
235
  }
241
236
 
242
237
  this.nestedExecutions.push(childExecutionResult);
243
- this.log(`Returning from nested call: ret=${childExecutionResult.returnValues.join(', ')}`);
238
+ this.log.debug(`Returning from nested call: ret=${childExecutionResult.returnValues.join(', ')}`);
244
239
 
245
240
  return childExecutionResult.returnValues;
246
241
  }
@@ -0,0 +1,240 @@
1
+ // All code in this file needs to die once the public executor is phased out in favor of the AVM.
2
+ import { UnencryptedFunctionL2Logs, UnencryptedL2Log } from '@aztec/circuit-types';
3
+ import {
4
+ CallContext,
5
+ ContractStorageRead,
6
+ ContractStorageUpdateRequest,
7
+ FunctionData,
8
+ type GlobalVariables,
9
+ type Header,
10
+ L2ToL1Message,
11
+ ReadRequest,
12
+ SideEffect,
13
+ SideEffectLinkedToNoteHash,
14
+ } from '@aztec/circuits.js';
15
+ import { Fr } from '@aztec/foundation/fields';
16
+
17
+ import { type AvmContext } from '../avm/avm_context.js';
18
+ import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
19
+ import { AvmContractCallResults } from '../avm/avm_message_call_result.js';
20
+ import { type JournalData } from '../avm/journal/journal.js';
21
+ import { Mov } from '../avm/opcodes/memory.js';
22
+ import { createSimulationError } from '../common/errors.js';
23
+ import { PackedArgsCache, SideEffectCounter } from '../index.js';
24
+ import { type PublicExecution, type PublicExecutionResult } from './execution.js';
25
+ import { PublicExecutionContext } from './public_execution_context.js';
26
+
27
+ /**
28
+ * Convert a PublicExecution(Environment) object to an AvmExecutionEnvironment
29
+ *
30
+ * @param current
31
+ * @param globalVariables
32
+ * @returns
33
+ */
34
+ export function createAvmExecutionEnvironment(
35
+ current: PublicExecution,
36
+ header: Header,
37
+ globalVariables: GlobalVariables,
38
+ ): AvmExecutionEnvironment {
39
+ return new AvmExecutionEnvironment(
40
+ current.contractAddress,
41
+ current.callContext.storageContractAddress,
42
+ current.callContext.msgSender, // TODO: origin is not available
43
+ current.callContext.msgSender,
44
+ current.callContext.portalContractAddress,
45
+ /*feePerL1Gas=*/ Fr.zero(),
46
+ /*feePerL2Gas=*/ Fr.zero(),
47
+ /*feePerDaGas=*/ Fr.zero(),
48
+ /*contractCallDepth=*/ Fr.zero(),
49
+ header,
50
+ globalVariables,
51
+ current.callContext.isStaticCall,
52
+ current.callContext.isDelegateCall,
53
+ current.args,
54
+ current.functionData.selector,
55
+ );
56
+ }
57
+
58
+ export function createPublicExecutionContext(avmContext: AvmContext, calldata: Fr[]): PublicExecutionContext {
59
+ const sideEffectCounter = avmContext.persistableState.trace.accessCounter;
60
+ const callContext = CallContext.from({
61
+ msgSender: avmContext.environment.sender,
62
+ storageContractAddress: avmContext.environment.storageAddress,
63
+ portalContractAddress: avmContext.environment.portal,
64
+ functionSelector: avmContext.environment.temporaryFunctionSelector,
65
+ isDelegateCall: avmContext.environment.isDelegateCall,
66
+ isStaticCall: avmContext.environment.isStaticCall,
67
+ sideEffectCounter: sideEffectCounter,
68
+ });
69
+ const functionData = new FunctionData(avmContext.environment.temporaryFunctionSelector, /*isPrivate=*/ false);
70
+ const execution: PublicExecution = {
71
+ contractAddress: avmContext.environment.address,
72
+ callContext,
73
+ args: calldata,
74
+ functionData,
75
+ };
76
+ const packedArgs = PackedArgsCache.create([]);
77
+
78
+ const context = new PublicExecutionContext(
79
+ execution,
80
+ avmContext.environment.header,
81
+ avmContext.environment.globals,
82
+ packedArgs,
83
+ new SideEffectCounter(sideEffectCounter),
84
+ avmContext.persistableState.hostStorage.publicStateDb,
85
+ avmContext.persistableState.hostStorage.contractsDb,
86
+ avmContext.persistableState.hostStorage.commitmentsDb,
87
+ );
88
+
89
+ return context;
90
+ }
91
+
92
+ /**
93
+ * Convert the result of an AVM contract call to a PublicExecutionResult for the public kernel
94
+ *
95
+ * @param execution
96
+ * @param newWorldState
97
+ * @param result
98
+ * @returns
99
+ */
100
+ export async function convertAvmResults(
101
+ executionContext: PublicExecutionContext,
102
+ newWorldState: JournalData,
103
+ result: AvmContractCallResults,
104
+ ): Promise<PublicExecutionResult> {
105
+ const execution = executionContext.execution;
106
+
107
+ const contractStorageReads: ContractStorageRead[] = newWorldState.storageReads.map(
108
+ read => new ContractStorageRead(read.slot, read.value, read.counter.toNumber()),
109
+ );
110
+ const contractStorageUpdateRequests: ContractStorageUpdateRequest[] = newWorldState.storageWrites.map(
111
+ write => new ContractStorageUpdateRequest(write.slot, write.value, write.counter.toNumber()),
112
+ );
113
+ // We need to write the storage updates to the DB, because that's what the ACVM expects.
114
+ // Assumes the updates are in the right order.
115
+ for (const write of newWorldState.storageWrites) {
116
+ await executionContext.stateDb.storageWrite(write.storageAddress, write.slot, write.value);
117
+ }
118
+
119
+ const newNoteHashes = newWorldState.newNoteHashes.map(
120
+ noteHash => new SideEffect(noteHash.noteHash, noteHash.counter),
121
+ );
122
+ const nullifierReadRequests: ReadRequest[] = newWorldState.nullifierChecks
123
+ .filter(nullifierCheck => nullifierCheck.exists)
124
+ .map(nullifierCheck => new ReadRequest(nullifierCheck.nullifier, nullifierCheck.counter.toNumber()));
125
+ const nullifierNonExistentReadRequests: ReadRequest[] = newWorldState.nullifierChecks
126
+ .filter(nullifierCheck => !nullifierCheck.exists)
127
+ .map(nullifierCheck => new ReadRequest(nullifierCheck.nullifier, nullifierCheck.counter.toNumber()));
128
+ const newNullifiers: SideEffectLinkedToNoteHash[] = newWorldState.newNullifiers.map(
129
+ tracedNullifier =>
130
+ new SideEffectLinkedToNoteHash(
131
+ /*value=*/ tracedNullifier.nullifier,
132
+ /*noteHash=*/ Fr.ZERO, // NEEDED?
133
+ tracedNullifier.counter,
134
+ ),
135
+ );
136
+ const unencryptedLogs: UnencryptedFunctionL2Logs = new UnencryptedFunctionL2Logs(
137
+ newWorldState.newLogs.map(log => new UnencryptedL2Log(log.contractAddress, log.selector, log.data)),
138
+ );
139
+ const newL2ToL1Messages = newWorldState.newL1Messages.map(m => new L2ToL1Message(m.recipient, m.content));
140
+
141
+ const returnValues = result.output;
142
+
143
+ // TODO: Support nested executions.
144
+ const nestedExecutions: PublicExecutionResult[] = [];
145
+ // TODO keep track of side effect counters
146
+ const startSideEffectCounter = Fr.ZERO;
147
+ const endSideEffectCounter = Fr.ZERO;
148
+
149
+ return {
150
+ execution,
151
+ nullifierReadRequests,
152
+ nullifierNonExistentReadRequests,
153
+ newNoteHashes,
154
+ newL2ToL1Messages,
155
+ startSideEffectCounter,
156
+ endSideEffectCounter,
157
+ newNullifiers,
158
+ contractStorageReads,
159
+ contractStorageUpdateRequests,
160
+ returnValues,
161
+ nestedExecutions,
162
+ unencryptedLogs,
163
+ reverted: result.reverted,
164
+ revertReason: result.revertReason ? createSimulationError(result.revertReason) : undefined,
165
+ };
166
+ }
167
+
168
+ export function convertPublicExecutionResult(res: PublicExecutionResult): AvmContractCallResults {
169
+ return new AvmContractCallResults(res.reverted, res.returnValues, res.revertReason);
170
+ }
171
+
172
+ export function updateAvmContextFromPublicExecutionResult(ctx: AvmContext, result: PublicExecutionResult): void {
173
+ // We have to push these manually and not use the trace* functions
174
+ // so that we respect the side effect counters.
175
+ for (const readRequest of result.contractStorageReads) {
176
+ ctx.persistableState.trace.publicStorageReads.push({
177
+ storageAddress: ctx.environment.storageAddress,
178
+ exists: true, // FIXME
179
+ slot: readRequest.storageSlot,
180
+ value: readRequest.currentValue,
181
+ counter: new Fr(readRequest.sideEffectCounter ?? Fr.ZERO),
182
+ });
183
+ }
184
+
185
+ for (const updateRequest of result.contractStorageUpdateRequests) {
186
+ ctx.persistableState.trace.publicStorageWrites.push({
187
+ storageAddress: ctx.environment.storageAddress,
188
+ slot: updateRequest.storageSlot,
189
+ value: updateRequest.newValue,
190
+ counter: new Fr(updateRequest.sideEffectCounter ?? Fr.ZERO),
191
+ });
192
+
193
+ // We need to manually populate the cache.
194
+ ctx.persistableState.publicStorage.write(
195
+ ctx.environment.storageAddress,
196
+ updateRequest.storageSlot,
197
+ updateRequest.newValue,
198
+ );
199
+ }
200
+
201
+ for (const nullifier of result.newNullifiers) {
202
+ ctx.persistableState.trace.newNullifiers.push({
203
+ storageAddress: ctx.environment.storageAddress,
204
+ nullifier: nullifier.value,
205
+ counter: nullifier.counter,
206
+ });
207
+ }
208
+
209
+ for (const noteHash of result.newNoteHashes) {
210
+ ctx.persistableState.trace.newNoteHashes.push({
211
+ storageAddress: ctx.environment.storageAddress,
212
+ noteHash: noteHash.value,
213
+ counter: noteHash.counter,
214
+ });
215
+ }
216
+
217
+ for (const message of result.newL2ToL1Messages) {
218
+ ctx.persistableState.newL1Messages.push(message);
219
+ }
220
+
221
+ for (const log of result.unencryptedLogs.logs) {
222
+ ctx.persistableState.newLogs.push(new UnencryptedL2Log(log.contractAddress, log.selector, log.data));
223
+ }
224
+ }
225
+
226
+ const AVM_MAGIC_SUFFIX = Buffer.from([
227
+ Mov.opcode, // opcode
228
+ 0x00, // indirect
229
+ ...Buffer.from('000018ca', 'hex'), // srcOffset
230
+ ...Buffer.from('000018ca', 'hex'), // dstOffset
231
+ ]);
232
+
233
+ export function markBytecodeAsAvm(bytecode: Buffer): Buffer {
234
+ return Buffer.concat([bytecode, AVM_MAGIC_SUFFIX]);
235
+ }
236
+
237
+ export function isAvmBytecode(bytecode: Buffer): boolean {
238
+ const magicSize = AVM_MAGIC_SUFFIX.length;
239
+ return bytecode.subarray(-magicSize).equals(AVM_MAGIC_SUFFIX);
240
+ }
@@ -1,19 +0,0 @@
1
- import { type ForeignCallInput } from '@noir-lang/acvm_js';
2
- import { type ACVMField } from '../acvm_types.js';
3
- /**
4
- * Convert an array of ACVMFields to a string.
5
- *
6
- * @param msg - array of ACVMFields where each represents a single ascii character
7
- * @returns string representation of the message
8
- */
9
- export declare function acvmFieldMessageToString(msg: ACVMField[]): string;
10
- /**
11
- * Convert an array of ACVMFields from ACVM to a formatted string.
12
- *
13
- * @param parameters - either one parameter representing a simple field or array, or two parameters when
14
- * It's a message without args or three parameters when it's a message with arguments.
15
- *
16
- * @returns formatted string
17
- */
18
- export declare function oracleDebugCallToFormattedStr(parameters: ForeignCallInput[]): string;
19
- //# sourceMappingURL=debug.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../../src/acvm/oracle/debug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,MAAM,CAajE;AAyBD;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAcpF"}