@aztec/simulator 0.62.0 → 0.63.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 (216) hide show
  1. package/dest/acvm/acvm.d.ts +2 -16
  2. package/dest/acvm/acvm.d.ts.map +1 -1
  3. package/dest/acvm/acvm.js +2 -70
  4. package/dest/acvm/oracle/oracle.d.ts +4 -4
  5. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/oracle.js +10 -11
  7. package/dest/acvm/oracle/typed_oracle.d.ts +5 -5
  8. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  9. package/dest/acvm/oracle/typed_oracle.js +8 -8
  10. package/dest/avm/avm_gas.d.ts.map +1 -1
  11. package/dest/avm/avm_gas.js +2 -1
  12. package/dest/avm/avm_machine_state.d.ts +27 -8
  13. package/dest/avm/avm_machine_state.d.ts.map +1 -1
  14. package/dest/avm/avm_machine_state.js +6 -10
  15. package/dest/avm/avm_memory_types.d.ts +8 -0
  16. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  17. package/dest/avm/avm_memory_types.js +5 -1
  18. package/dest/avm/avm_simulator.d.ts +2 -19
  19. package/dest/avm/avm_simulator.d.ts.map +1 -1
  20. package/dest/avm/avm_simulator.js +12 -14
  21. package/dest/avm/avm_tree.d.ts +249 -0
  22. package/dest/avm/avm_tree.d.ts.map +1 -0
  23. package/dest/avm/avm_tree.js +637 -0
  24. package/dest/avm/errors.d.ts +4 -17
  25. package/dest/avm/errors.d.ts.map +1 -1
  26. package/dest/avm/errors.js +21 -50
  27. package/dest/avm/fixtures/index.d.ts +7 -2
  28. package/dest/avm/fixtures/index.d.ts.map +1 -1
  29. package/dest/avm/fixtures/index.js +12 -12
  30. package/dest/avm/index.d.ts +1 -0
  31. package/dest/avm/index.d.ts.map +1 -1
  32. package/dest/avm/index.js +2 -1
  33. package/dest/avm/journal/journal.d.ts +43 -24
  34. package/dest/avm/journal/journal.d.ts.map +1 -1
  35. package/dest/avm/journal/journal.js +172 -39
  36. package/dest/avm/journal/nullifiers.d.ts +5 -4
  37. package/dest/avm/journal/nullifiers.d.ts.map +1 -1
  38. package/dest/avm/journal/nullifiers.js +2 -3
  39. package/dest/avm/journal/public_storage.d.ts +6 -5
  40. package/dest/avm/journal/public_storage.d.ts.map +1 -1
  41. package/dest/avm/journal/public_storage.js +1 -1
  42. package/dest/avm/opcodes/accrued_substate.d.ts.map +1 -1
  43. package/dest/avm/opcodes/accrued_substate.js +4 -10
  44. package/dest/avm/opcodes/arithmetic.d.ts +4 -1
  45. package/dest/avm/opcodes/arithmetic.d.ts.map +1 -1
  46. package/dest/avm/opcodes/arithmetic.js +18 -4
  47. package/dest/avm/opcodes/bitwise.d.ts.map +1 -1
  48. package/dest/avm/opcodes/bitwise.js +1 -3
  49. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  50. package/dest/avm/opcodes/comparators.js +1 -2
  51. package/dest/avm/opcodes/contract.d.ts.map +1 -1
  52. package/dest/avm/opcodes/contract.js +2 -3
  53. package/dest/avm/opcodes/control_flow.d.ts +4 -0
  54. package/dest/avm/opcodes/control_flow.d.ts.map +1 -1
  55. package/dest/avm/opcodes/control_flow.js +21 -6
  56. package/dest/avm/opcodes/conversion.d.ts.map +1 -1
  57. package/dest/avm/opcodes/conversion.js +1 -2
  58. package/dest/avm/opcodes/ec_add.d.ts.map +1 -1
  59. package/dest/avm/opcodes/ec_add.js +5 -11
  60. package/dest/avm/opcodes/environment_getters.d.ts.map +1 -1
  61. package/dest/avm/opcodes/environment_getters.js +1 -2
  62. package/dest/avm/opcodes/external_calls.d.ts +4 -2
  63. package/dest/avm/opcodes/external_calls.d.ts.map +1 -1
  64. package/dest/avm/opcodes/external_calls.js +38 -22
  65. package/dest/avm/opcodes/hashing.d.ts.map +1 -1
  66. package/dest/avm/opcodes/hashing.js +1 -4
  67. package/dest/avm/opcodes/instruction.d.ts +4 -0
  68. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  69. package/dest/avm/opcodes/instruction.js +7 -1
  70. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  71. package/dest/avm/opcodes/memory.js +1 -7
  72. package/dest/avm/opcodes/misc.js +3 -3
  73. package/dest/avm/opcodes/multi_scalar_mul.d.ts.map +1 -1
  74. package/dest/avm/opcodes/multi_scalar_mul.js +6 -5
  75. package/dest/avm/opcodes/storage.d.ts.map +1 -1
  76. package/dest/avm/opcodes/storage.js +2 -4
  77. package/dest/avm/serialization/bytecode_serialization.d.ts +1 -6
  78. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  79. package/dest/avm/serialization/bytecode_serialization.js +24 -20
  80. package/dest/client/client_execution_context.d.ts +7 -11
  81. package/dest/client/client_execution_context.d.ts.map +1 -1
  82. package/dest/client/client_execution_context.js +18 -20
  83. package/dest/client/db_oracle.d.ts +17 -10
  84. package/dest/client/db_oracle.d.ts.map +1 -1
  85. package/dest/client/db_oracle.js +1 -1
  86. package/dest/client/private_execution.d.ts.map +1 -1
  87. package/dest/client/private_execution.js +5 -4
  88. package/dest/client/unconstrained_execution.d.ts.map +1 -1
  89. package/dest/client/unconstrained_execution.js +3 -2
  90. package/dest/client/view_data_oracle.d.ts +6 -12
  91. package/dest/client/view_data_oracle.d.ts.map +1 -1
  92. package/dest/client/view_data_oracle.js +10 -12
  93. package/dest/common/errors.d.ts +15 -2
  94. package/dest/common/errors.d.ts.map +1 -1
  95. package/dest/common/errors.js +85 -4
  96. package/dest/mocks/fixtures.d.ts +9 -28
  97. package/dest/mocks/fixtures.d.ts.map +1 -1
  98. package/dest/mocks/fixtures.js +12 -57
  99. package/dest/public/dual_side_effect_trace.d.ts +34 -26
  100. package/dest/public/dual_side_effect_trace.d.ts.map +1 -1
  101. package/dest/public/dual_side_effect_trace.js +48 -36
  102. package/dest/public/enqueued_call_side_effect_trace.d.ts +96 -33
  103. package/dest/public/enqueued_call_side_effect_trace.d.ts.map +1 -1
  104. package/dest/public/enqueued_call_side_effect_trace.js +212 -138
  105. package/dest/public/execution.d.ts +50 -17
  106. package/dest/public/execution.d.ts.map +1 -1
  107. package/dest/public/execution.js +1 -29
  108. package/dest/public/executor.d.ts +28 -11
  109. package/dest/public/executor.d.ts.map +1 -1
  110. package/dest/public/executor.js +33 -33
  111. package/dest/public/index.d.ts +4 -5
  112. package/dest/public/index.d.ts.map +1 -1
  113. package/dest/public/index.js +4 -5
  114. package/dest/public/public_db_sources.d.ts +1 -0
  115. package/dest/public/public_db_sources.d.ts.map +1 -1
  116. package/dest/public/public_db_sources.js +12 -5
  117. package/dest/public/public_processor.d.ts +7 -11
  118. package/dest/public/public_processor.d.ts.map +1 -1
  119. package/dest/public/public_processor.js +60 -42
  120. package/dest/public/public_processor_metrics.d.ts +3 -3
  121. package/dest/public/public_processor_metrics.d.ts.map +1 -1
  122. package/dest/public/public_processor_metrics.js +1 -1
  123. package/dest/public/public_tx_context.d.ts +130 -0
  124. package/dest/public/public_tx_context.d.ts.map +1 -0
  125. package/dest/public/public_tx_context.js +293 -0
  126. package/dest/public/public_tx_simulator.d.ts +36 -0
  127. package/dest/public/public_tx_simulator.d.ts.map +1 -0
  128. package/dest/public/public_tx_simulator.js +148 -0
  129. package/dest/public/side_effect_trace.d.ts +30 -15
  130. package/dest/public/side_effect_trace.d.ts.map +1 -1
  131. package/dest/public/side_effect_trace.js +70 -16
  132. package/dest/public/side_effect_trace_interface.d.ts +43 -12
  133. package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
  134. package/dest/public/transitional_adapters.d.ts +9 -0
  135. package/dest/public/transitional_adapters.d.ts.map +1 -0
  136. package/dest/public/transitional_adapters.js +127 -0
  137. package/dest/public/utils.d.ts +5 -0
  138. package/dest/public/utils.d.ts.map +1 -0
  139. package/dest/public/utils.js +30 -0
  140. package/package.json +12 -9
  141. package/src/acvm/acvm.ts +3 -94
  142. package/src/acvm/oracle/oracle.ts +9 -14
  143. package/src/acvm/oracle/typed_oracle.ts +8 -8
  144. package/src/avm/avm_gas.ts +1 -0
  145. package/src/avm/avm_machine_state.ts +28 -12
  146. package/src/avm/avm_memory_types.ts +5 -0
  147. package/src/avm/avm_simulator.ts +13 -16
  148. package/src/avm/avm_tree.ts +785 -0
  149. package/src/avm/errors.ts +25 -48
  150. package/src/avm/fixtures/index.ts +16 -12
  151. package/src/avm/index.ts +1 -0
  152. package/src/avm/journal/journal.ts +291 -52
  153. package/src/avm/journal/nullifiers.ts +7 -7
  154. package/src/avm/journal/public_storage.ts +5 -5
  155. package/src/avm/opcodes/accrued_substate.ts +3 -9
  156. package/src/avm/opcodes/arithmetic.ts +26 -4
  157. package/src/avm/opcodes/bitwise.ts +0 -2
  158. package/src/avm/opcodes/comparators.ts +0 -1
  159. package/src/avm/opcodes/contract.ts +1 -2
  160. package/src/avm/opcodes/control_flow.ts +24 -5
  161. package/src/avm/opcodes/conversion.ts +0 -1
  162. package/src/avm/opcodes/ec_add.ts +6 -9
  163. package/src/avm/opcodes/environment_getters.ts +0 -1
  164. package/src/avm/opcodes/external_calls.ts +39 -21
  165. package/src/avm/opcodes/hashing.ts +0 -3
  166. package/src/avm/opcodes/instruction.ts +7 -0
  167. package/src/avm/opcodes/memory.ts +0 -6
  168. package/src/avm/opcodes/misc.ts +2 -2
  169. package/src/avm/opcodes/multi_scalar_mul.ts +5 -4
  170. package/src/avm/opcodes/storage.ts +1 -3
  171. package/src/avm/serialization/bytecode_serialization.ts +31 -22
  172. package/src/client/client_execution_context.ts +22 -23
  173. package/src/client/db_oracle.ts +22 -11
  174. package/src/client/private_execution.ts +5 -4
  175. package/src/client/unconstrained_execution.ts +2 -1
  176. package/src/client/view_data_oracle.ts +14 -13
  177. package/src/common/errors.ts +119 -3
  178. package/src/mocks/fixtures.ts +15 -106
  179. package/src/public/dual_side_effect_trace.ts +138 -50
  180. package/src/public/enqueued_call_side_effect_trace.ts +352 -212
  181. package/src/public/execution.ts +58 -42
  182. package/src/public/executor.ts +52 -67
  183. package/src/public/index.ts +7 -5
  184. package/src/public/public_db_sources.ts +12 -4
  185. package/src/public/public_processor.ts +111 -73
  186. package/src/public/public_processor_metrics.ts +3 -3
  187. package/src/public/public_tx_context.ts +411 -0
  188. package/src/public/public_tx_simulator.ts +232 -0
  189. package/src/public/side_effect_trace.ts +154 -28
  190. package/src/public/side_effect_trace_interface.ts +92 -14
  191. package/src/public/transitional_adapters.ts +347 -0
  192. package/src/public/utils.ts +32 -0
  193. package/dest/public/enqueued_call_simulator.d.ts +0 -43
  194. package/dest/public/enqueued_call_simulator.d.ts.map +0 -1
  195. package/dest/public/enqueued_call_simulator.js +0 -156
  196. package/dest/public/enqueued_calls_processor.d.ts +0 -43
  197. package/dest/public/enqueued_calls_processor.d.ts.map +0 -1
  198. package/dest/public/enqueued_calls_processor.js +0 -209
  199. package/dest/public/hints_builder.d.ts +0 -29
  200. package/dest/public/hints_builder.d.ts.map +0 -1
  201. package/dest/public/hints_builder.js +0 -75
  202. package/dest/public/public_kernel.d.ts +0 -30
  203. package/dest/public/public_kernel.d.ts.map +0 -1
  204. package/dest/public/public_kernel.js +0 -67
  205. package/dest/public/public_kernel_circuit_simulator.d.ts +0 -25
  206. package/dest/public/public_kernel_circuit_simulator.d.ts.map +0 -1
  207. package/dest/public/public_kernel_circuit_simulator.js +0 -2
  208. package/dest/public/public_kernel_tail_simulator.d.ts +0 -15
  209. package/dest/public/public_kernel_tail_simulator.d.ts.map +0 -1
  210. package/dest/public/public_kernel_tail_simulator.js +0 -39
  211. package/src/public/enqueued_call_simulator.ts +0 -360
  212. package/src/public/enqueued_calls_processor.ts +0 -372
  213. package/src/public/hints_builder.ts +0 -168
  214. package/src/public/public_kernel.ts +0 -100
  215. package/src/public/public_kernel_circuit_simulator.ts +0 -32
  216. package/src/public/public_kernel_tail_simulator.ts +0 -97
