@aztec/simulator 0.46.7 → 0.47.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) 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/oracle/oracle.d.ts +4 -4
  4. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  5. package/dest/acvm/oracle/oracle.js +10 -12
  6. package/dest/acvm/oracle/typed_oracle.d.ts +9 -6
  7. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  8. package/dest/acvm/oracle/typed_oracle.js +3 -3
  9. package/dest/acvm/serialize.d.ts +0 -11
  10. package/dest/acvm/serialize.d.ts.map +1 -1
  11. package/dest/acvm/serialize.js +1 -26
  12. package/dest/avm/avm_gas.d.ts.map +1 -1
  13. package/dest/avm/avm_gas.js +5 -1
  14. package/dest/avm/fixtures/index.d.ts +2 -1
  15. package/dest/avm/fixtures/index.d.ts.map +1 -1
  16. package/dest/avm/fixtures/index.js +5 -2
  17. package/dest/avm/opcodes/commitment.d.ts +16 -0
  18. package/dest/avm/opcodes/commitment.d.ts.map +1 -0
  19. package/dest/avm/opcodes/commitment.js +50 -0
  20. package/dest/avm/opcodes/hashing.d.ts +11 -0
  21. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  22. package/dest/avm/opcodes/hashing.js +42 -3
  23. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  24. package/dest/avm/serialization/bytecode_serialization.js +7 -2
  25. package/dest/avm/serialization/instruction_serialization.d.ts +4 -1
  26. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  27. package/dest/avm/serialization/instruction_serialization.js +6 -2
  28. package/dest/client/client_execution_context.d.ts +17 -12
  29. package/dest/client/client_execution_context.d.ts.map +1 -1
  30. package/dest/client/client_execution_context.js +25 -31
  31. package/dest/client/execution_result.d.ts +12 -6
  32. package/dest/client/execution_result.d.ts.map +1 -1
  33. package/dest/client/execution_result.js +21 -8
  34. package/dest/mocks/fixtures.d.ts +5 -5
  35. package/dest/mocks/fixtures.d.ts.map +1 -1
  36. package/dest/mocks/fixtures.js +6 -9
  37. package/dest/providers/factory.d.ts +12 -0
  38. package/dest/providers/factory.d.ts.map +1 -0
  39. package/dest/providers/factory.js +27 -0
  40. package/dest/providers/index.d.ts +1 -0
  41. package/dest/providers/index.d.ts.map +1 -1
  42. package/dest/providers/index.js +2 -1
  43. package/dest/public/abstract_phase_manager.d.ts +4 -5
  44. package/dest/public/abstract_phase_manager.d.ts.map +1 -1
  45. package/dest/public/abstract_phase_manager.js +16 -83
  46. package/dest/public/execution.d.ts +8 -10
  47. package/dest/public/execution.d.ts.map +1 -1
  48. package/dest/public/execution.js +10 -1
  49. package/dest/public/executor.d.ts +2 -1
  50. package/dest/public/executor.d.ts.map +1 -1
  51. package/dest/public/executor.js +3 -3
  52. package/dest/public/index.d.ts +1 -1
  53. package/dest/public/index.d.ts.map +1 -1
  54. package/dest/public/index.js +1 -1
  55. package/dest/public/public_processor.d.ts +1 -1
  56. package/dest/public/public_processor.d.ts.map +1 -1
  57. package/dest/public/public_processor.js +9 -3
  58. package/dest/public/side_effect_trace.d.ts +1 -0
  59. package/dest/public/side_effect_trace.d.ts.map +1 -1
  60. package/dest/public/side_effect_trace.js +9 -9
  61. package/package.json +9 -9
  62. package/src/acvm/acvm.ts +1 -1
  63. package/src/acvm/oracle/oracle.ts +9 -7
  64. package/src/acvm/oracle/typed_oracle.ts +6 -10
  65. package/src/acvm/serialize.ts +0 -29
  66. package/src/avm/avm_gas.ts +4 -0
  67. package/src/avm/fixtures/index.ts +5 -1
  68. package/src/avm/opcodes/commitment.ts +66 -0
  69. package/src/avm/opcodes/hashing.ts +53 -2
  70. package/src/avm/serialization/bytecode_serialization.ts +6 -1
  71. package/src/avm/serialization/instruction_serialization.ts +4 -0
  72. package/src/client/client_execution_context.ts +34 -38
  73. package/src/client/execution_result.ts +25 -10
  74. package/src/mocks/fixtures.ts +13 -11
  75. package/src/providers/factory.ts +38 -0
  76. package/src/providers/index.ts +1 -0
  77. package/src/public/abstract_phase_manager.ts +22 -102
  78. package/src/public/execution.ts +30 -14
  79. package/src/public/executor.ts +4 -3
  80. package/src/public/index.ts +1 -1
  81. package/src/public/public_processor.ts +8 -5
  82. package/src/public/side_effect_trace.ts +13 -7
