@aztec/simulator 0.34.0 → 0.35.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 (168) hide show
  1. package/dest/acvm/acvm.d.ts +4 -1
  2. package/dest/acvm/acvm.d.ts.map +1 -1
  3. package/dest/acvm/acvm.js +5 -5
  4. package/dest/acvm/deserialize.d.ts +3 -5
  5. package/dest/acvm/deserialize.d.ts.map +1 -1
  6. package/dest/acvm/deserialize.js +6 -9
  7. package/dest/acvm/oracle/oracle.d.ts +2 -0
  8. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  9. package/dest/acvm/oracle/oracle.js +12 -4
  10. package/dest/acvm/oracle/typed_oracle.d.ts +2 -0
  11. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  12. package/dest/acvm/oracle/typed_oracle.js +7 -1
  13. package/dest/avm/avm_execution_environment.d.ts +4 -2
  14. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  15. package/dest/avm/avm_execution_environment.js +7 -5
  16. package/dest/avm/avm_gas.js +2 -2
  17. package/dest/avm/avm_machine_state.d.ts +2 -0
  18. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  19. package/dest/avm/avm_machine_state.js +24 -6
  20. package/dest/avm/avm_memory_types.js +2 -2
  21. package/dest/avm/avm_simulator.js +2 -2
  22. package/dest/avm/fixtures/index.d.ts +3 -0
  23. package/dest/avm/fixtures/index.d.ts.map +1 -1
  24. package/dest/avm/fixtures/index.js +11 -4
  25. package/dest/avm/journal/journal.d.ts +1 -0
  26. package/dest/avm/journal/journal.d.ts.map +1 -1
  27. package/dest/avm/journal/journal.js +12 -1
  28. package/dest/avm/opcodes/accrued_substate.d.ts +2 -1
  29. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  30. package/dest/avm/opcodes/accrued_substate.js +13 -5
  31. package/dest/avm/opcodes/context_getters.js +2 -2
  32. package/dest/avm/opcodes/external_calls.d.ts +2 -2
  33. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  34. package/dest/avm/opcodes/external_calls.js +7 -6
  35. package/dest/avm/opcodes/hashing.d.ts +8 -8
  36. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  37. package/dest/avm/opcodes/hashing.js +35 -43
  38. package/dest/avm/serialization/instruction_serialization.d.ts +1 -1
  39. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  40. package/dest/avm/serialization/instruction_serialization.js +2 -2
  41. package/dest/client/client_execution_context.d.ts +13 -3
  42. package/dest/client/client_execution_context.d.ts.map +1 -1
  43. package/dest/client/client_execution_context.js +23 -8
  44. package/dest/client/private_execution.d.ts.map +1 -1
  45. package/dest/client/private_execution.js +8 -6
  46. package/dest/client/simulator.d.ts.map +1 -1
  47. package/dest/client/simulator.js +6 -5
  48. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  49. package/dest/client/unconstrained_execution.js +5 -4
  50. package/dest/common/index.d.ts +1 -1
  51. package/dest/common/index.d.ts.map +1 -1
  52. package/dest/common/index.js +2 -2
  53. package/dest/common/packed_values_cache.d.ts +28 -0
  54. package/dest/common/packed_values_cache.d.ts.map +1 -0
  55. package/dest/common/packed_values_cache.js +50 -0
  56. package/dest/index.d.ts +1 -0
  57. package/dest/index.d.ts.map +1 -1
  58. package/dest/index.js +2 -1
  59. package/dest/mocks/fixtures.d.ts +42 -0
  60. package/dest/mocks/fixtures.d.ts.map +1 -0
  61. package/dest/mocks/fixtures.js +84 -0
  62. package/dest/mocks/index.d.ts +2 -0
  63. package/dest/mocks/index.d.ts.map +1 -0
  64. package/dest/mocks/index.js +2 -0
  65. package/dest/public/abstract_phase_manager.d.ts +82 -0
  66. package/dest/public/abstract_phase_manager.d.ts.map +1 -0
  67. package/dest/public/abstract_phase_manager.js +320 -0
  68. package/dest/public/app_logic_phase_manager.d.ts +29 -0
  69. package/dest/public/app_logic_phase_manager.d.ts.map +1 -0
  70. package/dest/public/app_logic_phase_manager.js +50 -0
  71. package/dest/public/execution.d.ts +3 -0
  72. package/dest/public/execution.d.ts.map +1 -1
  73. package/dest/public/execution.js +1 -1
  74. package/dest/public/executor.d.ts.map +1 -1
  75. package/dest/public/executor.js +17 -13
  76. package/dest/public/hints_builder.d.ts +23 -0
  77. package/dest/public/hints_builder.d.ts.map +1 -0
  78. package/dest/public/hints_builder.js +62 -0
  79. package/dest/public/index.d.ts +5 -0
  80. package/dest/public/index.d.ts.map +1 -1
  81. package/dest/public/index.js +6 -1
  82. package/dest/public/phase_manager_factory.d.ts +18 -0
  83. package/dest/public/phase_manager_factory.d.ts.map +1 -0
  84. package/dest/public/phase_manager_factory.js +56 -0
  85. package/dest/public/public_execution_context.d.ts +15 -5
  86. package/dest/public/public_execution_context.d.ts.map +1 -1
  87. package/dest/public/public_execution_context.js +28 -12
  88. package/dest/public/public_executor.d.ts +79 -0
  89. package/dest/public/public_executor.d.ts.map +1 -0
  90. package/dest/public/public_executor.js +198 -0
  91. package/dest/public/public_kernel.d.ts +37 -0
  92. package/dest/public/public_kernel.d.ts.map +1 -0
  93. package/dest/public/public_kernel.js +97 -0
  94. package/dest/public/public_kernel_circuit_simulator.d.ts +31 -0
  95. package/dest/public/public_kernel_circuit_simulator.d.ts.map +1 -0
  96. package/dest/public/public_kernel_circuit_simulator.js +2 -0
  97. package/dest/public/public_processor.d.ts +53 -0
  98. package/dest/public/public_processor.d.ts.map +1 -0
  99. package/dest/public/public_processor.js +144 -0
  100. package/dest/public/setup_phase_manager.d.ts +30 -0
  101. package/dest/public/setup_phase_manager.d.ts.map +1 -0
  102. package/dest/public/setup_phase_manager.js +46 -0
  103. package/dest/public/tail_phase_manager.d.ts +30 -0
  104. package/dest/public/tail_phase_manager.d.ts.map +1 -0
  105. package/dest/public/tail_phase_manager.js +60 -0
  106. package/dest/public/teardown_phase_manager.d.ts +30 -0
  107. package/dest/public/teardown_phase_manager.d.ts.map +1 -0
  108. package/dest/public/teardown_phase_manager.js +46 -0
  109. package/dest/public/transitional_adaptors.d.ts +2 -1
  110. package/dest/public/transitional_adaptors.d.ts.map +1 -1
  111. package/dest/public/transitional_adaptors.js +11 -10
  112. package/dest/public/utils.d.ts +8 -0
  113. package/dest/public/utils.d.ts.map +1 -0
  114. package/dest/public/utils.js +29 -0
  115. package/dest/simulator/acvm_native.d.ts +19 -3
  116. package/dest/simulator/acvm_native.d.ts.map +1 -1
  117. package/dest/simulator/acvm_native.js +75 -48
  118. package/dest/simulator/acvm_wasm.d.ts.map +1 -1
  119. package/dest/simulator/acvm_wasm.js +3 -4
  120. package/package.json +8 -5
  121. package/src/acvm/acvm.ts +8 -5
  122. package/src/acvm/deserialize.ts +5 -9
  123. package/src/acvm/oracle/oracle.ts +13 -3
  124. package/src/acvm/oracle/typed_oracle.ts +8 -0
  125. package/src/avm/avm_execution_environment.ts +9 -1
  126. package/src/avm/avm_gas.ts +1 -1
  127. package/src/avm/avm_machine_state.ts +26 -5
  128. package/src/avm/avm_memory_types.ts +1 -1
  129. package/src/avm/avm_simulator.ts +1 -1
  130. package/src/avm/fixtures/index.ts +13 -1
  131. package/src/avm/journal/journal.ts +13 -0
  132. package/src/avm/opcodes/accrued_substate.ts +16 -4
  133. package/src/avm/opcodes/context_getters.ts +1 -1
  134. package/src/avm/opcodes/external_calls.ts +8 -5
  135. package/src/avm/opcodes/hashing.ts +38 -54
  136. package/src/avm/serialization/instruction_serialization.ts +1 -1
  137. package/src/client/client_execution_context.ts +25 -6
  138. package/src/client/private_execution.ts +7 -6
  139. package/src/client/simulator.ts +7 -3
  140. package/src/client/unconstrained_execution.ts +4 -3
  141. package/src/common/index.ts +1 -1
  142. package/src/common/packed_values_cache.ts +55 -0
  143. package/src/index.ts +1 -0
  144. package/src/mocks/fixtures.ts +169 -0
  145. package/src/mocks/index.ts +1 -0
  146. package/src/public/abstract_phase_manager.ts +571 -0
  147. package/src/public/app_logic_phase_manager.ts +76 -0
  148. package/src/public/execution.ts +4 -0
  149. package/src/public/executor.ts +18 -13
  150. package/src/public/hints_builder.ts +119 -0
  151. package/src/public/index.ts +5 -0
  152. package/src/public/phase_manager_factory.ts +126 -0
  153. package/src/public/public_execution_context.ts +29 -18
  154. package/src/public/public_executor.ts +267 -0
  155. package/src/public/public_kernel.ts +139 -0
  156. package/src/public/public_kernel_circuit_simulator.ts +36 -0
  157. package/src/public/public_processor.ts +212 -0
  158. package/src/public/setup_phase_manager.ts +66 -0
  159. package/src/public/tail_phase_manager.ts +120 -0
  160. package/src/public/teardown_phase_manager.ts +66 -0
  161. package/src/public/transitional_adaptors.ts +14 -5
  162. package/src/public/utils.ts +31 -0
  163. package/src/simulator/acvm_native.ts +94 -47
  164. package/src/simulator/acvm_wasm.ts +7 -3
  165. package/dest/common/packed_args_cache.d.ts +0 -28
  166. package/dest/common/packed_args_cache.d.ts.map +0 -1
  167. package/dest/common/packed_args_cache.js +0 -50
  168. package/src/common/packed_args_cache.ts +0 -55