@@ -1,80 +1,96 @@
1
- import { UnencryptedL2Log } from '@aztec/circuit-types';
1
+ import { UnencryptedFunctionL2Logs, UnencryptedL2Log } from '@aztec/circuit-types';
2
2
  import {
3
+ AvmAccumulatedData,
4
+ AvmAppendTreeHint,
5
+ AvmCircuitPublicInputs,
3
6
  AvmContractBytecodeHints,
4
7
  AvmContractInstanceHint,
8
+ AvmEnqueuedCallHint,
5
9
  AvmExecutionHints,
6
10
  AvmExternalCallHint,
7
11
  AvmKeyValueHint,
8
- AztecAddress,
9
- CallContext,
10
- type CombinedConstantData,
12
+ AvmNullifierReadTreeHint,
13
+ AvmNullifierWriteTreeHint,
14
+ AvmPublicDataReadTreeHint,
15
+ AvmPublicDataWriteTreeHint,
16
+ type AztecAddress,
11
17
  type ContractClassIdPreimage,
12
- ContractStorageRead,
13
- ContractStorageUpdateRequest,
14
18
  EthAddress,
15
19
  Gas,
20
+ type GasSettings,
21
+ type GlobalVariables,
22
+ L1_TO_L2_MSG_TREE_HEIGHT,
16
23
  L2ToL1Message,
17
24
  LogHash,
18
- MAX_ENCRYPTED_LOGS_PER_TX,
25
+ MAX_ENQUEUED_CALLS_PER_TX,
19
26
  MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX,
20
27
  MAX_L2_TO_L1_MSGS_PER_TX,
21
- MAX_NOTE_ENCRYPTED_LOGS_PER_TX,
22
28
  MAX_NOTE_HASHES_PER_TX,
23
29
  MAX_NOTE_HASH_READ_REQUESTS_PER_TX,
24
30
  MAX_NULLIFIERS_PER_TX,
25
31
  MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX,
26
32
  MAX_NULLIFIER_READ_REQUESTS_PER_TX,
27
- MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX,
28
33
  MAX_PUBLIC_DATA_READS_PER_TX,
29
34
  MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
30
35
  MAX_UNENCRYPTED_LOGS_PER_TX,
36
+ NOTE_HASH_TREE_HEIGHT,
37
+ NULLIFIER_TREE_HEIGHT,
31
38
  NoteHash,
32
39
  Nullifier,
33
- PublicAccumulatedData,
34
- PublicAccumulatedDataArrayLengths,
40
+ NullifierLeafPreimage,
41
+ PUBLIC_DATA_TREE_HEIGHT,
42
+ PrivateToAvmAccumulatedData,
43
+ PrivateToAvmAccumulatedDataArrayLengths,
35
44
  PublicCallRequest,
36
45
  PublicDataRead,
46
+ PublicDataTreeLeafPreimage,
37
47
  PublicDataUpdateRequest,
38
- PublicInnerCallRequest,
39
- PublicValidationRequestArrayLengths,
40
- PublicValidationRequests,
48
+ PublicDataWrite,
41
49
  ReadRequest,
42
- RollupValidationRequests,
43
50
  ScopedL2ToL1Message,
44
51
  ScopedLogHash,
45
- ScopedNoteHash,
46
- type ScopedNullifier,
47
- ScopedReadRequest,
52
+ type ScopedNoteHash,
53
+ type ScopedReadRequest,
48
54
  SerializableContractInstance,
49
55
  TreeLeafReadRequest,
50
- VMCircuitPublicInputs,
56
+ type TreeSnapshots,
51
57
  } from '@aztec/circuits.js';