@@ -8,6 +8,7 @@ import {
8
8
  L1NotePayload,
9
9
  Note,
10
10
  type NoteStatus,
11
+ PublicExecutionRequest,
11
12
  TaggedLog,
12
13
  type UnencryptedL2Log,
13
14
  } from '@aztec/circuit-types';
@@ -17,7 +18,6 @@ import {
17
18
  type Header,
18
19
  type KeyValidationRequest,
19
20
  PrivateContextInputs,
20
- PublicCallRequest,
21
21
  type TxContext,
22
22
  } from '@aztec/circuits.js';
23
23
  import { Aes128 } from '@aztec/circuits.js/barretenberg';
@@ -29,7 +29,7 @@ import {
29
29
  type NoteSelector,
30
30
  countArgumentsSize,
31
31
  } from '@aztec/foundation/abi';
32
- import { AztecAddress } from '@aztec/foundation/aztec-address';
32
+ import { type AztecAddress } from '@aztec/foundation/aztec-address';
33
33
  import { pedersenHash } from '@aztec/foundation/crypto';
34
34
  import { Fr, GrumpkinScalar, type Point } from '@aztec/foundation/fields';
35
35
  import { applyStringFormatting, createDebugLogger } from '@aztec/foundation/log';
@@ -38,7 +38,13 @@ import { type NoteData, toACVMWitness } from '../acvm/index.js';
38
38
  import { type PackedValuesCache } from '../common/packed_values_cache.js';
39
39
  import { type DBOracle } from './db_oracle.js';
40
40
  import { type ExecutionNoteCache } from './execution_note_cache.js';
41
- import { CountedLog, CountedNoteLog, type ExecutionResult, type NoteAndSlot } from './execution_result.js';
41
+ import {
42
+ CountedLog,
43
+ CountedNoteLog,
44
+ CountedPublicExecutionRequest,
45
+ type ExecutionResult,
46
+ type NoteAndSlot,
47
+ } from './execution_result.js';
42
48
  import { pickNotes } from './pick_notes.js';
43
49
  import { executePrivateFunction } from './private_execution.js';
44
50
  import { ViewDataOracle } from './view_data_oracle.js';