@@ -0,0 +1,66 @@
1
+ import { type PublicKernelRequest, PublicKernelType, type Tx } from '@aztec/circuit-types';
2
+ import {
3
+ type GlobalVariables,
4
+ type Header,
5
+ type Proof,
6
+ type PublicKernelCircuitPublicInputs,
7
+ } from '@aztec/circuits.js';
8
+ import { type PublicExecutor, type PublicStateDB } from '@aztec/simulator';
9
+ import { type MerkleTreeOperations } from '@aztec/world-state';
10
+
11
+ import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
12
+ import { type ContractsDataSourcePublicDB } from './public_executor.js';
13
+ import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js';
14
+
15
+ /**
16
+ * The phase manager responsible for performing the fee preparation phase.
17
+ */
18
+ export class SetupPhaseManager extends AbstractPhaseManager {
19
+ constructor(
20
+ protected db: MerkleTreeOperations,
21
+ protected publicExecutor: PublicExecutor,
22
+ protected publicKernel: PublicKernelCircuitSimulator,
23
+ protected globalVariables: GlobalVariables,
24
+ protected historicalHeader: Header,
25
+ protected publicContractsDB: ContractsDataSourcePublicDB,
26
+ protected publicStateDB: PublicStateDB,
27
+ public phase: PublicKernelPhase = PublicKernelPhase.SETUP,
28
+ ) {
29
+ super(db, publicExecutor, publicKernel, globalVariables, historicalHeader, phase);
30
+ }
31
+
32
+ override async handle(
33
+ tx: Tx,
34
+ previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
35
+ previousPublicKernelProof: Proof,
36
+ ) {
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
+ );
46
+ tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
47
+ await this.publicStateDB.checkpoint();
48
+
49
+ // Return a list of setup proving requests
50
+ const kernelRequests = kernelInputs.map(input => {
51
+ const request: PublicKernelRequest = {
52
+ type: PublicKernelType.SETUP,
53
+ inputs: input,
54
+ };
55
+ return request;
56
+ });
57
+ return {
58
+ kernelRequests,
59
+ kernelInputs,
60
+ publicKernelOutput,
61
+ publicKernelProof,
62
+ revertReason,
63
+ returnValues: undefined,
64
+ };
65
+ }
66
+ }
@@ -0,0 +1,120 @@
1
+ import { type PublicKernelRequest, PublicKernelType, type Tx } from '@aztec/circuit-types';
2
+ import {
3
+ type Fr,
4
+ type GlobalVariables,
5
+ type Header,
6
+ type KernelCircuitPublicInputs,
7
+ MAX_NEW_NOTE_HASHES_PER_TX,
8
+ type Proof,
9
+ type PublicKernelCircuitPublicInputs,
10
+ PublicKernelTailCircuitPrivateInputs,
11
+ type SideEffect,
12
+ makeEmptyProof,
13
+ mergeAccumulatedData,
14
+ sortByCounter,
15
+ } from '@aztec/circuits.js';
16
+ import { type Tuple } from '@aztec/foundation/serialize';
17
+ import { type PublicExecutor, type PublicStateDB } from '@aztec/simulator';
18
+ import { type MerkleTreeOperations } from '@aztec/world-state';
19
+
20
+ import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
21
+ import { type ContractsDataSourcePublicDB } from './public_executor.js';
22
+ import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js';
23
+
24
+ export class TailPhaseManager extends AbstractPhaseManager {
25
+ constructor(
26
+ protected db: MerkleTreeOperations,
27
+ protected publicExecutor: PublicExecutor,
28
+ protected publicKernel: PublicKernelCircuitSimulator,
29
+ protected globalVariables: GlobalVariables,
30
+ protected historicalHeader: Header,
31
+ protected publicContractsDB: ContractsDataSourcePublicDB,
32
+ protected publicStateDB: PublicStateDB,
33
+ public readonly phase: PublicKernelPhase = PublicKernelPhase.TAIL,
34
+ ) {
35
+ super(db, publicExecutor, publicKernel, globalVariables, historicalHeader, phase);
36
+ }
37
+
38
+ async handle(tx: Tx, previousPublicKernelOutput: PublicKernelCircuitPublicInputs, previousPublicKernelProof: Proof) {
39
+ this.log.verbose(`Processing tx ${tx.getTxHash()}`);
40
+ const [inputs, finalKernelOutput] = await this.runTailKernelCircuit(
41
+ previousPublicKernelOutput,
42
+ previousPublicKernelProof,
43
+ ).catch(
44
+ // the abstract phase manager throws if simulation gives error in non-revertible phase
45
+ async err => {
46
+ await this.publicStateDB.rollbackToCommit();
47
+ throw err;
48
+ },
49
+ );
50
+
51
+ // commit the state updates from this transaction
52
+ await this.publicStateDB.commit();
53
+
54
+ // Return a tail proving request
55
+ const request: PublicKernelRequest = {
56
+ type: PublicKernelType.TAIL,
57
+ inputs: inputs,
58
+ };
59
+
60
+ return {
61
+ kernelRequests: [request],
62
+ publicKernelOutput: previousPublicKernelOutput,
63
+ finalKernelOutput,
64
+ publicKernelProof: makeEmptyProof(),
65
+ revertReason: undefined,
66
+ returnValues: undefined,
67
+ };
68
+ }
69
+
70
+ private async runTailKernelCircuit(
71
+ previousOutput: PublicKernelCircuitPublicInputs,
72
+ previousProof: Proof,
73
+ ): Promise<[PublicKernelTailCircuitPrivateInputs, KernelCircuitPublicInputs]> {
74
+ const [inputs, output] = await this.simulate(previousOutput, previousProof);
75
+
76
+ // Temporary hack. Should sort them in the tail circuit.
77
+ const noteHashes = mergeAccumulatedData(
78
+ MAX_NEW_NOTE_HASHES_PER_TX,
79
+ previousOutput.endNonRevertibleData.newNoteHashes,
80
+ previousOutput.end.newNoteHashes,
81
+ );
82
+ output.end.newNoteHashes = this.sortNoteHashes<typeof MAX_NEW_NOTE_HASHES_PER_TX>(noteHashes);
83
+
84
+ return [inputs, output];
85
+ }
86
+
87
+ private async simulate(
88
+ previousOutput: PublicKernelCircuitPublicInputs,
89
+ previousProof: Proof,
90
+ ): Promise<[PublicKernelTailCircuitPrivateInputs, KernelCircuitPublicInputs]> {
91
+ const previousKernel = this.getPreviousKernelData(previousOutput, previousProof);
92
+
93
+ const { validationRequests, endNonRevertibleData, end } = previousOutput;
94
+ const nullifierReadRequestHints = await this.hintsBuilder.getNullifierReadRequestHints(
95
+ validationRequests.nullifierReadRequests,
96
+ endNonRevertibleData.newNullifiers,
97
+ end.newNullifiers,
98
+ );
99
+ const nullifierNonExistentReadRequestHints = await this.hintsBuilder.getNullifierNonExistentReadRequestHints(
100
+ validationRequests.nullifierNonExistentReadRequests,
101
+ endNonRevertibleData.newNullifiers,
102
+ end.newNullifiers,
103
+ );
104
+
105
+ // We take a deep copy (clone) of these to pass to the prover
106
+ const inputs = new PublicKernelTailCircuitPrivateInputs(
107
+ previousKernel,
108
+ nullifierReadRequestHints,
109
+ nullifierNonExistentReadRequestHints,
110
+ );
111
+ return [inputs.clone(), await this.publicKernel.publicKernelCircuitTail(inputs)];
112
+ }
113
+
114
+ private sortNoteHashes<N extends number>(noteHashes: Tuple<SideEffect, N>): Tuple<Fr, N> {
115
+ return sortByCounter(noteHashes.map(n => ({ ...n, counter: n.counter.toNumber() }))).map(n => n.value) as Tuple<
116
+ Fr,
117
+ N
118
+ >;
119
+ }
120
+ }
@@ -0,0 +1,66 @@
1
+ import { type PublicKernelRequest, PublicKernelType, type Tx } from '@aztec/circuit-types';
2
+ import {
3
+ type GlobalVariables,
4
+ type Header,
5
+ type Proof,
6
+ type PublicKernelCircuitPublicInputs,
7
+ } from '@aztec/circuits.js';
8
+ import { type PublicExecutor, type PublicStateDB } from '@aztec/simulator';
9
+ import { type MerkleTreeOperations } from '@aztec/world-state';
10
+
11
+ import { AbstractPhaseManager, PublicKernelPhase } from './abstract_phase_manager.js';
12
+ import { type ContractsDataSourcePublicDB } from './public_executor.js';
13
+ import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js';
14
+
15
+ /**
16
+ * The phase manager responsible for performing the fee preparation phase.
17
+ */
18
+ export class TeardownPhaseManager extends AbstractPhaseManager {
19
+ constructor(
20
+ protected db: MerkleTreeOperations,
21
+ protected publicExecutor: PublicExecutor,
22
+ protected publicKernel: PublicKernelCircuitSimulator,
23
+ protected globalVariables: GlobalVariables,
24
+ protected historicalHeader: Header,
25
+ protected publicContractsDB: ContractsDataSourcePublicDB,
26
+ protected publicStateDB: PublicStateDB,
27
+ public phase: PublicKernelPhase = PublicKernelPhase.TEARDOWN,
28
+ ) {
29
+ super(db, publicExecutor, publicKernel, globalVariables, historicalHeader, phase);
30
+ }
31
+
32
+ override async handle(
33
+ tx: Tx,
34
+ previousPublicKernelOutput: PublicKernelCircuitPublicInputs,
35
+ previousPublicKernelProof: Proof,
36
+ ) {
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
+ );
46
+ tx.unencryptedLogs.addFunctionLogs(newUnencryptedFunctionLogs);
47
+ await this.publicStateDB.checkpoint();
48
+
49
+ // Return a list of teardown proving requests
50
+ const kernelRequests = kernelInputs.map(input => {
51
+ const request: PublicKernelRequest = {
52
+ type: PublicKernelType.TEARDOWN,
53
+ inputs: input,
54
+ };
55
+ return request;
56
+ });
57
+ return {
58
+ kernelRequests,
59
+ kernelInputs,
60
+ publicKernelOutput,
61
+ publicKernelProof,
62
+ revertReason,
63
+ returnValues: undefined,
64
+ };
65
+ }
66
+ }
@@ -5,6 +5,7 @@ import {
5
5
  ContractStorageRead,
6
6
  ContractStorageUpdateRequest,
7
7
  FunctionData,
8
+ Gas,
8
9
  type GlobalVariables,
9
10
  type Header,
10
11
  L2ToL1Message,
@@ -16,11 +17,12 @@ import { Fr } from '@aztec/foundation/fields';
16
17
 
17
18
  import { type AvmContext } from '../avm/avm_context.js';
18
19
  import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
20
+ import { type AvmMachineState } from '../avm/avm_machine_state.js';
19
21
  import { AvmContractCallResults } from '../avm/avm_message_call_result.js';
20
22
  import { type JournalData } from '../avm/journal/journal.js';
21
23
  import { Mov } from '../avm/opcodes/memory.js';
22
24
  import { createSimulationError } from '../common/errors.js';
23
- import { PackedArgsCache, SideEffectCounter } from '../index.js';
25
+ import { PackedValuesCache, SideEffectCounter } from '../index.js';
24
26
  import { type PublicExecution, type PublicExecutionResult } from './execution.js';
25
27
  import { PublicExecutionContext } from './public_execution_context.js';
26
28
 
@@ -42,15 +44,17 @@ export function createAvmExecutionEnvironment(
42
44
  current.callContext.msgSender, // TODO: origin is not available
43
45
  current.callContext.msgSender,
44
46
  current.callContext.portalContractAddress,
45
- /*feePerL1Gas=*/ Fr.zero(),
46
- /*feePerL2Gas=*/ Fr.zero(),
47
- /*feePerDaGas=*/ Fr.zero(),
47
+ globalVariables.gasFees.feePerL1Gas,
48
+ globalVariables.gasFees.feePerL2Gas,
49
+ globalVariables.gasFees.feePerDaGas,
48
50
  /*contractCallDepth=*/ Fr.zero(),
49
51
  header,
50
52
  globalVariables,
51
53
  current.callContext.isStaticCall,
52
54
  current.callContext.isDelegateCall,
53
55
  current.args,
56
+ current.callContext.gasSettings,
57
+ current.callContext.transactionFee,
54
58
  current.functionData.selector,
55
59
  );
56
60
  }