52
- import { computeVarArgsHash } from '@aztec/circuits.js/hash';
53
- import { makeTuple } from '@aztec/foundation/array';
58
+ import { computePublicDataTreeLeafSlot, siloNullifier } from '@aztec/circuits.js/hash';
54
59
  import { padArrayEnd } from '@aztec/foundation/collection';
55
60
  import { Fr } from '@aztec/foundation/fields';
56
61
  import { createDebugLogger } from '@aztec/foundation/log';
57
62
 
63
+ import { assert } from 'console';
64
+
58
65
  import { type AvmContractCallResult } from '../avm/avm_contract_call_result.js';
59
66
  import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
67
+ import { createSimulationError } from '../common/errors.js';
68
+ import { type EnqueuedPublicCallExecutionResultWithSideEffects, type PublicFunctionCallResult } from './execution.js';
60
69
  import { SideEffectLimitReachedError } from './side_effect_errors.js';
61
70
  import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js';
62
71
 
72
+ const emptyPublicDataPath = () => new Array(PUBLIC_DATA_TREE_HEIGHT).fill(Fr.zero());
73
+ const emptyNoteHashPath = () => new Array(NOTE_HASH_TREE_HEIGHT).fill(Fr.zero());
74
+ const emptyNullifierPath = () => new Array(NULLIFIER_TREE_HEIGHT).fill(Fr.zero());
75
+ const emptyL1ToL2MessagePath = () => new Array(L1_TO_L2_MSG_TREE_HEIGHT).fill(Fr.zero());
76
+
63
77
  /**
64
78
  * A struct containing just the side effects as regular arrays
65
79
  * as opposed to "Tuple" arrays used by circuit public inputs.
66
80
  * This struct is helpful for testing and checking array lengths.
67
81
  **/