@@ -70,8 +76,8 @@ export class ClientExecutionContext extends ViewDataOracle {
70
76
  private encryptedLogs: CountedLog<EncryptedL2Log>[] = [];
71
77
  private unencryptedLogs: CountedLog<UnencryptedL2Log>[] = [];
72
78
  private nestedExecutions: ExecutionResult[] = [];
73
- private enqueuedPublicFunctionCalls: PublicCallRequest[] = [];
74
- private publicTeardownFunctionCall: PublicCallRequest = PublicCallRequest.empty();
79
+ private enqueuedPublicFunctionCalls: CountedPublicExecutionRequest[] = [];
80
+ private publicTeardownFunctionCall: PublicExecutionRequest = PublicExecutionRequest.empty();
75
81
 
76
82
  constructor(
77
83
  contractAddress: AztecAddress,
@@ -377,6 +383,7 @@ export class ClientExecutionContext extends ViewDataOracle {
377
383
  * @param eventTypeId - The type ID of the event (function selector).
378
384
  * @param ovKeys - The outgoing viewing keys to use to encrypt.
379
385
  * @param ivpkM - The master incoming viewing public key.
386
+ * @param recipient - The recipient of the encrypted event log.
380
387
  * @param preimage - The event preimage.
381
388
  */
382
389
  public override computeEncryptedEventLog(
@@ -385,6 +392,7 @@ export class ClientExecutionContext extends ViewDataOracle {
385
392
  eventTypeId: Fr,
386
393
  ovKeys: KeyValidationRequest,
387
394
  ivpkM: Point,
395
+ recipient: AztecAddress,
388
396
  preimage: Fr[],
389
397
  ) {
390
398
  const event = new Event(preimage);
@@ -393,8 +401,6 @@ export class ClientExecutionContext extends ViewDataOracle {
393
401
 
394
402
  const ephSk = GrumpkinScalar.random();
395
403
 
396
- const recipient = AztecAddress.random();
397
-
398
404
  return taggedEvent.encrypt(ephSk, recipient, ivpkM, ovKeys);
399
405
  }
400
406
 
@@ -405,6 +411,7 @@ export class ClientExecutionContext extends ViewDataOracle {
405
411
  * @param noteTypeId - The type ID of the note.
406
412
  * @param ovKeys - The outgoing viewing keys to use to encrypt.
407
413
  * @param ivpkM - The master incoming viewing public key.
414
+ * @param recipient - The recipient of the encrypted note log.
408
415
  * @param preimage - The note preimage.
409
416
  */
410
417
  public override computeEncryptedNoteLog(
@@ -413,6 +420,7 @@ export class ClientExecutionContext extends ViewDataOracle {
413
420
  noteTypeId: NoteSelector,
414
421
  ovKeys: KeyValidationRequest,
415
422
  ivpkM: Point,
423
+ recipient: AztecAddress,
416
424
  preimage: Fr[],
417
425
  ) {
418
426
  const note = new Note(preimage);
@@ -421,11 +429,6 @@ export class ClientExecutionContext extends ViewDataOracle {
421
429
 
422
430
  const ephSk = GrumpkinScalar.random();
423
431
 
424
- // @todo This should be populated properly.
425
- // Note that this encryption function SHOULD not be used, but is currently used
426
- // as oracle for encrypted event logs.
427
- const recipient = AztecAddress.random();
428
-
429
432
  return taggedNote.encrypt(ephSk, recipient, ivpkM, ovKeys);
430
433
  }
431
434
 
@@ -531,7 +534,11 @@ export class ClientExecutionContext extends ViewDataOracle {
531
534
 
532
535
  this.nestedExecutions.push(childExecutionResult);
533
536
 
534
- return childExecutionResult.callStackItem;
537
+ const publicInputs = childExecutionResult.callStackItem.publicInputs;
538
+ return {
539
+ endSideEffectCounter: publicInputs.endSideEffectCounter,
540
+ returnsHash: publicInputs.returnsHash,
541
+ };
535
542
  }
536
543
 
537
544
  /**
@@ -543,7 +550,7 @@ export class ClientExecutionContext extends ViewDataOracle {
543
550
  * @param isStaticCall - Whether the call is a static call.
544
551
  * @returns The public call stack item with the request information.
545
552
  */
546
- protected async createPublicCallRequest(
553
+ protected async createPublicExecutionRequest(
547
554
  callType: 'enqueued' | 'teardown',
548
555
  targetContractAddress: AztecAddress,
549
556
  functionSelector: FunctionSelector,
@@ -551,9 +558,7 @@ export class ClientExecutionContext extends ViewDataOracle {
551
558
  sideEffectCounter: number,
552
559
  isStaticCall: boolean,
553
560
  isDelegateCall: boolean,
554
- ): Promise<PublicCallRequest> {
555
- isStaticCall = isStaticCall || this.callContext.isStaticCall;
556
-
561
+ ) {
557
562
  const targetArtifact = await this.db.getFunctionArtifact(targetContractAddress, functionSelector);
558
563
  const derivedCallContext = this.deriveCallContext(
559
564
  targetContractAddress,
@@ -563,22 +568,21 @@ export class ClientExecutionContext extends ViewDataOracle {
563
568
  );
564
569
  const args = this.packedValuesCache.unpack(argsHash);
565
570
 
566
- // TODO($846): if enqueued public calls are associated with global
567
- // side-effect counter, that will leak info about how many other private
568
- // side-effects occurred in the TX. Ultimately the private kernel should
569
- // just output everything in the proper order without any counters.
570
571
  this.log.verbose(
571
- `Created PublicCallRequest of type [${callType}], side-effect counter [${sideEffectCounter}] to ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`,
572
+ `Created PublicExecutionRequest of type [${callType}], side-effect counter [${sideEffectCounter}] to ${targetContractAddress}:${functionSelector}(${targetArtifact.name})`,
572
573
  );
573
574
 
574
- return PublicCallRequest.from({
575
+ const request = PublicExecutionRequest.from({
575
576
  args,
576
577
  callContext: derivedCallContext,
577
- parentCallContext: this.callContext,
578
- functionSelector,
579
578
  contractAddress: targetContractAddress,
580
- sideEffectCounter,
581
579
  });
580
+
581
+ if (callType === 'enqueued') {
582
+ this.enqueuedPublicFunctionCalls.push(new CountedPublicExecutionRequest(request, sideEffectCounter));
583
+ } else {
584
+ this.publicTeardownFunctionCall = request;
585
+ }
582
586
  }
583
587
 
584
588
  /**
@@ -599,8 +603,8 @@ export class ClientExecutionContext extends ViewDataOracle {
599
603
  sideEffectCounter: number,
600
604
  isStaticCall: boolean,
601
605
  isDelegateCall: boolean,
602
- ): Promise<PublicCallRequest> {
603
- const enqueuedRequest = await this.createPublicCallRequest(
606
+ ) {
607
+ await this.createPublicExecutionRequest(
604
608
  'enqueued',
605
609
  targetContractAddress,
606
610
  functionSelector,
@@ -609,10 +613,6 @@ export class ClientExecutionContext extends ViewDataOracle {
609
613
  isStaticCall,
610
614
  isDelegateCall,
611
615
  );
612
-
613
- this.enqueuedPublicFunctionCalls.push(enqueuedRequest);
614
-
615
- return enqueuedRequest;
616
616
  }
617
617
 
618
618
  /**
@@ -633,8 +633,8 @@ export class ClientExecutionContext extends ViewDataOracle {
633
633
  sideEffectCounter: number,
634
634
  isStaticCall: boolean,
635
635
  isDelegateCall: boolean,
636
- ): Promise<PublicCallRequest> {
637
- const publicTeardownFunctionCall = await this.createPublicCallRequest(
636
+ ) {
637
+ await this.createPublicExecutionRequest(
638
638
  'teardown',
639
639
  targetContractAddress,
640
640
  functionSelector,
@@ -643,10 +643,6 @@ export class ClientExecutionContext extends ViewDataOracle {
643
643
  isStaticCall,
644
644
  isDelegateCall,
645
645
  );
646
-
647
- this.publicTeardownFunctionCall = publicTeardownFunctionCall;
648
-
649
- return publicTeardownFunctionCall;
650
646
  }
651
647
 
652
648
  /**
@@ -4,10 +4,11 @@ import {
4
4
  type EncryptedL2NoteLog,
5
5
  EncryptedNoteFunctionL2Logs,
6
6
  type Note,
7
+ PublicExecutionRequest,
7
8
  UnencryptedFunctionL2Logs,
8
9
  type UnencryptedL2Log,
9
10
  } from '@aztec/circuit-types';
10
- import { type IsEmpty, type PrivateCallStackItem, PublicCallRequest, sortByCounter } from '@aztec/circuits.js';
11
+ import { type IsEmpty, type PrivateCallStackItem, sortByCounter } from '@aztec/circuits.js';
11
12
  import { type NoteSelector } from '@aztec/foundation/abi';
12
13
  import { type Fr } from '@aztec/foundation/fields';
13
14
 
@@ -38,6 +39,15 @@ export class CountedNoteLog extends CountedLog<EncryptedL2NoteLog> {
38
39
  super(log, counter);
39
40
  }
40
41
  }
42
+
43
+ export class CountedPublicExecutionRequest {
44
+ constructor(public request: PublicExecutionRequest, public counter: number) {}
45
+
46
+ isEmpty(): boolean {
47
+ return this.request.isEmpty() && !this.counter;
48
+ }
49
+ }
50
+
41
51
  /**
42
52
  * The result of executing a private function.
43
53
  */
@@ -63,9 +73,9 @@ export interface ExecutionResult {
63
73
  /** The nested executions. */
64
74
  nestedExecutions: this[];
65
75
  /** Enqueued public function execution requests to be picked up by the sequencer. */
66
- enqueuedPublicFunctionCalls: PublicCallRequest[];
76
+ enqueuedPublicFunctionCalls: CountedPublicExecutionRequest[];
67
77
  /** Public function execution requested for teardown */
68
- publicTeardownFunctionCall: PublicCallRequest;
78
+ publicTeardownFunctionCall: PublicExecutionRequest;
69
79
  /**
70
80
  * Encrypted note logs emitted during execution of this function call.
71
81
  * Note: These are preimages to `noteEncryptedLogsHashes`.
@@ -161,21 +171,26 @@ export function collectSortedUnencryptedLogs(execResult: ExecutionResult): Unenc
161
171
  return new UnencryptedFunctionL2Logs(sortedLogs.map(l => l.log));
162
172
  }
163
173
 
174
+ function collectEnqueuedCountedPublicExecutionRequests(execResult: ExecutionResult): CountedPublicExecutionRequest[] {
175
+ return [
176
+ ...execResult.enqueuedPublicFunctionCalls,
177
+ ...execResult.nestedExecutions.flatMap(collectEnqueuedCountedPublicExecutionRequests),
178
+ ];
179
+ }
180
+
164
181
  /**
165
182
  * Collect all enqueued public function calls across all nested executions.
166
183
  * @param execResult - The topmost execution result.
167
184
  * @returns All enqueued public function calls.
168
185
  */
169
- export function collectEnqueuedPublicFunctionCalls(execResult: ExecutionResult): PublicCallRequest[] {
186
+ export function collectEnqueuedPublicFunctionCalls(execResult: ExecutionResult): PublicExecutionRequest[] {
187
+ const countedRequests = collectEnqueuedCountedPublicExecutionRequests(execResult);
170
188
  // without the reverse sort, the logs will be in a queue like fashion which is wrong
171
189
  // as the kernel processes it like a stack, popping items off and pushing them to output
172
- return [
173
- ...execResult.enqueuedPublicFunctionCalls,
174
- ...execResult.nestedExecutions.flatMap(collectEnqueuedPublicFunctionCalls),
175
- ].sort((a, b) => b.sideEffectCounter - a.sideEffectCounter);
190
+ return sortByCounter(countedRequests, false).map(r => r.request);
176
191
  }
177
192
 
178
- export function collectPublicTeardownFunctionCall(execResult: ExecutionResult): PublicCallRequest {
193
+ export function collectPublicTeardownFunctionCall(execResult: ExecutionResult): PublicExecutionRequest {
179
194
  const teardownCalls = [
180
195
  execResult.publicTeardownFunctionCall,
181
196
  ...execResult.nestedExecutions.flatMap(collectPublicTeardownFunctionCall),
@@ -189,5 +204,5 @@ export function collectPublicTeardownFunctionCall(execResult: ExecutionResult):
189
204
  throw new Error('Multiple public teardown calls detected');
190
205
  }
191
206
 
192
- return PublicCallRequest.empty();
207
+ return PublicExecutionRequest.empty();
193
208
  }
@@ -1,4 +1,9 @@
1
- import { type FunctionCall, type SimulationError, UnencryptedFunctionL2Logs } from '@aztec/circuit-types';
1
+ import {
2
+ type FunctionCall,
3
+ PublicExecutionRequest,
4
+ type SimulationError,
5
+ UnencryptedFunctionL2Logs,
6
+ } from '@aztec/circuit-types';
2
7
  import {
3
8
  ARGS_LENGTH,
4
9
  AvmExecutionHints,
@@ -8,13 +13,12 @@ import {
8
13
  type ContractStorageUpdateRequest,
9
14
  Fr,
10
15
  Gas,
11
- type PublicCallRequest,
12
16
  } from '@aztec/circuits.js';
13
17
  import { makeAztecAddress, makeSelector } from '@aztec/circuits.js/testing';
14
18
  import { FunctionType } from '@aztec/foundation/abi';
15
19
  import { padArrayEnd } from '@aztec/foundation/collection';
16
20
 
17
- import { type PublicExecutionRequest, type PublicExecutionResult } from '../public/execution.js';
21
+ import { type PublicExecutionResult, resultToPublicCallRequest } from '../public/execution.js';
18
22
 
19
23
  export class PublicExecutionResultBuilder {
20
24
  private _executionRequest: PublicExecutionRequest;
@@ -29,7 +33,7 @@ export class PublicExecutionResultBuilder {
29
33
  this._executionRequest = executionRequest;
30
34
  }
31
35
 
32
- static fromPublicCallRequest({
36
+ static fromPublicExecutionRequest({
33
37
  request,
34
38
  returnValues = [new Fr(1n)],
35
39
  nestedExecutions = [],
@@ -37,7 +41,7 @@ export class PublicExecutionResultBuilder {
37
41
  contractStorageReads = [],
38
42
  revertReason = undefined,
39
43
  }: {
40
- request: PublicCallRequest;
44
+ request: PublicExecutionRequest;
41
45
  returnValues?: Fr[];
42
46
  nestedExecutions?: PublicExecutionResult[];
43
47
  contractStorageUpdateRequests?: ContractStorageUpdateRequest[];
@@ -74,12 +78,9 @@ export class PublicExecutionResultBuilder {
74
78
  contractStorageReads?: ContractStorageRead[];
75
79
  revertReason?: SimulationError;
76
80
  }) {
77
- const builder = new PublicExecutionResultBuilder({
78
- callContext: new CallContext(from, tx.to, tx.selector, false, false),
79
- contractAddress: tx.to,
80
- functionSelector: tx.selector,
81
- args: tx.args,
82
- });
81
+ const builder = new PublicExecutionResultBuilder(
82
+ new PublicExecutionRequest(tx.to, new CallContext(from, tx.to, tx.selector, false, false), tx.args),
83
+ );
83
84
 
84
85
  builder.withNestedExecutions(...nestedExecutions);
85
86
  builder.withContractStorageUpdateRequest(...contractStorageUpdateRequests);
@@ -122,6 +123,7 @@ export class PublicExecutionResultBuilder {
122
123
  return {
123
124
  executionRequest: this._executionRequest,
124
125
  nestedExecutions: this._nestedExecutions,
126
+ publicCallRequests: this._nestedExecutions.map(resultToPublicCallRequest),
125
127
  noteHashReadRequests: [],
126
128
  nullifierReadRequests: [],
127
129
  nullifierNonExistentReadRequests: [],
@@ -0,0 +1,38 @@
1
+ import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
2
+
3
+ import * as fs from 'fs/promises';
4
+
5
+ import { NativeACVMSimulator } from './acvm_native.js';
6
+ import { WASMSimulator } from './acvm_wasm.js';
7
+ import { type SimulationProvider } from './simulation_provider.js';
8
+
9
+ export type SimulationProviderConfig = {
10
+ acvmBinaryPath?: string;
11
+ acvmWorkingDirectory?: string;
12
+ };
13
+
14
+ export function getSimulationProviderConfigFromEnv() {
15
+ const { ACVM_BINARY_PATH, ACVM_WORKING_DIRECTORY } = process.env;
16
+ return {
17
+ acvmWorkingDirectory: ACVM_WORKING_DIRECTORY ? ACVM_WORKING_DIRECTORY : undefined,
18
+ acvmBinaryPath: ACVM_BINARY_PATH ? ACVM_BINARY_PATH : undefined,
19
+ };
20
+ }
21
+
22
+ export async function createSimulationProvider(
23
+ config: SimulationProviderConfig,
24
+ logger: DebugLogger = createDebugLogger('aztec:simulator'),
25
+ ): Promise<SimulationProvider> {
26
+ if (config.acvmBinaryPath && config.acvmWorkingDirectory) {
27
+ try {
28
+ await fs.access(config.acvmBinaryPath, fs.constants.R_OK);
29
+ await fs.mkdir(config.acvmWorkingDirectory, { recursive: true });
30
+ logger.info(`Using native ACVM at ${config.acvmBinaryPath} and working directory ${config.acvmWorkingDirectory}`);
31
+ return new NativeACVMSimulator(config.acvmWorkingDirectory, config.acvmBinaryPath);
32
+ } catch {
33
+ logger.warn(`Failed to access ACVM at ${config.acvmBinaryPath}, falling back to WASM`);
34
+ }
35
+ }
36
+ logger.info('Using WASM ACVM simulation');
37
+ return new WASMSimulator();
38
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './acvm_native.js';
2
2
  export * from './acvm_wasm.js';
3
3
  export * from './simulation_provider.js';
4
+ export * from './factory.js';
@@ -3,6 +3,7 @@ import {
3
3
  type AvmProvingRequest,
4
4
  MerkleTreeId,
5
5
  type NestedProcessReturnValues,
6
+ type PublicExecutionRequest,
6
7
  type PublicKernelNonTailRequest,
7
8
  PublicKernelType,
8
9
  type PublicProvingRequest,
@@ -13,7 +14,6 @@ import {
13
14
  import {
14
15
  type AvmExecutionHints,
15
16
  AztecAddress,
16
- CallRequest,
17
17
  ClientIvcProof,
18
18
  ContractStorageRead,
19
19
  ContractStorageUpdateRequest,
@@ -40,7 +40,7 @@ import {
40
40
  NoteHash,
41
41
  Nullifier,
42
42
  PublicCallData,
43
- type PublicCallRequest,
43
+ PublicCallRequest,
44
44
  PublicCallStackItem,
45
45
  PublicCircuitPublicInputs,
46
46
  PublicKernelCircuitPrivateInputs,
@@ -62,7 +62,6 @@ import {
62
62
  getVKSiblingPath,
63
63
  } from '@aztec/noir-protocol-circuits-types';
64
64
  import {
65
- type PublicExecutionRequest,
66
65
  type PublicExecutionResult,
67
66
  type PublicExecutor,
68
67
  accumulateReturnValues,
@@ -165,76 +164,18 @@ export abstract class AbstractPhaseManager {
165
164
  previousKernelArtifact: ProtocolArtifact,
166
165
  ): Promise<PhaseResult>;
167
166
 
168
- public static extractEnqueuedPublicCallsByPhase(tx: Tx): Record<PublicKernelType, PublicCallRequest[]> {
169
- const data = tx.data.forPublic;
170
- if (!data) {
171
- return {
172
- [PublicKernelType.NON_PUBLIC]: [],
173
- [PublicKernelType.SETUP]: [],
174
- [PublicKernelType.APP_LOGIC]: [],
175
- [PublicKernelType.TEARDOWN]: [],
176
- [PublicKernelType.TAIL]: [],
177
- };
178
- }
179
- const publicCallsStack = tx.enqueuedPublicFunctionCalls.slice().reverse();
180
- const nonRevertibleCallStack = data.endNonRevertibleData.publicCallStack.filter(i => !i.isEmpty());
181
- const revertibleCallStack = data.end.publicCallStack.filter(i => !i.isEmpty());
182
-
183
- const callRequestsStack = publicCallsStack
184
- .map(call => call.toCallRequest())
185
- .filter(
186
- // filter out enqueued calls that are not in the public call stack
187
- // TODO mitch left a question about whether this is only needed when unit testing
188
- // with mock data
189
- call => revertibleCallStack.find(p => p.equals(call)) || nonRevertibleCallStack.find(p => p.equals(call)),
190
- );
191
-
192
- const teardownCallStack = tx.publicTeardownFunctionCall.isEmpty() ? [] : [tx.publicTeardownFunctionCall];
193
-
194
- if (callRequestsStack.length === 0) {
195
- return {
196
- [PublicKernelType.NON_PUBLIC]: [],
197
- [PublicKernelType.SETUP]: [],
198
- [PublicKernelType.APP_LOGIC]: [],
199
- [PublicKernelType.TEARDOWN]: teardownCallStack,
200
- [PublicKernelType.TAIL]: [],
201
- };
202
- }
203
-
204
- // find the first call that is revertible
205
- const firstRevertibleCallIndex = callRequestsStack.findIndex(
206
- c => revertibleCallStack.findIndex(p => p.equals(c)) !== -1,
207
- );
208
-
209
- if (firstRevertibleCallIndex === 0) {
210
- return {
211
- [PublicKernelType.NON_PUBLIC]: [],
212
- [PublicKernelType.SETUP]: [],
213
- [PublicKernelType.APP_LOGIC]: publicCallsStack,
214
- [PublicKernelType.TEARDOWN]: teardownCallStack,
215
- [PublicKernelType.TAIL]: [],
216
- };
217
- } else if (firstRevertibleCallIndex === -1) {
218
- // there's no app logic, split the functions between setup (many) and teardown (just one function call)
219
- return {
220
- [PublicKernelType.NON_PUBLIC]: [],
221
- [PublicKernelType.SETUP]: publicCallsStack,
222
- [PublicKernelType.APP_LOGIC]: [],
223
- [PublicKernelType.TEARDOWN]: teardownCallStack,
224
- [PublicKernelType.TAIL]: [],
225
- };
226
- } else {
227
- return {
228
- [PublicKernelType.NON_PUBLIC]: [],
229
- [PublicKernelType.SETUP]: publicCallsStack.slice(0, firstRevertibleCallIndex),
230
- [PublicKernelType.APP_LOGIC]: publicCallsStack.slice(firstRevertibleCallIndex),
231
- [PublicKernelType.TEARDOWN]: teardownCallStack,
232
- [PublicKernelType.TAIL]: [],
233
- };
234
- }
167
+ public static extractEnqueuedPublicCallsByPhase(tx: Tx): Record<PublicKernelType, PublicExecutionRequest[]> {
168
+ const teardownRequest = tx.getPublicTeardownExecutionRequest();
169
+ return {
170
+ [PublicKernelType.NON_PUBLIC]: [],
171
+ [PublicKernelType.SETUP]: tx.getNonRevertiblePublicExecutionRequests(),
172
+ [PublicKernelType.APP_LOGIC]: tx.getRevertiblePublicExecutionRequests(),
173
+ [PublicKernelType.TEARDOWN]: teardownRequest ? [teardownRequest] : [],
174
+ [PublicKernelType.TAIL]: [],
175
+ };
235
176
  }
236
177
 
237
- protected extractEnqueuedPublicCalls(tx: Tx): PublicCallRequest[] {
178
+ protected extractEnqueuedPublicCalls(tx: Tx): PublicExecutionRequest[] {
238
179
  const calls = AbstractPhaseManager.extractEnqueuedPublicCallsByPhase(tx)[this.phase];
239
180
 
240
181
  return calls;
@@ -245,7 +186,7 @@ export abstract class AbstractPhaseManager {
245
186
  previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
246
187
  previousKernelArtifact: ProtocolArtifact,
247
188
  ): Promise<TxPublicCallsResult> {
248
- const enqueuedCalls = this.extractEnqueuedPublicCalls(tx);
189
+ const enqueuedCalls = [...this.extractEnqueuedPublicCalls(tx)].reverse();
249
190
 
250
191
  if (!enqueuedCalls || !enqueuedCalls.length) {
251
192
  return {
@@ -299,7 +240,7 @@ export abstract class AbstractPhaseManager {
299
240
 
300
241
  // Sanity check for a current upstream assumption.
301
242
  // Consumers of the result seem to expect "reverted <=> revertReason !== undefined".
302
- const functionSelector = result.executionRequest.functionSelector.toString();
243
+ const functionSelector = result.executionRequest.callContext.functionSelector.toString();
303
244
  if (result.reverted && !result.revertReason) {
304
245
  throw new Error(
305
246
  `Simulation of ${result.executionRequest.contractAddress.toString()}:${functionSelector}(${
@@ -460,13 +401,6 @@ export abstract class AbstractPhaseManager {
460
401
  const publicDataTreeInfo = await this.db.getTreeInfo(MerkleTreeId.PUBLIC_DATA_TREE);
461
402
  this.historicalHeader.state.partial.publicDataTree.root = Fr.fromBuffer(publicDataTreeInfo.root);
462
403
 
463
- const callStackPreimages = await this.getPublicCallStackPreimages(result);
464
- const publicCallStackHashes = padArrayEnd(
465
- callStackPreimages.map(c => c.getCompressed().hash()),
466
- Fr.ZERO,
467
- MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
468
- );
469
-
470
404
  const publicCircuitPublicInputs = PublicCircuitPublicInputs.from({
471
405
  callContext: result.executionRequest.callContext,
472
406
  proverAddress: AztecAddress.ZERO,
@@ -507,7 +441,11 @@ export abstract class AbstractPhaseManager {
507
441
  ContractStorageUpdateRequest.empty(),
508
442
  MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL,
509
443
  ),
510
- publicCallStackHashes,
444
+ publicCallRequests: padArrayEnd(
445
+ result.publicCallRequests,
446
+ PublicCallRequest.empty(),
447
+ MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL,
448
+ ),
511
449
  unencryptedLogsHashes: padArrayEnd(result.unencryptedLogsHashes, LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_CALL),
512
450
  historicalHeader: this.historicalHeader,
513
451
  globalVariables: this.globalVariables,
@@ -520,23 +458,12 @@ export abstract class AbstractPhaseManager {
520
458
 
521
459
  return new PublicCallStackItem(
522
460
  result.executionRequest.contractAddress,
523
- new FunctionData(result.executionRequest.functionSelector, false),
461
+ new FunctionData(result.executionRequest.callContext.functionSelector, false),
524
462
  publicCircuitPublicInputs,
525
463
  isExecutionRequest,
526
464
  );
527
465
  }
528
466
 
529
- protected async getPublicCallStackPreimages(result: PublicExecutionResult): Promise<PublicCallStackItem[]> {
530
- const nested = result.nestedExecutions;
531
- if (nested.length > MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL) {
532
- throw new Error(
533
- `Public call stack size exceeded (max ${MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL}, got ${nested.length})`,
534
- );
535
- }
536
-
537
- return await Promise.all(nested.map(n => this.getPublicCallStackItem(n)));
538
- }
539
-
540
467
  /**
541
468
  * Looks at the side effects of a transaction and returns the highest counter
542
469
  * @param tx - A transaction
@@ -562,10 +489,7 @@ export abstract class AbstractPhaseManager {
562
489
 
563
490
  let max = 0;
564
491
  for (const sideEffect of sideEffectCounters) {
565
- if ('startSideEffectCounter' in sideEffect) {
566
- // look at both start and end counters because for enqueued public calls start > 0 while end === 0
567
- max = Math.max(max, sideEffect.startSideEffectCounter.toNumber(), sideEffect.endSideEffectCounter.toNumber());
568
- } else if ('counter' in sideEffect) {
492
+ if ('counter' in sideEffect) {
569
493
  max = Math.max(max, sideEffect.counter);
570
494
  } else {
571
495
  throw new Error('Unknown side effect type');
@@ -593,10 +517,6 @@ export abstract class AbstractPhaseManager {
593
517
  protected async getPublicCallData(result: PublicExecutionResult, isExecutionRequest = false) {
594
518
  const bytecodeHash = await this.getBytecodeHash(result);
595
519
  const callStackItem = await this.getPublicCallStackItem(result, isExecutionRequest);
596
- const publicCallRequests = (await this.getPublicCallStackPreimages(result)).map(c =>
597
- c.toCallRequest(callStackItem.publicInputs.callContext),
598
- );
599
- const publicCallStack = padArrayEnd(publicCallRequests, CallRequest.empty(), MAX_PUBLIC_CALL_STACK_LENGTH_PER_CALL);
600
- return new PublicCallData(callStackItem, publicCallStack, makeEmptyProof(), bytecodeHash);
520
+ return new PublicCallData(callStackItem, makeEmptyProof(), bytecodeHash);
601
521
  }
602
522
  }