@@ -62,9 +66,12 @@ export function createPublicExecutionContext(avmContext: AvmContext, calldata: F
62
66
  storageContractAddress: avmContext.environment.storageAddress,
63
67
  portalContractAddress: avmContext.environment.portal,
64
68
  functionSelector: avmContext.environment.temporaryFunctionSelector,
69
+ gasLeft: Gas.from(avmContext.machineState.gasLeft),
65
70
  isDelegateCall: avmContext.environment.isDelegateCall,
66
71
  isStaticCall: avmContext.environment.isStaticCall,
67
72
  sideEffectCounter: sideEffectCounter,
73
+ gasSettings: avmContext.environment.gasSettings,
74
+ transactionFee: avmContext.environment.transactionFee,
68
75
  });
69
76
  const functionData = new FunctionData(avmContext.environment.temporaryFunctionSelector, /*isPrivate=*/ false);
70
77
  const execution: PublicExecution = {
@@ -73,7 +80,7 @@ export function createPublicExecutionContext(avmContext: AvmContext, calldata: F
73
80
  args: calldata,
74
81
  functionData,
75
82
  };
76
- const packedArgs = PackedArgsCache.create([]);
83
+ const packedArgs = PackedValuesCache.create([]);
77
84
 
78
85
  const context = new PublicExecutionContext(
79
86
  execution,
@@ -101,6 +108,7 @@ export async function convertAvmResults(
101
108
  executionContext: PublicExecutionContext,
102
109
  newWorldState: JournalData,
103
110
  result: AvmContractCallResults,
111
+ endMachineState: AvmMachineState,
104
112
  ): Promise<PublicExecutionResult> {
105
113
  const execution = executionContext.execution;
106
114
 
@@ -162,6 +170,7 @@ export async function convertAvmResults(
162
170
  unencryptedLogs,
163
171
  reverted: result.reverted,
164
172
  revertReason: result.revertReason ? createSimulationError(result.revertReason) : undefined,
173
+ gasLeft: endMachineState.gasLeft,
165
174
  };
166
175
  }
167
176
 
@@ -0,0 +1,31 @@
1
+ import { type Tx } from '@aztec/circuit-types';
2
+ import { CallRequest } from '@aztec/circuits.js';
3
+
4
+ /**
5
+ * Looks at the side effects of a transaction and returns the highest counter
6
+ * @param tx - A transaction
7
+ * @returns The highest side effect counter in the transaction so far
8
+ */
9
+ export function lastSideEffectCounter(tx: Tx): number {
10
+ const data = tx.data.forPublic!;
11
+ const sideEffectCounters = [
12
+ ...data.endNonRevertibleData.newNoteHashes,
13
+ ...data.endNonRevertibleData.newNullifiers,
14
+ ...data.endNonRevertibleData.publicCallStack,
15
+ ...data.end.newNoteHashes,
16
+ ...data.end.newNullifiers,
17
+ ...data.end.publicCallStack,
18
+ ];
19
+
20
+ let max = 0;
21
+ for (const sideEffect of sideEffectCounters) {
22
+ if (sideEffect instanceof CallRequest) {
23
+ // look at both start and end counters because for enqueued public calls start > 0 while end === 0
24
+ max = Math.max(max, sideEffect.startSideEffectCounter.toNumber(), sideEffect.endSideEffectCounter.toNumber());
25
+ } else {
26
+ max = Math.max(max, sideEffect.counter.toNumber());
27
+ }
28
+ }
29
+
30
+ return max;
31
+ }
@@ -1,4 +1,6 @@
1
1
  import { randomBytes } from '@aztec/foundation/crypto';
2
+ import { createDebugLogger } from '@aztec/foundation/log';
3
+ import { Timer } from '@aztec/foundation/timer';
2
4
  import { type NoirCompiledCircuit } from '@aztec/types/noir';
3
5
 
4
6
  import { type WitnessMap } from '@noir-lang/types';
@@ -7,6 +9,26 @@ import fs from 'fs/promises';
7
9
 
8
10
  import { type SimulationProvider } from './simulation_provider.js';
9
11
 
12
+ const logger = createDebugLogger('aztec:acvm-native');
13
+
14
+ export enum ACVM_RESULT {
15
+ SUCCESS,
16
+ FAILURE,
17
+ }
18
+
19
+ export type ACVMSuccess = {
20
+ status: ACVM_RESULT.SUCCESS;
21
+ duration: number;
22
+ witness: Map<number, string>;
23
+ };
24
+
25
+ export type ACVMFailure = {
26
+ status: ACVM_RESULT.FAILURE;
27
+ reason: string;
28
+ };
29
+
30
+ export type ACVMResult = ACVMSuccess | ACVMFailure;
31
+
10
32
  /**
11
33
  * Parses a TOML format witness map string into a Map structure
12
34
  * @param outputString - The witness map in TOML format
@@ -29,7 +51,8 @@ function parseIntoWitnessMap(outputString: string) {
29
51
  * @param inputWitness - The circuit's input witness
30
52
  * @param bytecode - The circuit bytecode
31
53
  * @param workingDirectory - A directory to use for temporary files by the ACVM
32
- * @param pathToAcvm - The path to the ACVm binary
54
+ * @param pathToAcvm - The path to the ACVM binary
55
+ * @param outputFilename - If specified, the output will be stored as a file, encoded using Bincode
33
56
  * @returns The completed partial witness outputted from the circuit
34
57
  */
35
58
  export async function executeNativeCircuit(
@@ -37,7 +60,8 @@ export async function executeNativeCircuit(
37
60
  bytecode: Buffer,
38
61
  workingDirectory: string,
39
62
  pathToAcvm: string,
40
- ) {
63
+ outputFilename?: string,
64
+ ): Promise<ACVMResult> {
41
65
  const bytecodeFilename = 'bytecode';
42
66
  const witnessFilename = 'input_witness.toml';
43
67
 
@@ -47,55 +71,69 @@ export async function executeNativeCircuit(
47
71
  witnessMap = witnessMap.concat(`${key} = '${value}'\n`);
48
72
  });
49
73
 
50
- // In case the directory is still around from some time previously, remove it
51
- await fs.rm(workingDirectory, { recursive: true, force: true });
52
- // Create the new working directory
53
- await fs.mkdir(workingDirectory, { recursive: true });
54
- // Write the bytecode and input witness to the working directory
55
- await fs.writeFile(`${workingDirectory}/${bytecodeFilename}`, bytecode);
56
- await fs.writeFile(`${workingDirectory}/${witnessFilename}`, witnessMap);
57
-
58
- // Execute the ACVM using the given args
59
- const args = [
60
- `execute`,
61
- `--working-directory`,
62
- `${workingDirectory}`,
63
- `--bytecode`,
64
- `${bytecodeFilename}`,
65
- `--input-witness`,
66
- `${witnessFilename}`,
67
- `--print`,
68
- ];
69
- const processPromise = new Promise<string>((resolve, reject) => {
70
- let outputWitness = Buffer.alloc(0);
71
- let errorBuffer = Buffer.alloc(0);
72
- const acvm = proc.spawn(pathToAcvm, args);
73
- acvm.stdout.on('data', data => {
74
- outputWitness = Buffer.concat([outputWitness, data]);
75
- });
76
- acvm.stderr.on('data', data => {
77
- errorBuffer = Buffer.concat([errorBuffer, data]);
78
- });
79
- acvm.on('close', code => {
80
- if (code === 0) {
81
- resolve(outputWitness.toString('utf-8'));
82
- } else {
83
- reject(errorBuffer.toString('utf-8'));
84
- }
85
- });
86
- });
74
+ try {
75
+ // Check that the directory exists
76
+ await fs.access(workingDirectory);
77
+ } catch (error) {
78
+ return { status: ACVM_RESULT.FAILURE, reason: `Working directory ${workingDirectory} does not exist` };
79
+ }
87
80
 
88
81
  try {
82
+ // Write the bytecode and input witness to the working directory
83
+ await fs.writeFile(`${workingDirectory}/${bytecodeFilename}`, bytecode);
84
+ await fs.writeFile(`${workingDirectory}/${witnessFilename}`, witnessMap);
85
+
86
+ // Execute the ACVM using the given args
87
+ const args = [
88
+ `execute`,
89
+ `--working-directory`,
90
+ `${workingDirectory}`,
91
+ `--bytecode`,
92
+ `${bytecodeFilename}`,
93
+ `--input-witness`,
94
+ `${witnessFilename}`,
95
+ '--print',
96
+ '--output-witness',
97
+ 'output-witness',
98
+ ];
99
+
100
+ logger.debug(`Calling ACVM with ${args.join(' ')}`);
101
+
102
+ const processPromise = new Promise<string>((resolve, reject) => {
103
+ let outputWitness = Buffer.alloc(0);
104
+ let errorBuffer = Buffer.alloc(0);
105
+ const acvm = proc.spawn(pathToAcvm, args);
106
+ acvm.stdout.on('data', data => {
107
+ outputWitness = Buffer.concat([outputWitness, data]);
108
+ });
109
+ acvm.stderr.on('data', data => {
110
+ errorBuffer = Buffer.concat([errorBuffer, data]);
111
+ });
112
+ acvm.on('close', code => {
113
+ if (code === 0) {
114
+ resolve(outputWitness.toString('utf-8'));
115
+ } else {
116
+ logger.error(`From ACVM: ${errorBuffer.toString('utf-8')}`);
117
+ reject(errorBuffer.toString('utf-8'));
118
+ }
119
+ });
120
+ });
121
+
122
+ const duration = new Timer();
89
123
  const output = await processPromise;
90
- return parseIntoWitnessMap(output);
91
- } finally {
92
- // Clean up the working directory before we leave
93
- await fs.rm(workingDirectory, { recursive: true, force: true });
124
+ if (outputFilename) {
125
+ const outputWitnessFileName = `${workingDirectory}/output-witness.gz`;
126
+ await fs.copyFile(outputWitnessFileName, outputFilename);
127
+ }
128
+ const witness = parseIntoWitnessMap(output);
129
+ return { status: ACVM_RESULT.SUCCESS, witness, duration: duration.ms() };
130
+ } catch (error) {
131
+ return { status: ACVM_RESULT.FAILURE, reason: `${error}` };
94
132
  }
95
133
  }
96
134
 
97
135
  export class NativeACVMSimulator implements SimulationProvider {
98
- constructor(private workingDirectory: string, private pathToAcvm: string) {}
136
+ constructor(private workingDirectory: string, private pathToAcvm: string, private witnessFilename?: string) {}
99
137
  async simulateCircuit(input: WitnessMap, compiledCircuit: NoirCompiledCircuit): Promise<WitnessMap> {
100
138
  // Execute the circuit on those initial witness values
101
139
 
@@ -103,10 +141,19 @@ export class NativeACVMSimulator implements SimulationProvider {
103
141
  const decodedBytecode = Buffer.from(compiledCircuit.bytecode, 'base64');
104
142
 
105
143
  // Provide a unique working directory so we don't get clashes with parallel executions
106
- const directory = `${this.workingDirectory}/${randomBytes(32).toString('hex')}`;
144
+ const directory = `${this.workingDirectory}/${randomBytes(8).toString('hex')}`;
145
+
146
+ await fs.mkdir(directory, { recursive: true });
147
+
107
148
  // Execute the circuit
108
- const _witnessMap = await executeNativeCircuit(input, decodedBytecode, directory, this.pathToAcvm);
149
+ const result = await executeNativeCircuit(input, decodedBytecode, directory, this.pathToAcvm, this.witnessFilename);
150
+
151
+ await fs.rm(directory, { force: true, recursive: true });
152
+
153
+ if (result.status == ACVM_RESULT.FAILURE) {
154
+ throw new Error(`Failed to generate witness: ${result.reason}`);
155
+ }
109
156
 
110
- return _witnessMap;
157
+ return result.witness;
111
158
  }
112
159
  }
@@ -1,3 +1,4 @@
1
+ import { foreignCallHandler } from '@aztec/noir-protocol-circuits-types';
1
2
  import { type NoirCompiledCircuit } from '@aztec/types/noir';
2
3
 
3
4
  import {
@@ -26,9 +27,12 @@ export class WASMSimulator implements SimulationProvider {
26
27
  const decodedBytecode = Buffer.from(compiledCircuit.bytecode, 'base64');
27
28
  //
28
29
  // Execute the circuit
29
- const _witnessMap = await executeCircuitWithBlackBoxSolver(await getSolver(), decodedBytecode, input, () => {
30
- throw Error('unexpected oracle during execution');
31
- });
30
+ const _witnessMap = await executeCircuitWithBlackBoxSolver(
31
+ await getSolver(),
32
+ decodedBytecode,
33
+ input,
34
+ foreignCallHandler, // handle calls to debug_log
35
+ );
32
36
 
33
37
  return _witnessMap;
34
38
  }
@@ -1,28 +0,0 @@
1
- import { PackedArguments } from '@aztec/circuit-types';
2
- import { Fr } from '@aztec/circuits.js';
3
- /**
4
- * A cache for packed arguments during transaction execution.
5
- */
6
- export declare class PackedArgsCache {
7
- private cache;
8
- constructor(initialArguments?: PackedArguments[]);
9
- /**
10
- * Creates a new packed arguments cache.
11
- * @param initialArguments - The initial arguments to add to the cache.
12
- * @returns The new packed arguments cache.
13
- */
14
- static create(initialArguments?: PackedArguments[]): PackedArgsCache;
15
- /**
16
- * Unpacks packed arguments.
17
- * @param hash - The hash of the packed arguments.
18
- * @returns The unpacked arguments.
19
- */
20
- unpack(hash: Fr): Fr[];
21
- /**
22
- * Packs arguments.
23
- * @param args - The arguments to pack.
24
- * @returns The hash of the packed arguments.
25
- */
26
- pack(args: Fr[]): Fr;
27
- }
28
- //# sourceMappingURL=packed_args_cache.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"packed_args_cache.d.ts","sourceRoot":"","sources":["../../src/common/packed_args_cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAExC;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAoB;gBAErB,gBAAgB,GAAE,eAAe,EAAO;IAOpD;;;;OAIG;WACW,MAAM,CAAC,gBAAgB,GAAE,eAAe,EAAO;IAI7D;;;;OAIG;IACI,MAAM,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE;IAW7B;;;;OAIG;IACI,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE;CAQvB"}
@@ -1,50 +0,0 @@
1
- import { PackedArguments } from '@aztec/circuit-types';
2
- import { Fr } from '@aztec/circuits.js';
3
- /**
4
- * A cache for packed arguments during transaction execution.
5
- */
6
- export class PackedArgsCache {
7
- constructor(initialArguments = []) {
8
- this.cache = new Map();
9
- for (const initialArg of initialArguments) {
10
- this.cache.set(initialArg.hash.toBigInt(), initialArg.args);
11
- }
12
- }
13
- /**
14
- * Creates a new packed arguments cache.
15
- * @param initialArguments - The initial arguments to add to the cache.
16
- * @returns The new packed arguments cache.
17
- */
18
- static create(initialArguments = []) {
19
- return new PackedArgsCache(initialArguments);
20
- }
21
- /**
22
- * Unpacks packed arguments.
23
- * @param hash - The hash of the packed arguments.
24
- * @returns The unpacked arguments.
25
- */
26
- unpack(hash) {
27
- if (hash.equals(Fr.ZERO)) {
28
- return [];
29
- }
30
- const packedArgs = this.cache.get(hash.value);
31
- if (!packedArgs) {
32
- throw new Error(`Packed arguments for hash ${hash.toString()} not found in cache`);
33
- }
34
- return packedArgs;
35
- }
36
- /**
37
- * Packs arguments.
38
- * @param args - The arguments to pack.
39
- * @returns The hash of the packed arguments.
40
- */
41
- pack(args) {
42
- if (args.length === 0) {
43
- return Fr.ZERO;
44
- }
45
- const packedArguments = PackedArguments.fromArgs(args);
46
- this.cache.set(packedArguments.hash.value, packedArguments.args);
47
- return packedArguments.hash;
48
- }
49
- }
50
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFja2VkX2FyZ3NfY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbW9uL3BhY2tlZF9hcmdzX2NhY2hlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFeEM7O0dBRUc7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQUcxQixZQUFZLG1CQUFzQyxFQUFFO1FBQ2xELElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUN2QixLQUFLLE1BQU0sVUFBVSxJQUFJLGdCQUFnQixFQUFFLENBQUM7WUFDMUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDOUQsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksTUFBTSxDQUFDLE1BQU0sQ0FBQyxtQkFBc0MsRUFBRTtRQUMzRCxPQUFPLElBQUksZUFBZSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsSUFBUTtRQUNwQixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDekIsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixJQUFJLENBQUMsUUFBUSxFQUFFLHFCQUFxQixDQUFDLENBQUM7UUFDckYsQ0FBQztRQUNELE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ksSUFBSSxDQUFDLElBQVU7UUFDcEIsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3RCLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQztRQUNqQixDQUFDO1FBQ0QsTUFBTSxlQUFlLEdBQUcsZUFBZSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2RCxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakUsT0FBTyxlQUFlLENBQUMsSUFBSSxDQUFDO0lBQzlCLENBQUM7Q0FDRiJ9