68
82
  export type SideEffects = {
69
- contractStorageReads: ContractStorageRead[];
70
- contractStorageUpdateRequests: ContractStorageUpdateRequest[];
83
+ enqueuedCalls: PublicCallRequest[];
84
+
85
+ publicDataReads: PublicDataRead[];
86
+ publicDataWrites: PublicDataUpdateRequest[];
71
87
 
72
88
  noteHashReadRequests: TreeLeafReadRequest[];
73
89
  noteHashes: ScopedNoteHash[];
74
90
 
75
91
  nullifierReadRequests: ScopedReadRequest[];
76
92
  nullifierNonExistentReadRequests: ScopedReadRequest[];
77
- nullifiers: ScopedNullifier[];
93
+ nullifiers: Nullifier[];
78
94
 
79
95
  l1ToL2MsgReadRequests: TreeLeafReadRequest[];
80
96
  l2ToL1Msgs: ScopedL2ToL1Message[];
@@ -83,6 +99,29 @@ export type SideEffects = {
83
99
  unencryptedLogsHashes: ScopedLogHash[];
84
100
  };
85
101
 
102
+ export class SideEffectArrayLengths {
103
+ constructor(
104
+ public readonly publicDataReads: number,
105
+ public readonly publicDataWrites: number,
106
+
107
+ public readonly noteHashReadRequests: number,
108
+ public readonly noteHashes: number,
109
+
110
+ public readonly nullifierReadRequests: number,
111
+ public readonly nullifierNonExistentReadRequests: number,
112
+ public readonly nullifiers: number,
113
+
114
+ public readonly l1ToL2MsgReadRequests: number,
115
+ public readonly l2ToL1Msgs: number,
116
+
117
+ public readonly unencryptedLogs: number,
118
+ ) {}
119
+
120
+ static empty() {
121
+ return new this(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
122
+ }
123
+ }
124
+
86
125
  /**
87
126
  * Trace side effects for an entire enqueued call.
88
127
  */
@@ -92,35 +131,38 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
92
131
  /** The side effect counter increments with every call to the trace. */
93
132
  private sideEffectCounter: number;
94
133
 
95
- // TODO(dbanks12): make contract address mandatory in ContractStorage* structs,
96
- // and include it in serialization, or modify PublicData* structs for this.
97
- private contractStorageReads: ContractStorageRead[] = [];
98
- private contractStorageUpdateRequests: ContractStorageUpdateRequest[] = [];
134
+ private enqueuedCalls: PublicCallRequest[] = [];
135
+
136
+ private publicDataReads: PublicDataRead[] = [];
137
+ private publicDataWrites: PublicDataUpdateRequest[] = [];
99
138
 
100
139
  private noteHashReadRequests: TreeLeafReadRequest[] = [];
101
140
  private noteHashes: ScopedNoteHash[] = [];
102
141
 
103
142
  private nullifierReadRequests: ScopedReadRequest[] = [];
104
143
  private nullifierNonExistentReadRequests: ScopedReadRequest[] = [];
105
- private nullifiers: ScopedNullifier[] = [];
144
+ private nullifiers: Nullifier[] = [];
106
145
 
107
146
  private l1ToL2MsgReadRequests: TreeLeafReadRequest[] = [];
108
- private l2ToL1Msgs: ScopedL2ToL1Message[] = [];
147
+ private l2ToL1Messages: ScopedL2ToL1Message[] = [];
109
148
 
110
149
  private unencryptedLogs: UnencryptedL2Log[] = [];
111
150
  private unencryptedLogsHashes: ScopedLogHash[] = [];
112
151
 
113
152
  private avmCircuitHints: AvmExecutionHints;
114
153
 
154
+ /** Make sure a forked trace is never merged twice. */
155
+ private alreadyMergedIntoParent = false;
156
+
115
157
  constructor(
116
158
  /** The counter of this trace's first side effect. */
117
159
  public readonly startSideEffectCounter: number = 0,
118
160
  /** Track parent's (or previous kernel's) lengths so the AVM can properly enforce TX-wide limits,
119
161
  * otherwise the public kernel can fail to prove because TX limits are breached.
120
162
  */
121
- private readonly previousValidationRequestArrayLengths: PublicValidationRequestArrayLengths = PublicValidationRequestArrayLengths.empty(),
122
- private readonly previousAccumulatedDataArrayLengths: PublicAccumulatedDataArrayLengths = PublicAccumulatedDataArrayLengths.empty(),
163
+ private readonly previousSideEffectArrayLengths: SideEffectArrayLengths = SideEffectArrayLengths.empty(),
123
164
  ) {
165
+ this.log.debug(`Creating trace instance with startSideEffectCounter: ${startSideEffectCounter}`);
124
166
  this.sideEffectCounter = startSideEffectCounter;
125
167
  this.avmCircuitHints = AvmExecutionHints.empty();
126
168
  }
@@ -128,27 +170,46 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
128
170
  public fork() {
129
171
  return new PublicEnqueuedCallSideEffectTrace(
130
172
  this.sideEffectCounter,
131
- new PublicValidationRequestArrayLengths(
132
- this.previousValidationRequestArrayLengths.noteHashReadRequests + this.noteHashReadRequests.length,
133
- this.previousValidationRequestArrayLengths.nullifierReadRequests + this.nullifierReadRequests.length,
134
- this.previousValidationRequestArrayLengths.nullifierNonExistentReadRequests +
173
+ new SideEffectArrayLengths(
174
+ this.previousSideEffectArrayLengths.publicDataReads + this.publicDataReads.length,
175
+ this.previousSideEffectArrayLengths.publicDataWrites + this.publicDataWrites.length,
176
+ this.previousSideEffectArrayLengths.noteHashReadRequests + this.noteHashReadRequests.length,
177
+ this.previousSideEffectArrayLengths.noteHashes + this.noteHashes.length,
178
+ this.previousSideEffectArrayLengths.nullifierReadRequests + this.nullifierReadRequests.length,
179
+ this.previousSideEffectArrayLengths.nullifierNonExistentReadRequests +
135
180
  this.nullifierNonExistentReadRequests.length,
136
- this.previousValidationRequestArrayLengths.l1ToL2MsgReadRequests + this.l1ToL2MsgReadRequests.length,
137
- this.previousValidationRequestArrayLengths.publicDataReads + this.contractStorageReads.length,
138
- ),
139
- new PublicAccumulatedDataArrayLengths(
140
- this.previousAccumulatedDataArrayLengths.noteHashes + this.noteHashes.length,
141
- this.previousAccumulatedDataArrayLengths.nullifiers + this.nullifiers.length,
142
- this.previousAccumulatedDataArrayLengths.l2ToL1Msgs + this.l2ToL1Msgs.length,
143
- this.previousAccumulatedDataArrayLengths.noteEncryptedLogsHashes,
144
- this.previousAccumulatedDataArrayLengths.encryptedLogsHashes,
145
- this.previousAccumulatedDataArrayLengths.unencryptedLogsHashes + this.unencryptedLogsHashes.length,
146
- this.previousAccumulatedDataArrayLengths.publicDataUpdateRequests + this.contractStorageUpdateRequests.length,
147
- this.previousAccumulatedDataArrayLengths.publicCallStack,
181
+ this.previousSideEffectArrayLengths.nullifiers + this.nullifiers.length,
182
+ this.previousSideEffectArrayLengths.l1ToL2MsgReadRequests + this.l1ToL2MsgReadRequests.length,
183
+ this.previousSideEffectArrayLengths.l2ToL1Msgs + this.l2ToL1Messages.length,
184
+ this.previousSideEffectArrayLengths.unencryptedLogs + this.unencryptedLogs.length,
148
185
  ),
149
186
  );
150
187
  }
151
188
 
189
+ public merge(forkedTrace: this, reverted: boolean = false) {
190
+ // sanity check to avoid merging the same forked trace twice
191
+ assert(!this.alreadyMergedIntoParent, 'Cannot merge a forked trace that has already been merged into its parent!');
192
+ forkedTrace.alreadyMergedIntoParent = true;
193
+
194
+ // TODO(dbanks12): accept & merge forked trace's hints!
195
+ this.sideEffectCounter = forkedTrace.sideEffectCounter;
196
+ this.enqueuedCalls.push(...forkedTrace.enqueuedCalls);
197
+
198
+ if (!reverted) {
199
+ this.publicDataReads.push(...forkedTrace.publicDataReads);
200
+ this.publicDataWrites.push(...forkedTrace.publicDataWrites);
201
+ this.noteHashReadRequests.push(...forkedTrace.noteHashReadRequests);
202
+ this.noteHashes.push(...forkedTrace.noteHashes);
203
+ this.nullifierReadRequests.push(...forkedTrace.nullifierReadRequests);
204
+ this.nullifierNonExistentReadRequests.push(...forkedTrace.nullifierNonExistentReadRequests);
205
+ this.nullifiers.push(...forkedTrace.nullifiers);
206
+ this.l1ToL2MsgReadRequests.push(...forkedTrace.l1ToL2MsgReadRequests);
207
+ this.l2ToL1Messages.push(...forkedTrace.l2ToL1Messages);
208
+ this.unencryptedLogs.push(...forkedTrace.unencryptedLogs);
209
+ this.unencryptedLogsHashes.push(...forkedTrace.unencryptedLogsHashes);
210
+ }
211
+ }
212
+
152
213
  public getCounter() {
153
214
  return this.sideEffectCounter;
154
215
  }
@@ -157,74 +218,136 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
157
218
  this.sideEffectCounter++;
158
219
  }
159
220
 
160
- public tracePublicStorageRead(contractAddress: Fr, slot: Fr, value: Fr, _exists: boolean, _cached: boolean) {
221
+ public tracePublicStorageRead(
222
+ contractAddress: AztecAddress,
223
+ slot: Fr,
224
+ value: Fr,
225
+ leafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(),
226
+ leafIndex: Fr = Fr.zero(),
227
+ path: Fr[] = emptyPublicDataPath(),
228
+ ) {
229
+ if (!leafIndex.equals(Fr.zero())) {
230
+ // if we have real merkle hint content, make sure the value matches the the provided preimage
231
+ assert(leafPreimage.value.equals(value), 'Value mismatch when tracing in public data write');
232
+ }
161
233
  // NOTE: exists and cached are unused for now but may be used for optimizations or kernel hints later
162
234
  if (
163
- this.contractStorageReads.length + this.previousValidationRequestArrayLengths.publicDataReads >=
235
+ this.publicDataReads.length + this.previousSideEffectArrayLengths.publicDataReads >=
164
236
  MAX_PUBLIC_DATA_READS_PER_TX
165
237
  ) {
166
- throw new SideEffectLimitReachedError('contract storage read', MAX_PUBLIC_DATA_READS_PER_TX);
238
+ throw new SideEffectLimitReachedError('public data (contract storage) read', MAX_PUBLIC_DATA_READS_PER_TX);
167
239
  }
168
240
 
169
- this.contractStorageReads.push(
170
- new ContractStorageRead(slot, value, this.sideEffectCounter, AztecAddress.fromField(contractAddress)),
171
- );
241
+ const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot);
242
+
243
+ this.publicDataReads.push(new PublicDataRead(leafSlot, value, this.sideEffectCounter));
244
+
172
245
  this.avmCircuitHints.storageValues.items.push(
173
246
  new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ value),
174
247
  );
248
+ this.avmCircuitHints.storageReadRequest.items.push(new AvmPublicDataReadTreeHint(leafPreimage, leafIndex, path));
175
249
  this.log.debug(`SLOAD cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`);
176
250
  this.incrementSideEffectCounter();
177
251
  }
178
252
 
179
- public tracePublicStorageWrite(contractAddress: Fr, slot: Fr, value: Fr) {
253
+ public tracePublicStorageWrite(
254
+ contractAddress: AztecAddress,
255
+ slot: Fr,
256
+ value: Fr,
257
+ lowLeafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(),
258
+ lowLeafIndex: Fr = Fr.zero(),
259
+ lowLeafPath: Fr[] = emptyPublicDataPath(),
260
+ newLeafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(),
261
+ insertionPath: Fr[] = emptyPublicDataPath(),
262
+ ) {
263
+ if (!lowLeafIndex.equals(Fr.zero())) {
264
+ // if we have real merkle hint content, make sure the value matches the the provided preimage
265
+ assert(newLeafPreimage.value.equals(value), 'Value mismatch when tracing in public data read');
266
+ }
180
267
  if (
181
- this.contractStorageUpdateRequests.length + this.previousAccumulatedDataArrayLengths.publicDataUpdateRequests >=
268
+ this.publicDataWrites.length + this.previousSideEffectArrayLengths.publicDataWrites >=
182
269
  MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
183
270
  ) {
184
- throw new SideEffectLimitReachedError('contract storage write', MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX);
271
+ throw new SideEffectLimitReachedError(
272
+ 'public data (contract storage) write',
273
+ MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
274
+ );
185
275
  }
186
276
 
187
- this.contractStorageUpdateRequests.push(
188
- new ContractStorageUpdateRequest(slot, value, this.sideEffectCounter, contractAddress),
277
+ const leafSlot = computePublicDataTreeLeafSlot(contractAddress, slot);
278
+ this.publicDataWrites.push(new PublicDataUpdateRequest(leafSlot, value, this.sideEffectCounter));
279
+
280
+ // New hinting
281
+ const readHint = new AvmPublicDataReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath);
282
+ this.avmCircuitHints.storageUpdateRequest.items.push(
283
+ new AvmPublicDataWriteTreeHint(readHint, newLeafPreimage, insertionPath),
284
+ );
285
+
286
+ this.log.debug(
287
+ `Traced public data write (address=${contractAddress}, slot=${slot}, leafSlot=${leafSlot}): value=${value} (counter=${this.sideEffectCounter})`,
189
288
  );
190
- this.log.debug(`SSTORE cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`);
191
289
  this.incrementSideEffectCounter();
192
290
  }
193
291
 
194
292
  // TODO(8287): _exists can be removed once we have the vm properly handling the equality check
195
- public traceNoteHashCheck(_contractAddress: Fr, noteHash: Fr, leafIndex: Fr, exists: boolean) {
293
+ public traceNoteHashCheck(
294
+ _contractAddress: AztecAddress,
295
+ noteHash: Fr,
296
+ leafIndex: Fr,
297
+ exists: boolean,
298
+ path: Fr[] = emptyNoteHashPath(),
299
+ ) {
196
300
  // NOTE: contractAddress is unused because noteHash is an already-siloed leaf
197
301
  if (
198
- this.noteHashReadRequests.length + this.previousValidationRequestArrayLengths.noteHashReadRequests >=
302
+ this.noteHashReadRequests.length + this.previousSideEffectArrayLengths.noteHashReadRequests >=
199
303
  MAX_NOTE_HASH_READ_REQUESTS_PER_TX
200
304
  ) {
201
305
  throw new SideEffectLimitReachedError('note hash read request', MAX_NOTE_HASH_READ_REQUESTS_PER_TX);
202
306
  }
203
307
 
308
+ // note hash is already siloed here
204
309
  this.noteHashReadRequests.push(new TreeLeafReadRequest(noteHash, leafIndex));
205
310
  this.avmCircuitHints.noteHashExists.items.push(
206
311
  new AvmKeyValueHint(/*key=*/ new Fr(leafIndex), /*value=*/ exists ? Fr.ONE : Fr.ZERO),
207
312
  );
313
+ // New Hinting
314
+ this.avmCircuitHints.noteHashReadRequest.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path));
208
315
  // NOTE: counter does not increment for note hash checks (because it doesn't rely on pending note hashes)
209
316
  }
210
317
 
211
- public traceNewNoteHash(contractAddress: Fr, noteHash: Fr) {
212
- if (this.noteHashes.length + this.previousAccumulatedDataArrayLengths.noteHashes >= MAX_NOTE_HASHES_PER_TX) {
318
+ public traceNewNoteHash(
319
+ contractAddress: AztecAddress,
320
+ noteHash: Fr,
321
+ leafIndex: Fr,
322
+ path: Fr[] = emptyNoteHashPath(),
323
+ ) {
324
+ if (this.noteHashes.length + this.previousSideEffectArrayLengths.noteHashes >= MAX_NOTE_HASHES_PER_TX) {
213
325
  throw new SideEffectLimitReachedError('note hash', MAX_NOTE_HASHES_PER_TX);
214
326
  }
215
327
 
216
- this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter).scope(AztecAddress.fromField(contractAddress)));
328
+ // TODO(dbanks12): make unique and silo instead of scoping
329
+ //const siloedNoteHash = siloNoteHash(contractAddress, noteHash);
330
+ this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter).scope(contractAddress));
217
331
  this.log.debug(`NEW_NOTE_HASH cnt: ${this.sideEffectCounter}`);
332
+ this.avmCircuitHints.noteHashWriteRequest.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path));
218
333
  this.incrementSideEffectCounter();
219
334
  }
220
335
 
221
- public traceNullifierCheck(contractAddress: Fr, nullifier: Fr, _leafIndex: Fr, exists: boolean, _isPending: boolean) {
336
+ public traceNullifierCheck(
337
+ contractAddress: AztecAddress,
338
+ nullifier: Fr,
339
+ exists: boolean,
340
+ lowLeafPreimage: NullifierLeafPreimage = NullifierLeafPreimage.empty(),
341
+ lowLeafIndex: Fr = Fr.zero(),
342
+ lowLeafPath: Fr[] = emptyNullifierPath(),
343
+ ) {
222
344
  // NOTE: isPending and leafIndex are unused for now but may be used for optimizations or kernel hints later
223
345
  this.enforceLimitOnNullifierChecks();
224
346
 
225
- const readRequest = new ReadRequest(nullifier, this.sideEffectCounter).scope(
226
- AztecAddress.fromField(contractAddress),
227
- );
347
+ // TODO(dbanks12): use siloed nullifier instead of scoped once public kernel stops siloing
348
+ // and once VM public inputs are meant to contain siloed nullifiers.
349
+ //const siloedNullifier = siloNullifier(contractAddress, nullifier);
350
+ const readRequest = new ReadRequest(nullifier, this.sideEffectCounter).scope(contractAddress);
228
351
  if (exists) {
229
352
  this.nullifierReadRequests.push(readRequest);
230
353
  } else {
@@ -233,29 +356,47 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
233
356
  this.avmCircuitHints.nullifierExists.items.push(
234
357
  new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ new Fr(exists ? 1 : 0)),
235
358
  );
359
+ // New Hints
360
+ this.avmCircuitHints.nullifierReadRequest.items.push(
361
+ new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath),
362
+ );
236
363
  this.log.debug(`NULLIFIER_EXISTS cnt: ${this.sideEffectCounter}`);
237
364
  this.incrementSideEffectCounter();
238
365
  }
239
366
 
240
- public traceNewNullifier(contractAddress: Fr, nullifier: Fr) {
241
- if (this.nullifiers.length + this.previousAccumulatedDataArrayLengths.nullifiers >= MAX_NULLIFIERS_PER_TX) {
367
+ public traceNewNullifier(
368
+ contractAddress: AztecAddress,
369
+ nullifier: Fr,
370
+ lowLeafPreimage: NullifierLeafPreimage = NullifierLeafPreimage.empty(),
371
+ lowLeafIndex: Fr = Fr.zero(),
372
+ lowLeafPath: Fr[] = emptyNullifierPath(),
373
+ insertionPath: Fr[] = emptyNullifierPath(),
374
+ ) {
375
+ if (this.nullifiers.length + this.previousSideEffectArrayLengths.nullifiers >= MAX_NULLIFIERS_PER_TX) {
242
376
  throw new SideEffectLimitReachedError('nullifier', MAX_NULLIFIERS_PER_TX);
243
377
  }
244
378
 
245
- this.nullifiers.push(
246
- new Nullifier(nullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO).scope(
247
- AztecAddress.fromField(contractAddress),
248
- ),
249
- );
379
+ const siloedNullifier = siloNullifier(contractAddress, nullifier);
380
+ this.nullifiers.push(new Nullifier(siloedNullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO));
381
+
382
+ // New hinting
383
+ const lowLeafReadHint = new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath);
384
+ this.avmCircuitHints.nullifierWriteHints.items.push(new AvmNullifierWriteTreeHint(lowLeafReadHint, insertionPath));
250
385
  this.log.debug(`NEW_NULLIFIER cnt: ${this.sideEffectCounter}`);
251
386
  this.incrementSideEffectCounter();
252
387
  }
253
388
 
254
389
  // TODO(8287): _exists can be removed once we have the vm properly handling the equality check
255
- public traceL1ToL2MessageCheck(_contractAddress: Fr, msgHash: Fr, msgLeafIndex: Fr, exists: boolean) {
390
+ public traceL1ToL2MessageCheck(
391
+ _contractAddress: AztecAddress,
392
+ msgHash: Fr,
393
+ msgLeafIndex: Fr,
394
+ exists: boolean,
395
+ path: Fr[] = emptyL1ToL2MessagePath(),
396
+ ) {
256
397
  // NOTE: contractAddress is unused because msgHash is an already-siloed leaf
257
398
  if (
258
- this.l1ToL2MsgReadRequests.length + this.previousValidationRequestArrayLengths.l1ToL2MsgReadRequests >=
399
+ this.l1ToL2MsgReadRequests.length + this.previousSideEffectArrayLengths.l1ToL2MsgReadRequests >=
259
400
  MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX
260
401
  ) {
261
402
  throw new SideEffectLimitReachedError('l1 to l2 message read request', MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX);
@@ -265,50 +406,45 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
265
406
  this.avmCircuitHints.l1ToL2MessageExists.items.push(
266
407
  new AvmKeyValueHint(/*key=*/ new Fr(msgLeafIndex), /*value=*/ exists ? Fr.ONE : Fr.ZERO),
267
408
  );
409
+ // New Hinting
410
+ this.avmCircuitHints.l1ToL2MessageReadRequest.items.push(new AvmAppendTreeHint(msgLeafIndex, msgHash, path));
268
411
  }
269
412
 
270
- public traceNewL2ToL1Message(contractAddress: Fr, recipient: Fr, content: Fr) {
271
- if (this.l2ToL1Msgs.length + this.previousAccumulatedDataArrayLengths.l2ToL1Msgs >= MAX_L2_TO_L1_MSGS_PER_TX) {
413
+ public traceNewL2ToL1Message(contractAddress: AztecAddress, recipient: Fr, content: Fr) {
414
+ if (this.l2ToL1Messages.length + this.previousSideEffectArrayLengths.l2ToL1Msgs >= MAX_L2_TO_L1_MSGS_PER_TX) {
272
415
  throw new SideEffectLimitReachedError('l2 to l1 message', MAX_L2_TO_L1_MSGS_PER_TX);
273
416
  }
274
417
 
275
418
  const recipientAddress = EthAddress.fromField(recipient);
276
- this.l2ToL1Msgs.push(
277
- new L2ToL1Message(recipientAddress, content, this.sideEffectCounter).scope(
278
- AztecAddress.fromField(contractAddress),
279
- ),
419
+ this.l2ToL1Messages.push(
420
+ new L2ToL1Message(recipientAddress, content, this.sideEffectCounter).scope(contractAddress),
280
421
  );
281
422
  this.log.debug(`NEW_L2_TO_L1_MSG cnt: ${this.sideEffectCounter}`);
282
423
  this.incrementSideEffectCounter();
283
424
  }
284
425
 
285
- public traceUnencryptedLog(contractAddress: Fr, log: Fr[]) {
426
+ public traceUnencryptedLog(contractAddress: AztecAddress, log: Fr[]) {
286
427
  if (
287
- this.unencryptedLogs.length + this.previousAccumulatedDataArrayLengths.unencryptedLogsHashes >=
428
+ this.unencryptedLogs.length + this.previousSideEffectArrayLengths.unencryptedLogs >=
288
429
  MAX_UNENCRYPTED_LOGS_PER_TX
289
430
  ) {
290
431
  throw new SideEffectLimitReachedError('unencrypted log', MAX_UNENCRYPTED_LOGS_PER_TX);
291
432
  }
292
433
 
293
- const ulog = new UnencryptedL2Log(
294
- AztecAddress.fromField(contractAddress),
295
- Buffer.concat(log.map(f => f.toBuffer())),
296
- );
434
+ const ulog = new UnencryptedL2Log(contractAddress, Buffer.concat(log.map(f => f.toBuffer())));
297
435
  const basicLogHash = Fr.fromBuffer(ulog.hash());
298
436
  this.unencryptedLogs.push(ulog);
299
437
  // This length is for charging DA and is checked on-chain - has to be length of log preimage + 4 bytes.
300
438
  // The .length call also has a +4 but that is unrelated
301
439
  this.unencryptedLogsHashes.push(
302
- new LogHash(basicLogHash, this.sideEffectCounter, new Fr(ulog.length + 4)).scope(
303
- AztecAddress.fromField(contractAddress),
304
- ),
440
+ new LogHash(basicLogHash, this.sideEffectCounter, new Fr(ulog.length + 4)).scope(contractAddress),
305
441
  );
306
442
  this.log.debug(`NEW_UNENCRYPTED_LOG cnt: ${this.sideEffectCounter}`);
307
443
  this.incrementSideEffectCounter();
308
444
  }
309
445
 
310
446
  public traceGetContractInstance(
311
- contractAddress: Fr,
447
+ contractAddress: AztecAddress,
312
448
  exists: boolean,
313
449
  instance: SerializableContractInstance = SerializableContractInstance.default(),
314
450
  ) {
@@ -330,10 +466,10 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
330
466
  }
331
467
 
332
468
  // This tracing function gets called everytime we start simulation/execution.
333
- // This happens both when starting a new top-level trace and the start of every nested trace
469
+ // This happens both when starting a new top-level trace and the start of every forked trace
334
470
  // We use this to collect the AvmContractBytecodeHints
335
471
  public traceGetBytecode(
336
- contractAddress: Fr,
472
+ contractAddress: AztecAddress,
337
473
  exists: boolean,
338
474
  bytecode: Buffer = Buffer.alloc(0),
339
475
  contractInstance: SerializableContractInstance = SerializableContractInstance.default(),
@@ -369,7 +505,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
369
505
  */
370
506
  public traceNestedCall(
371
507
  /** The trace of the nested call. */
372
- nestedCallTrace: this,
508
+ _nestedCallTrace: this,
373
509
  /** The execution environment of the nested call. */
374
510
  nestedEnvironment: AvmExecutionEnvironment,
375
511
  /** How much gas was available for this public execution. */
@@ -383,20 +519,11 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
383
519
  /** Function name for logging */
384
520
  _functionName: string = 'unknown',
385
521
  ) {
522
+ // TODO(4805): check if some threshold is reached for max nested calls (to unique contracts?)
523
+ //
386
524
  // Store end side effect counter before it gets updated by absorbing nested call trace
387
525
  const endSideEffectCounter = new Fr(this.sideEffectCounter);
388
526
 
389
- // TODO(4805): check if some threshold is reached for max nested calls (to unique contracts?)
390
- // TODO(dbanks12): should emit a nullifier read request. There should be two thresholds.
391
- // one for max unique contract calls, and another based on max nullifier reads.
392
- // Since this trace function happens _after_ a nested call, such threshold limits must take
393
- // place in another trace function that occurs _before_ a nested call.
394
- if (avmCallResults.reverted) {
395
- this.absorbRevertedNestedTrace(nestedCallTrace);
396
- } else {
397
- this.absorbSuccessfulNestedTrace(nestedCallTrace);
398
- }
399
-
400
527
  const gasUsed = new Gas(startGasLeft.daGas - endGasLeft.daGas, startGasLeft.l2Gas - endGasLeft.l2Gas);
401
528
 
402
529
  this.avmCircuitHints.externalCalls.items.push(
@@ -410,85 +537,133 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
410
537
  );
411
538
  }
412
539
 
413
- public absorbSuccessfulNestedTrace(nestedTrace: this) {
414
- this.sideEffectCounter = nestedTrace.sideEffectCounter;
415
- this.contractStorageReads.push(...nestedTrace.contractStorageReads);
416
- this.contractStorageUpdateRequests.push(...nestedTrace.contractStorageUpdateRequests);
417
- this.noteHashReadRequests.push(...nestedTrace.noteHashReadRequests);
418
- this.noteHashes.push(...nestedTrace.noteHashes);
419
- this.nullifierReadRequests.push(...nestedTrace.nullifierReadRequests);
420
- this.nullifierNonExistentReadRequests.push(...nestedTrace.nullifierNonExistentReadRequests);
421
- this.nullifiers.push(...nestedTrace.nullifiers);
422
- this.l1ToL2MsgReadRequests.push(...nestedTrace.l1ToL2MsgReadRequests);
423
- this.l2ToL1Msgs.push(...nestedTrace.l2ToL1Msgs);
424
- this.unencryptedLogs.push(...nestedTrace.unencryptedLogs);
425
- this.unencryptedLogsHashes.push(...nestedTrace.unencryptedLogsHashes);
426
- }
427
-
428
- public absorbRevertedNestedTrace(nestedTrace: this) {
429
- // All read requests, and any writes (storage & nullifiers) that
430
- // require complex validation in public kernel (with end lifetimes)
431
- // must be absorbed even on revert.
432
-
433
- // TODO(dbanks12): What should happen to side effect counter on revert?
434
- this.sideEffectCounter = nestedTrace.sideEffectCounter;
435
- this.contractStorageReads.push(...nestedTrace.contractStorageReads);
436
- this.contractStorageUpdateRequests.push(...nestedTrace.contractStorageUpdateRequests);
437
- this.noteHashReadRequests.push(...nestedTrace.noteHashReadRequests);
438
- // new noteHashes are tossed on revert
439
- this.nullifierReadRequests.push(...nestedTrace.nullifierReadRequests);
440
- this.nullifierNonExistentReadRequests.push(...nestedTrace.nullifierNonExistentReadRequests);
441
- this.nullifiers.push(...nestedTrace.nullifiers);
442
- this.l1ToL2MsgReadRequests.push(...nestedTrace.l1ToL2MsgReadRequests);
443
- // new l2-to-l1 messages are tossed on revert
444
- // new unencrypted logs are tossed on revert
540
+ /**
541
+ * Trace an enqueued call.
542
+ * Accept some results from a finished call's trace into this one.
543
+ */
544
+ public traceEnqueuedCall(
545
+ /** The call request from private that enqueued this call. */
546
+ publicCallRequest: PublicCallRequest,
547
+ /** The call's calldata */
548
+ calldata: Fr[],
549
+ /** Did the call revert? */
550
+ _reverted: boolean,
551
+ ) {
552
+ this.log.debug(`Tracing enqueued call`);
553
+ // TODO(4805): check if some threshold is reached for max enqueued or nested calls (to unique contracts?)
554
+ this.enqueuedCalls.push(publicCallRequest);
555
+ this.avmCircuitHints.enqueuedCalls.items.push(new AvmEnqueuedCallHint(publicCallRequest.contractAddress, calldata));
445
556
  }
446
557
 
447
558
  public getSideEffects(): SideEffects {
448
559
  return {
449
- contractStorageReads: this.contractStorageReads,
450
- contractStorageUpdateRequests: this.contractStorageUpdateRequests,
560
+ enqueuedCalls: this.enqueuedCalls,
561
+ publicDataReads: this.publicDataReads,
562
+ publicDataWrites: this.publicDataWrites,
451
563
  noteHashReadRequests: this.noteHashReadRequests,
452
564
  noteHashes: this.noteHashes,
453
565
  nullifierReadRequests: this.nullifierReadRequests,
454
566
  nullifierNonExistentReadRequests: this.nullifierNonExistentReadRequests,
455
567
  nullifiers: this.nullifiers,
456
568
  l1ToL2MsgReadRequests: this.l1ToL2MsgReadRequests,
457
- l2ToL1Msgs: this.l2ToL1Msgs,
569
+ l2ToL1Msgs: this.l2ToL1Messages,
458
570
  unencryptedLogs: this.unencryptedLogs,
459
571
  unencryptedLogsHashes: this.unencryptedLogsHashes,
460
572
  };
461
573
  }
462
574
 
463
- public toVMCircuitPublicInputs(
464
- /** Constants. */
465
- constants: CombinedConstantData,
466
- /** The execution environment of the nested call. */
467
- avmEnvironment: AvmExecutionEnvironment,
468
- /** How much gas was available for this public execution. */
469
- startGasLeft: Gas,
575
+ /**
576
+ * Get the results of public execution.
577
+ */
578
+ public toPublicEnqueuedCallExecutionResult(
470
579
  /** How much gas was left after this public execution. */
471
580
  endGasLeft: Gas,
472
581
  /** The call's results */
473
582
  avmCallResults: AvmContractCallResult,
474
- ): VMCircuitPublicInputs {
475
- return new VMCircuitPublicInputs(
476
- /*constants=*/ constants,
477
- /*callRequest=*/ createPublicCallRequest(avmEnvironment),
478
- /*publicCallStack=*/ makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicInnerCallRequest.empty),
479
- /*previousValidationRequestArrayLengths=*/ this.previousValidationRequestArrayLengths,
480
- /*validationRequests=*/ this.getValidationRequests(),
481
- /*previousAccumulatedDataArrayLengths=*/ this.previousAccumulatedDataArrayLengths,
482
- /*accumulatedData=*/ this.getAccumulatedData(startGasLeft.sub(endGasLeft)),
483
- /*startSideEffectCounter=*/ this.startSideEffectCounter,
484
- /*endSideEffectCounter=*/ this.sideEffectCounter,
485
- /*startGasLeft=*/ startGasLeft,
486
- // TODO(dbanks12): should have endGasLeft
487
- /*transactionFee=*/ avmEnvironment.transactionFee,
488
- /*reverted=*/ avmCallResults.reverted,
583
+ ): EnqueuedPublicCallExecutionResultWithSideEffects {
584
+ return {
585
+ endGasLeft,
586
+ endSideEffectCounter: new Fr(this.sideEffectCounter),
587
+ returnValues: avmCallResults.output,
588
+ reverted: avmCallResults.reverted,
589
+ revertReason: avmCallResults.revertReason
590
+ ? createSimulationError(avmCallResults.revertReason, avmCallResults.output)
591
+ : undefined,
592
+ sideEffects: {
593
+ publicDataWrites: this.publicDataWrites,
594
+ noteHashes: this.noteHashes,
595
+ nullifiers: this.nullifiers,
596
+ l2ToL1Messages: this.l2ToL1Messages,
597
+ unencryptedLogsHashes: this.unencryptedLogsHashes, // Scoped?
598
+ unencryptedLogs: new UnencryptedFunctionL2Logs(this.unencryptedLogs),
599
+ },
600
+ };
601
+ }
602
+
603
+ public toAvmCircuitPublicInputs(
604
+ /** Globals. */
605
+ globalVariables: GlobalVariables,
606
+ /** Start tree snapshots. */
607
+ startTreeSnapshots: TreeSnapshots,
608
+ /** Gas used at start of TX. */
609
+ startGasUsed: Gas,
610
+ /** How much gas was available for this public execution. */
611
+ gasLimits: GasSettings,
612
+ /** Call requests for setup phase. */
613
+ publicSetupCallRequests: PublicCallRequest[],
614
+ /** Call requests for app logic phase. */
615
+ publicAppLogicCallRequests: PublicCallRequest[],
616
+ /** Call request for teardown phase. */
617
+ publicTeardownCallRequest: PublicCallRequest,
618
+ /** End tree snapshots. */
619
+ endTreeSnapshots: TreeSnapshots,
620
+ /**
621
+ * Gas used by the whole transaction, assuming entire teardown limit is used.
622
+ * This is the gas used when computing transaction fee.
623
+ */
624
+ endGasUsed: Gas,
625
+ /** Transaction fee. */
626
+ transactionFee: Fr,
627
+ /** The call's results */
628
+ reverted: boolean,
629
+ ): AvmCircuitPublicInputs {
630
+ return new AvmCircuitPublicInputs(
631
+ globalVariables,
632
+ startTreeSnapshots,
633
+ startGasUsed,
634
+ gasLimits,
635
+ padArrayEnd(publicSetupCallRequests, PublicCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_TX),
636
+ padArrayEnd(publicAppLogicCallRequests, PublicCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_TX),
637
+ publicTeardownCallRequest,
638
+ /*previousNonRevertibleAccumulatedDataArrayLengths=*/ PrivateToAvmAccumulatedDataArrayLengths.empty(),
639
+ /*previousRevertibleAccumulatedDataArrayLengths=*/ PrivateToAvmAccumulatedDataArrayLengths.empty(),
640
+ /*previousNonRevertibleAccumulatedDataArray=*/ PrivateToAvmAccumulatedData.empty(),
641
+ /*previousRevertibleAccumulatedDataArray=*/ PrivateToAvmAccumulatedData.empty(),
642
+ endTreeSnapshots,
643
+ endGasUsed,
644
+ /*accumulatedData=*/ this.getAvmAccumulatedData(),
645
+ transactionFee,
646
+ reverted,
489
647
  );
490
648
  }
491
649
 
650
+ public toPublicFunctionCallResult(
651
+ /** The execution environment of the nested call. */
652
+ _avmEnvironment: AvmExecutionEnvironment,
653
+ /** How much gas was available for this public execution. */
654
+ _startGasLeft: Gas,
655
+ /** How much gas was left after this public execution. */
656
+ _endGasLeft: Gas,
657
+ /** Bytecode used for this execution. */
658
+ _bytecode: Buffer,
659
+ /** The call's results */
660
+ _avmCallResults: AvmContractCallResult,
661
+ /** Function name for logging */
662
+ _functionName: string = 'unknown',
663
+ ): PublicFunctionCallResult {
664
+ throw new Error('Not implemented');
665
+ }
666
+
492
667
  public getUnencryptedLogs() {
493
668
  return this.unencryptedLogs;
494
669
  }
@@ -497,47 +672,25 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
497
672
  return this.avmCircuitHints;
498
673
  }
499
674
 
500
- private getValidationRequests() {
501
- return new PublicValidationRequests(
502
- RollupValidationRequests.empty(), // TODO(dbanks12): what should this be?
503
- padArrayEnd(this.noteHashReadRequests, TreeLeafReadRequest.empty(), MAX_NOTE_HASH_READ_REQUESTS_PER_TX),
504
- padArrayEnd(this.nullifierReadRequests, ScopedReadRequest.empty(), MAX_NULLIFIER_READ_REQUESTS_PER_TX),
675
+ private getAvmAccumulatedData() {
676
+ return new AvmAccumulatedData(
505
677
  padArrayEnd(
506
- this.nullifierNonExistentReadRequests,
507
- ScopedReadRequest.empty(),
508
- MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX,
678
+ this.noteHashes.map(n => n.value),
679
+ Fr.zero(),
680
+ MAX_NOTE_HASHES_PER_TX,
509
681
  ),
510
- padArrayEnd(this.l1ToL2MsgReadRequests, TreeLeafReadRequest.empty(), MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX),
511
- // TODO(dbanks12): this is only necessary until VMCircuitPublicInputs uses unsiloed storage slots and pairs storage accesses with contract address
512
682
  padArrayEnd(
513
- this.contractStorageReads.map(r => new PublicDataRead(r.storageSlot, r.currentValue, r.counter)),
514
- PublicDataRead.empty(),
515
- MAX_PUBLIC_DATA_READS_PER_TX,
516
- ),
517
- );
518
- }
519
-
520
- private getAccumulatedData(gasUsed: Gas) {
521
- return new PublicAccumulatedData(
522
- padArrayEnd(this.noteHashes, ScopedNoteHash.empty(), MAX_NOTE_HASHES_PER_TX),
523
- // TODO(dbanks12): should be able to use ScopedNullifier here
524
- padArrayEnd(
525
- this.nullifiers.map(n => new Nullifier(n.nullifier.value, n.nullifier.counter, n.nullifier.noteHash)),
526
- Nullifier.empty(),
683
+ this.nullifiers.map(n => n.value),
684
+ Fr.zero(),
527
685
  MAX_NULLIFIERS_PER_TX,
528
686
  ),
529
- padArrayEnd(this.l2ToL1Msgs, ScopedL2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_TX),
530
- /*noteEncryptedLogsHashes=*/ makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash.empty),
531
- /*encryptedLogsHashes=*/ makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty),
687
+ padArrayEnd(this.l2ToL1Messages, ScopedL2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_TX),
532
688
  padArrayEnd(this.unencryptedLogsHashes, ScopedLogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_TX),
533
- // TODO(dbanks12): this is only necessary until VMCircuitPublicInputs uses unsiloed storage slots and pairs storage accesses with contract address
534
689
  padArrayEnd(
535
- this.contractStorageUpdateRequests.map(w => new PublicDataUpdateRequest(w.storageSlot, w.newValue, w.counter)),
536
- PublicDataUpdateRequest.empty(),
690
+ this.publicDataWrites.map(w => new PublicDataWrite(w.leafSlot, w.newValue)),
691
+ PublicDataWrite.empty(),
537
692
  MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
538
693
  ),
539
- /*publicCallStack=*/ makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest.empty),
540
- /*gasUsed=*/ gasUsed,
541
694
  );
542
695
  }
543
696
 
@@ -549,7 +702,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
549
702
  // going to skip the read request and just revert instead" when the nullifier actually doesn't exist
550
703
  // (or vice versa). So, if either maximum has been reached, any nullifier-reading operation must error.
551
704
  if (
552
- this.nullifierReadRequests.length + this.previousValidationRequestArrayLengths.nullifierReadRequests >=
705
+ this.nullifierReadRequests.length + this.previousSideEffectArrayLengths.nullifierReadRequests >=
553
706
  MAX_NULLIFIER_READ_REQUESTS_PER_TX
554
707
  ) {
555
708
  throw new SideEffectLimitReachedError(
@@ -559,7 +712,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
559
712
  }
560
713
  if (
561
714
  this.nullifierNonExistentReadRequests.length +
562
- this.previousValidationRequestArrayLengths.nullifierNonExistentReadRequests >=
715
+ this.previousSideEffectArrayLengths.nullifierNonExistentReadRequests >=
563
716
  MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX
564
717
  ) {
565
718
  throw new SideEffectLimitReachedError(
@@ -569,16 +722,3 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
569
722
  }
570
723
  }
571
724
  }
572
-
573
- /**
574
- * Helper function to create a public execution request from an AVM execution environment
575
- */
576
- function createPublicCallRequest(avmEnvironment: AvmExecutionEnvironment): PublicCallRequest {
577
- const callContext = CallContext.from({
578
- msgSender: avmEnvironment.sender,
579
- contractAddress: avmEnvironment.address,
580
- functionSelector: avmEnvironment.functionSelector,
581
- isStaticCall: avmEnvironment.isStaticCall,
582
- });
583
- return new PublicCallRequest(callContext, computeVarArgsHash(avmEnvironment.calldata), /*counter=*/ 0);
584
- }