@aztec/simulator 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/dest/acvm/oracle/oracle.d.ts +2 -2
  2. package/dest/acvm/oracle/oracle.d.ts.map +1 -1
  3. package/dest/acvm/oracle/oracle.js +5 -5
  4. package/dest/acvm/oracle/typed_oracle.d.ts +2 -2
  5. package/dest/acvm/oracle/typed_oracle.d.ts.map +1 -1
  6. package/dest/acvm/oracle/typed_oracle.js +3 -3
  7. package/dest/avm/avm_execution_environment.d.ts +3 -2
  8. package/dest/avm/avm_execution_environment.d.ts.map +1 -1
  9. package/dest/avm/avm_execution_environment.js +6 -5
  10. package/dest/avm/avm_memory_types.d.ts +120 -39
  11. package/dest/avm/avm_memory_types.d.ts.map +1 -1
  12. package/dest/avm/avm_memory_types.js +91 -109
  13. package/dest/avm/avm_simulator.d.ts.map +1 -1
  14. package/dest/avm/avm_simulator.js +2 -3
  15. package/dest/avm/errors.d.ts +3 -1
  16. package/dest/avm/errors.d.ts.map +1 -1
  17. package/dest/avm/errors.js +9 -3
  18. package/dest/avm/fixtures/index.d.ts +4 -0
  19. package/dest/avm/fixtures/index.d.ts.map +1 -1
  20. package/dest/avm/fixtures/index.js +11 -3
  21. package/dest/avm/journal/host_storage.d.ts +1 -1
  22. package/dest/avm/journal/host_storage.d.ts.map +1 -1
  23. package/dest/avm/opcodes/addressing_mode.d.ts +24 -0
  24. package/dest/avm/opcodes/addressing_mode.d.ts.map +1 -0
  25. package/dest/avm/opcodes/addressing_mode.js +62 -0
  26. package/dest/avm/opcodes/comparators.d.ts.map +1 -1
  27. package/dest/avm/opcodes/comparators.js +8 -5
  28. package/dest/avm/opcodes/instruction.d.ts +6 -4
  29. package/dest/avm/opcodes/instruction.d.ts.map +1 -1
  30. package/dest/avm/opcodes/instruction.js +4 -3
  31. package/dest/avm/opcodes/memory.d.ts +9 -2
  32. package/dest/avm/opcodes/memory.d.ts.map +1 -1
  33. package/dest/avm/opcodes/memory.js +46 -8
  34. package/dest/avm/serialization/bytecode_serialization.d.ts.map +1 -1
  35. package/dest/avm/serialization/bytecode_serialization.js +24 -22
  36. package/dest/avm/serialization/instruction_serialization.d.ts +17 -15
  37. package/dest/avm/serialization/instruction_serialization.d.ts.map +1 -1
  38. package/dest/avm/serialization/instruction_serialization.js +22 -17
  39. package/dest/avm/temporary_executor_migration.d.ts +25 -0
  40. package/dest/avm/temporary_executor_migration.d.ts.map +1 -0
  41. package/dest/avm/temporary_executor_migration.js +71 -0
  42. package/dest/client/client_execution_context.d.ts +4 -2
  43. package/dest/client/client_execution_context.d.ts.map +1 -1
  44. package/dest/client/client_execution_context.js +7 -4
  45. package/dest/client/execution_result.d.ts +2 -0
  46. package/dest/client/execution_result.d.ts.map +1 -1
  47. package/dest/client/execution_result.js +1 -1
  48. package/dest/client/simulator.d.ts +10 -5
  49. package/dest/client/simulator.d.ts.map +1 -1
  50. package/dest/client/simulator.js +19 -11
  51. package/dest/client/unconstrained_execution.js +2 -2
  52. package/dest/public/execution.js +2 -2
  53. package/dest/public/executor.d.ts +7 -0
  54. package/dest/public/executor.d.ts.map +1 -1
  55. package/dest/public/executor.js +26 -1
  56. package/dest/public/public_execution_context.js +2 -2
  57. package/dest/public/state_actions.d.ts +1 -1
  58. package/dest/public/state_actions.d.ts.map +1 -1
  59. package/dest/public/state_actions.js +5 -6
  60. package/dest/utils.d.ts +5 -20
  61. package/dest/utils.d.ts.map +1 -1
  62. package/dest/utils.js +4 -20
  63. package/package.json +7 -5
  64. package/src/acvm/acvm.ts +156 -0
  65. package/src/acvm/acvm_types.ts +11 -0
  66. package/src/acvm/deserialize.ts +36 -0
  67. package/src/acvm/index.ts +5 -0
  68. package/src/acvm/oracle/debug.ts +109 -0
  69. package/src/acvm/oracle/index.ts +17 -0
  70. package/src/acvm/oracle/oracle.ts +332 -0
  71. package/src/acvm/oracle/typed_oracle.ts +217 -0
  72. package/src/acvm/serialize.ts +75 -0
  73. package/src/avm/avm_context.ts +63 -0
  74. package/src/avm/avm_execution_environment.ts +98 -0
  75. package/src/avm/avm_machine_state.ts +93 -0
  76. package/src/avm/avm_memory_types.ts +309 -0
  77. package/src/avm/avm_message_call_result.ts +29 -0
  78. package/src/avm/avm_simulator.ts +89 -0
  79. package/src/avm/errors.ts +57 -0
  80. package/src/avm/fixtures/index.ts +90 -0
  81. package/src/avm/journal/host_storage.ts +20 -0
  82. package/src/avm/journal/index.ts +2 -0
  83. package/src/avm/journal/journal.ts +266 -0
  84. package/src/avm/opcodes/.eslintrc.cjs +8 -0
  85. package/src/avm/opcodes/accrued_substate.ts +92 -0
  86. package/src/avm/opcodes/addressing_mode.ts +66 -0
  87. package/src/avm/opcodes/arithmetic.ts +79 -0
  88. package/src/avm/opcodes/bitwise.ts +129 -0
  89. package/src/avm/opcodes/comparators.ts +72 -0
  90. package/src/avm/opcodes/control_flow.ts +129 -0
  91. package/src/avm/opcodes/environment_getters.ts +199 -0
  92. package/src/avm/opcodes/external_calls.ts +122 -0
  93. package/src/avm/opcodes/index.ts +10 -0
  94. package/src/avm/opcodes/instruction.ts +64 -0
  95. package/src/avm/opcodes/instruction_impl.ts +52 -0
  96. package/src/avm/opcodes/memory.ts +193 -0
  97. package/src/avm/opcodes/storage.ts +76 -0
  98. package/src/avm/serialization/buffer_cursor.ts +109 -0
  99. package/src/avm/serialization/bytecode_serialization.ts +172 -0
  100. package/src/avm/serialization/instruction_serialization.ts +167 -0
  101. package/src/avm/temporary_executor_migration.ts +108 -0
  102. package/src/client/client_execution_context.ts +472 -0
  103. package/src/client/db_oracle.ts +184 -0
  104. package/src/client/execution_note_cache.ts +90 -0
  105. package/src/client/execution_result.ts +89 -0
  106. package/src/client/index.ts +3 -0
  107. package/src/client/pick_notes.ts +125 -0
  108. package/src/client/private_execution.ts +78 -0
  109. package/src/client/simulator.ts +316 -0
  110. package/src/client/unconstrained_execution.ts +49 -0
  111. package/src/client/view_data_oracle.ts +243 -0
  112. package/src/common/errors.ts +61 -0
  113. package/src/common/index.ts +3 -0
  114. package/src/common/packed_args_cache.ts +55 -0
  115. package/src/common/side_effect_counter.ts +12 -0
  116. package/src/index.ts +3 -0
  117. package/src/public/db.ts +85 -0
  118. package/src/public/execution.ts +137 -0
  119. package/src/public/executor.ts +158 -0
  120. package/src/public/index.ts +9 -0
  121. package/src/public/public_execution_context.ts +217 -0
  122. package/src/public/state_actions.ts +100 -0
  123. package/src/test/utils.ts +38 -0
  124. package/src/utils.ts +18 -0
@@ -0,0 +1,332 @@
1
+ import { MerkleTreeId, UnencryptedL2Log } from '@aztec/circuit-types';
2
+ import { RETURN_VALUES_LENGTH } from '@aztec/circuits.js';
3
+ import { EventSelector, FunctionSelector } from '@aztec/foundation/abi';
4
+ import { AztecAddress } from '@aztec/foundation/aztec-address';
5
+ import { padArrayEnd } from '@aztec/foundation/collection';
6
+ import { Fr, Point } from '@aztec/foundation/fields';
7
+ import { createDebugLogger } from '@aztec/foundation/log';
8
+
9
+ import { ACVMField } from '../acvm_types.js';
10
+ import { frToNumber, fromACVMField } from '../deserialize.js';
11
+ import { toACVMField, toAcvmEnqueuePublicFunctionResult } from '../serialize.js';
12
+ import { acvmFieldMessageToString, oracleDebugCallToFormattedStr } from './debug.js';
13
+ import { TypedOracle } from './typed_oracle.js';
14
+
15
+ /**
16
+ * A data source that has all the apis required by Aztec.nr.
17
+ */
18
+ export class Oracle {
19
+ constructor(private typedOracle: TypedOracle, private log = createDebugLogger('aztec:simulator:oracle')) {}
20
+
21
+ getRandomField(): ACVMField {
22
+ const val = this.typedOracle.getRandomField();
23
+ return toACVMField(val);
24
+ }
25
+
26
+ async packArguments(args: ACVMField[]): Promise<ACVMField> {
27
+ const packed = await this.typedOracle.packArguments(args.map(fromACVMField));
28
+ return toACVMField(packed);
29
+ }
30
+
31
+ async getNullifierKeyPair([accountAddress]: ACVMField[]): Promise<ACVMField[]> {
32
+ const { publicKey, secretKey } = await this.typedOracle.getNullifierKeyPair(fromACVMField(accountAddress));
33
+ return [
34
+ toACVMField(publicKey.x),
35
+ toACVMField(publicKey.y),
36
+ toACVMField(secretKey.high),
37
+ toACVMField(secretKey.low),
38
+ ];
39
+ }
40
+
41
+ async getPublicKeyAndPartialAddress([address]: ACVMField[]) {
42
+ const { publicKey, partialAddress } = await this.typedOracle.getCompleteAddress(
43
+ AztecAddress.fromField(fromACVMField(address)),
44
+ );
45
+ return [publicKey.x, publicKey.y, partialAddress].map(toACVMField);
46
+ }
47
+
48
+ async getMembershipWitness(
49
+ [blockNumber]: ACVMField[],
50
+ [treeId]: ACVMField[],
51
+ [leafValue]: ACVMField[],
52
+ ): Promise<ACVMField[]> {
53
+ const parsedBlockNumber = frToNumber(fromACVMField(blockNumber));
54
+ const parsedTreeId = frToNumber(fromACVMField(treeId));
55
+ const parsedLeafValue = fromACVMField(leafValue);
56
+
57
+ const witness = await this.typedOracle.getMembershipWitness(parsedBlockNumber, parsedTreeId, parsedLeafValue);
58
+ if (!witness) {
59
+ throw new Error(
60
+ `Leaf ${leafValue} not found in the tree ${MerkleTreeId[parsedTreeId]} at block ${parsedBlockNumber}.`,
61
+ );
62
+ }
63
+ return witness.map(toACVMField);
64
+ }
65
+
66
+ async getSiblingPath(
67
+ [blockNumber]: ACVMField[],
68
+ [treeId]: ACVMField[],
69
+ [leafIndex]: ACVMField[],
70
+ ): Promise<ACVMField[]> {
71
+ const parsedBlockNumber = frToNumber(fromACVMField(blockNumber));
72
+ const parsedTreeId = frToNumber(fromACVMField(treeId));
73
+ const parsedLeafIndex = fromACVMField(leafIndex);
74
+
75
+ const path = await this.typedOracle.getSiblingPath(parsedBlockNumber, parsedTreeId, parsedLeafIndex);
76
+ return path.map(toACVMField);
77
+ }
78
+
79
+ async getNullifierMembershipWitness(
80
+ [blockNumber]: ACVMField[],
81
+ [nullifier]: ACVMField[], // nullifier, we try to find the witness for (to prove inclusion)
82
+ ): Promise<ACVMField[]> {
83
+ const parsedBlockNumber = frToNumber(fromACVMField(blockNumber));
84
+ const parsedNullifier = fromACVMField(nullifier);
85
+
86
+ const witness = await this.typedOracle.getNullifierMembershipWitness(parsedBlockNumber, parsedNullifier);
87
+ if (!witness) {
88
+ throw new Error(
89
+ `Low nullifier witness not found for nullifier ${parsedNullifier} at block ${parsedBlockNumber}.`,
90
+ );
91
+ }
92
+ return witness.toFields().map(toACVMField);
93
+ }
94
+
95
+ async getLowNullifierMembershipWitness(
96
+ [blockNumber]: ACVMField[],
97
+ [nullifier]: ACVMField[], // nullifier, we try to find the low nullifier witness for (to prove non-inclusion)
98
+ ): Promise<ACVMField[]> {
99
+ const parsedBlockNumber = frToNumber(fromACVMField(blockNumber));
100
+ const parsedNullifier = fromACVMField(nullifier);
101
+
102
+ const witness = await this.typedOracle.getLowNullifierMembershipWitness(parsedBlockNumber, parsedNullifier);
103
+ if (!witness) {
104
+ throw new Error(
105
+ `Low nullifier witness not found for nullifier ${parsedNullifier} at block ${parsedBlockNumber}.`,
106
+ );
107
+ }
108
+ return witness.toFields().map(toACVMField);
109
+ }
110
+
111
+ async getPublicDataTreeWitness([blockNumber]: ACVMField[], [leafSlot]: ACVMField[]): Promise<ACVMField[]> {
112
+ const parsedBlockNumber = frToNumber(fromACVMField(blockNumber));
113
+ const parsedLeafSlot = fromACVMField(leafSlot);
114
+
115
+ const witness = await this.typedOracle.getPublicDataTreeWitness(parsedBlockNumber, parsedLeafSlot);
116
+ if (!witness) {
117
+ throw new Error(`Public data witness not found for slot ${parsedLeafSlot} at block ${parsedBlockNumber}.`);
118
+ }
119
+ return witness.toFields().map(toACVMField);
120
+ }
121
+
122
+ async getHeader([blockNumber]: ACVMField[]): Promise<ACVMField[]> {
123
+ const parsedBlockNumber = frToNumber(fromACVMField(blockNumber));
124
+
125
+ const header = await this.typedOracle.getHeader(parsedBlockNumber);
126
+ if (!header) {
127
+ throw new Error(`Block header not found for block ${parsedBlockNumber}.`);
128
+ }
129
+ return header.toFields().map(toACVMField);
130
+ }
131
+
132
+ async getAuthWitness([messageHash]: ACVMField[]): Promise<ACVMField[]> {
133
+ const messageHashField = fromACVMField(messageHash);
134
+ const witness = await this.typedOracle.getAuthWitness(messageHashField);
135
+ if (!witness) {
136
+ throw new Error(`Authorization not found for message hash ${messageHashField}`);
137
+ }
138
+ return witness.map(toACVMField);
139
+ }
140
+
141
+ async popCapsule(): Promise<ACVMField[]> {
142
+ const capsule = await this.typedOracle.popCapsule();
143
+ if (!capsule) {
144
+ throw new Error(`No capsules available`);
145
+ }
146
+ return capsule.map(toACVMField);
147
+ }
148
+
149
+ async getNotes(
150
+ [storageSlot]: ACVMField[],
151
+ [numSelects]: ACVMField[],
152
+ selectBy: ACVMField[],
153
+ selectValues: ACVMField[],
154
+ selectComparators: ACVMField[],
155
+ sortBy: ACVMField[],
156
+ sortOrder: ACVMField[],
157
+ [limit]: ACVMField[],
158
+ [offset]: ACVMField[],
159
+ [status]: ACVMField[],
160
+ [returnSize]: ACVMField[],
161
+ ): Promise<ACVMField[]> {
162
+ const noteDatas = await this.typedOracle.getNotes(
163
+ fromACVMField(storageSlot),
164
+ +numSelects,
165
+ selectBy.map(s => +s),
166
+ selectValues.map(fromACVMField),
167
+ selectComparators.map(s => +s),
168
+ sortBy.map(s => +s),
169
+ sortOrder.map(s => +s),
170
+ +limit,
171
+ +offset,
172
+ +status,
173
+ );
174
+
175
+ const noteLength = noteDatas?.[0]?.note.items.length ?? 0;
176
+ if (!noteDatas.every(({ note }) => noteLength === note.items.length)) {
177
+ throw new Error('Notes should all be the same length.');
178
+ }
179
+
180
+ const contractAddress = noteDatas[0]?.contractAddress ?? Fr.ZERO;
181
+
182
+ // Values indicates whether the note is settled or transient.
183
+ const noteTypes = {
184
+ isSettled: new Fr(0),
185
+ isTransient: new Fr(1),
186
+ };
187
+ const flattenData = noteDatas.flatMap(({ nonce, note, index }) => [
188
+ nonce,
189
+ index === undefined ? noteTypes.isTransient : noteTypes.isSettled,
190
+ ...note.items,
191
+ ]);
192
+
193
+ const returnFieldSize = +returnSize;
194
+ const returnData = [noteDatas.length, contractAddress, ...flattenData].map(v => toACVMField(v));
195
+ if (returnData.length > returnFieldSize) {
196
+ throw new Error(`Return data size too big. Maximum ${returnFieldSize} fields. Got ${flattenData.length}.`);
197
+ }
198
+
199
+ const paddedZeros = Array(returnFieldSize - returnData.length).fill(toACVMField(0));
200
+ return returnData.concat(paddedZeros);
201
+ }
202
+
203
+ notifyCreatedNote(
204
+ [storageSlot]: ACVMField[],
205
+ [noteTypeId]: ACVMField[],
206
+ note: ACVMField[],
207
+ [innerNoteHash]: ACVMField[],
208
+ ): ACVMField {
209
+ this.typedOracle.notifyCreatedNote(
210
+ fromACVMField(storageSlot),
211
+ fromACVMField(noteTypeId),
212
+ note.map(fromACVMField),
213
+ fromACVMField(innerNoteHash),
214
+ );
215
+ return toACVMField(0);
216
+ }
217
+
218
+ async notifyNullifiedNote([innerNullifier]: ACVMField[], [innerNoteHash]: ACVMField[]): Promise<ACVMField> {
219
+ await this.typedOracle.notifyNullifiedNote(fromACVMField(innerNullifier), fromACVMField(innerNoteHash));
220
+ return toACVMField(0);
221
+ }
222
+
223
+ async checkNullifierExists([innerNullifier]: ACVMField[]): Promise<ACVMField> {
224
+ const exists = await this.typedOracle.checkNullifierExists(fromACVMField(innerNullifier));
225
+ return toACVMField(exists);
226
+ }
227
+
228
+ async getL1ToL2Message([msgKey]: ACVMField[]): Promise<ACVMField[]> {
229
+ const message = await this.typedOracle.getL1ToL2Message(fromACVMField(msgKey));
230
+ return message.toFields().map(toACVMField);
231
+ }
232
+
233
+ async getPortalContractAddress([aztecAddress]: ACVMField[]): Promise<ACVMField> {
234
+ const contractAddress = AztecAddress.fromString(aztecAddress);
235
+ const portalContactAddress = await this.typedOracle.getPortalContractAddress(contractAddress);
236
+ return toACVMField(portalContactAddress);
237
+ }
238
+
239
+ async storageRead([startStorageSlot]: ACVMField[], [numberOfElements]: ACVMField[]): Promise<ACVMField[]> {
240
+ const values = await this.typedOracle.storageRead(fromACVMField(startStorageSlot), +numberOfElements);
241
+ return values.map(toACVMField);
242
+ }
243
+
244
+ async storageWrite([startStorageSlot]: ACVMField[], values: ACVMField[]): Promise<ACVMField[]> {
245
+ const newValues = await this.typedOracle.storageWrite(fromACVMField(startStorageSlot), values.map(fromACVMField));
246
+ return newValues.map(toACVMField);
247
+ }
248
+
249
+ emitEncryptedLog(
250
+ [contractAddress]: ACVMField[],
251
+ [storageSlot]: ACVMField[],
252
+ [noteTypeId]: ACVMField[],
253
+ [publicKeyX]: ACVMField[],
254
+ [publicKeyY]: ACVMField[],
255
+ log: ACVMField[],
256
+ ): ACVMField {
257
+ const publicKey = new Point(fromACVMField(publicKeyX), fromACVMField(publicKeyY));
258
+ this.typedOracle.emitEncryptedLog(
259
+ AztecAddress.fromString(contractAddress),
260
+ Fr.fromString(storageSlot),
261
+ Fr.fromString(noteTypeId),
262
+ publicKey,
263
+ log.map(fromACVMField),
264
+ );
265
+ return toACVMField(0);
266
+ }
267
+
268
+ emitUnencryptedLog([contractAddress]: ACVMField[], [eventSelector]: ACVMField[], message: ACVMField[]): ACVMField {
269
+ const logPayload = Buffer.concat(message.map(fromACVMField).map(f => f.toBuffer()));
270
+ const log = new UnencryptedL2Log(
271
+ AztecAddress.fromString(contractAddress),
272
+ EventSelector.fromField(fromACVMField(eventSelector)),
273
+ logPayload,
274
+ );
275
+
276
+ this.typedOracle.emitUnencryptedLog(log);
277
+ return toACVMField(0);
278
+ }
279
+
280
+ debugLog(...args: ACVMField[][]): ACVMField {
281
+ this.log(oracleDebugCallToFormattedStr(args));
282
+ return toACVMField(0);
283
+ }
284
+
285
+ debugLogWithPrefix(arg0: ACVMField[], ...args: ACVMField[][]): ACVMField {
286
+ this.log(`${acvmFieldMessageToString(arg0)}: ${oracleDebugCallToFormattedStr(args)}`);
287
+ return toACVMField(0);
288
+ }
289
+
290
+ async callPrivateFunction(
291
+ [contractAddress]: ACVMField[],
292
+ [functionSelector]: ACVMField[],
293
+ [argsHash]: ACVMField[],
294
+ [sideffectCounter]: ACVMField[],
295
+ ): Promise<ACVMField[]> {
296
+ const callStackItem = await this.typedOracle.callPrivateFunction(
297
+ AztecAddress.fromField(fromACVMField(contractAddress)),
298
+ FunctionSelector.fromField(fromACVMField(functionSelector)),
299
+ fromACVMField(argsHash),
300
+ frToNumber(fromACVMField(sideffectCounter)),
301
+ );
302
+ return callStackItem.toFields().map(toACVMField);
303
+ }
304
+
305
+ async callPublicFunction(
306
+ [contractAddress]: ACVMField[],
307
+ [functionSelector]: ACVMField[],
308
+ [argsHash]: ACVMField[],
309
+ ): Promise<ACVMField[]> {
310
+ const returnValues = await this.typedOracle.callPublicFunction(
311
+ AztecAddress.fromField(fromACVMField(contractAddress)),
312
+ FunctionSelector.fromField(fromACVMField(functionSelector)),
313
+ fromACVMField(argsHash),
314
+ );
315
+ return padArrayEnd(returnValues, Fr.ZERO, RETURN_VALUES_LENGTH).map(toACVMField);
316
+ }
317
+
318
+ async enqueuePublicFunctionCall(
319
+ [contractAddress]: ACVMField[],
320
+ [functionSelector]: ACVMField[],
321
+ [argsHash]: ACVMField[],
322
+ [sideffectCounter]: ACVMField[],
323
+ ) {
324
+ const enqueuedRequest = await this.typedOracle.enqueuePublicFunctionCall(
325
+ AztecAddress.fromString(contractAddress),
326
+ FunctionSelector.fromField(fromACVMField(functionSelector)),
327
+ fromACVMField(argsHash),
328
+ frToNumber(fromACVMField(sideffectCounter)),
329
+ );
330
+ return toAcvmEnqueuePublicFunctionResult(enqueuedRequest);
331
+ }
332
+ }
@@ -0,0 +1,217 @@
1
+ import {
2
+ CompleteAddress,
3
+ L1ToL2Message,
4
+ MerkleTreeId,
5
+ Note,
6
+ NoteStatus,
7
+ NullifierMembershipWitness,
8
+ PublicDataWitness,
9
+ PublicKey,
10
+ SiblingPath,
11
+ UnencryptedL2Log,
12
+ } from '@aztec/circuit-types';
13
+ import {
14
+ GrumpkinPrivateKey,
15
+ Header,
16
+ L1_TO_L2_MSG_TREE_HEIGHT,
17
+ PrivateCallStackItem,
18
+ PublicCallRequest,
19
+ } from '@aztec/circuits.js';
20
+ import { FunctionSelector } from '@aztec/foundation/abi';
21
+ import { AztecAddress } from '@aztec/foundation/aztec-address';
22
+ import { EthAddress } from '@aztec/foundation/eth-address';
23
+ import { Fr } from '@aztec/foundation/fields';
24
+
25
+ /**
26
+ * A pair of public key and secret key.
27
+ */
28
+ export interface KeyPair {
29
+ /**
30
+ * Public key.
31
+ */
32
+ publicKey: PublicKey;
33
+ /**
34
+ * Secret Key.
35
+ */
36
+ secretKey: GrumpkinPrivateKey;
37
+ }
38
+
39
+ /**
40
+ * Information about a note needed during execution.
41
+ */
42
+ export interface NoteData {
43
+ /** The note. */
44
+ note: Note;
45
+ /** The contract address of the note. */
46
+ contractAddress: AztecAddress;
47
+ /** The storage slot of the note. */
48
+ storageSlot: Fr;
49
+ /** The nonce of the note. */
50
+ nonce: Fr;
51
+ /** The inner note hash of the note. */
52
+ innerNoteHash: Fr;
53
+ /** The corresponding nullifier of the note. Undefined for pending notes. */
54
+ siloedNullifier?: Fr;
55
+ /** The note's leaf index in the note hash tree. Undefined for pending notes. */
56
+ index?: bigint;
57
+ }
58
+
59
+ export class MessageLoadOracleInputs<N extends number> {
60
+ constructor(
61
+ /** The message. */
62
+ public message: L1ToL2Message,
63
+ /** The index of the message commitment in the merkle tree. */
64
+ public index: bigint,
65
+ /** The path in the merkle tree to the message. */
66
+ public siblingPath: SiblingPath<N>,
67
+ ) {}
68
+
69
+ toFields(): Fr[] {
70
+ return [...this.message.toFields(), new Fr(this.index), ...this.siblingPath.toFields()];
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Oracle with typed parameters and typed return values.
76
+ * Methods that require read and/or write will have to be implemented based on the context (public, private, or view)
77
+ * and are unavailable by default.
78
+ */
79
+ export abstract class TypedOracle {
80
+ getRandomField(): Fr {
81
+ return Fr.random();
82
+ }
83
+
84
+ packArguments(_args: Fr[]): Promise<Fr> {
85
+ throw new Error('Not available.');
86
+ }
87
+
88
+ getNullifierKeyPair(_accountAddress: AztecAddress): Promise<KeyPair> {
89
+ throw new Error('Not available.');
90
+ }
91
+
92
+ getPublicKeyAndPartialAddress(_address: AztecAddress): Promise<Fr[] | undefined> {
93
+ throw new Error('Not available.');
94
+ }
95
+
96
+ getMembershipWitness(_blockNumber: number, _treeId: MerkleTreeId, _leafValue: Fr): Promise<Fr[] | undefined> {
97
+ throw new Error('Not available.');
98
+ }
99
+
100
+ getSiblingPath(_blockNumber: number, _treeId: MerkleTreeId, _leafIndex: Fr): Promise<Fr[]> {
101
+ throw new Error('Not available.');
102
+ }
103
+
104
+ getNullifierMembershipWitness(_blockNumber: number, _nullifier: Fr): Promise<NullifierMembershipWitness | undefined> {
105
+ throw new Error('Not available.');
106
+ }
107
+
108
+ getPublicDataTreeWitness(_blockNumber: number, _leafSlot: Fr): Promise<PublicDataWitness | undefined> {
109
+ throw new Error('Not available.');
110
+ }
111
+
112
+ getLowNullifierMembershipWitness(
113
+ _blockNumber: number,
114
+ _nullifier: Fr,
115
+ ): Promise<NullifierMembershipWitness | undefined> {
116
+ throw new Error('Not available.');
117
+ }
118
+
119
+ getHeader(_blockNumber: number): Promise<Header | undefined> {
120
+ throw new Error('Not available.');
121
+ }
122
+
123
+ getCompleteAddress(_address: AztecAddress): Promise<CompleteAddress> {
124
+ throw new Error('Not available.');
125
+ }
126
+
127
+ getAuthWitness(_messageHash: Fr): Promise<Fr[] | undefined> {
128
+ throw new Error('Not available.');
129
+ }
130
+
131
+ popCapsule(): Promise<Fr[]> {
132
+ throw new Error('Not available.');
133
+ }
134
+
135
+ getNotes(
136
+ _storageSlot: Fr,
137
+ _numSelects: number,
138
+ _selectBy: number[],
139
+ _selectValues: Fr[],
140
+ _selectComparators: number[],
141
+ _sortBy: number[],
142
+ _sortOrder: number[],
143
+ _limit: number,
144
+ _offset: number,
145
+ _status: NoteStatus,
146
+ ): Promise<NoteData[]> {
147
+ throw new Error('Not available.');
148
+ }
149
+
150
+ notifyCreatedNote(_storageSlot: Fr, _noteTypeId: Fr, _note: Fr[], _innerNoteHash: Fr): void {
151
+ throw new Error('Not available.');
152
+ }
153
+
154
+ notifyNullifiedNote(_innerNullifier: Fr, _innerNoteHash: Fr): Promise<void> {
155
+ throw new Error('Not available.');
156
+ }
157
+
158
+ checkNullifierExists(_innerNullifier: Fr): Promise<boolean> {
159
+ throw new Error('Not available.');
160
+ }
161
+
162
+ getL1ToL2Message(_msgKey: Fr): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>> {
163
+ throw new Error('Not available.');
164
+ }
165
+
166
+ getPortalContractAddress(_contractAddress: AztecAddress): Promise<EthAddress> {
167
+ throw new Error('Not available.');
168
+ }
169
+
170
+ storageRead(_startStorageSlot: Fr, _numberOfElements: number): Promise<Fr[]> {
171
+ throw new Error('Not available.');
172
+ }
173
+
174
+ storageWrite(_startStorageSlot: Fr, _values: Fr[]): Promise<Fr[]> {
175
+ throw new Error('Not available.');
176
+ }
177
+
178
+ emitEncryptedLog(
179
+ _contractAddress: AztecAddress,
180
+ _storageSlot: Fr,
181
+ _noteTypeId: Fr,
182
+ _publicKey: PublicKey,
183
+ _log: Fr[],
184
+ ): void {
185
+ throw new Error('Not available.');
186
+ }
187
+
188
+ emitUnencryptedLog(_log: UnencryptedL2Log): void {
189
+ throw new Error('Not available.');
190
+ }
191
+
192
+ callPrivateFunction(
193
+ _targetContractAddress: AztecAddress,
194
+ _functionSelector: FunctionSelector,
195
+ _argsHash: Fr,
196
+ _sideffectCounter: number,
197
+ ): Promise<PrivateCallStackItem> {
198
+ throw new Error('Not available.');
199
+ }
200
+
201
+ callPublicFunction(
202
+ _targetContractAddress: AztecAddress,
203
+ _functionSelector: FunctionSelector,
204
+ _argsHash: Fr,
205
+ ): Promise<Fr[]> {
206
+ throw new Error('Not available.');
207
+ }
208
+
209
+ enqueuePublicFunctionCall(
210
+ _targetContractAddress: AztecAddress,
211
+ _functionSelector: FunctionSelector,
212
+ _argsHash: Fr,
213
+ _sideffectCounter: number,
214
+ ): Promise<PublicCallRequest> {
215
+ throw new Error('Not available.');
216
+ }
217
+ }
@@ -0,0 +1,75 @@
1
+ import { PublicCallRequest } from '@aztec/circuits.js';
2
+ import { AztecAddress } from '@aztec/foundation/aztec-address';
3
+ import { EthAddress } from '@aztec/foundation/eth-address';
4
+ import { Fr } from '@aztec/foundation/fields';
5
+
6
+ import { ACVMField } from './acvm_types.js';
7
+
8
+ /**
9
+ * Adapts the buffer to the field size.
10
+ * @param originalBuf - The buffer to adapt.
11
+ * @returns The adapted buffer.
12
+ */
13
+ function adaptBufferSize(originalBuf: Buffer) {
14
+ const buffer = Buffer.alloc(Fr.SIZE_IN_BYTES);
15
+ if (originalBuf.length > buffer.length) {
16
+ throw new Error('Buffer does not fit in field');
17
+ }
18
+ originalBuf.copy(buffer, buffer.length - originalBuf.length);
19
+ return buffer;
20
+ }
21
+
22
+ /**
23
+ * Converts a value to an ACVM field.
24
+ * @param value - The value to convert.
25
+ * @returns The ACVM field.
26
+ */
27
+ export function toACVMField(
28
+ value: AztecAddress | EthAddress | Fr | Buffer | boolean | number | bigint | ACVMField,
29
+ ): ACVMField {
30
+ let buffer;
31
+ if (Buffer.isBuffer(value)) {
32
+ buffer = value;
33
+ } else if (typeof value === 'boolean' || typeof value === 'number' || typeof value === 'bigint') {
34
+ buffer = new Fr(value).toBuffer();
35
+ } else if (typeof value === 'string') {
36
+ buffer = Fr.fromString(value).toBuffer();
37
+ } else {
38
+ buffer = value.toBuffer();
39
+ }
40
+ return `0x${adaptBufferSize(buffer).toString('hex')}`;
41
+ }
42
+
43
+ // Utilities to write TS classes to ACVM Field arrays
44
+ // In the order that the ACVM expects them
45
+
46
+ /**
47
+ * Converts a public call stack item with the request for executing a public function to
48
+ * a set of ACVM fields accepted by the enqueue_public_function_call_oracle Aztec.nr function.
49
+ * Note that only the fields related to the request are serialized: those related to the result
50
+ * are empty since this is just an execution request, so we don't send them to the circuit.
51
+ * @param item - The public call stack item to serialize to be passed onto Noir.
52
+ * @returns The fields expected by the enqueue_public_function_call_oracle Aztec.nr function.
53
+ * TODO(#4380): Nuke this and replace it with PublicCallRequest.toFields()
54
+ */
55
+ export function toAcvmEnqueuePublicFunctionResult(item: PublicCallRequest): ACVMField[] {
56
+ return [
57
+ item.contractAddress.toField(),
58
+ ...item.functionData.toFields(),
59
+ ...item.callContext.toFields(),
60
+ item.getArgsHash(),
61
+ ].map(toACVMField);
62
+ }
63
+
64
+ /**
65
+ * Inserts a list of ACVM fields to a witness.
66
+ * @param witnessStartIndex - The index where to start inserting the fields.
67
+ * @param fields - The fields to insert.
68
+ * @returns The witness.
69
+ */
70
+ export function toACVMWitness(witnessStartIndex: number, fields: Parameters<typeof toACVMField>[0][]) {
71
+ return fields.reduce((witness, field, index) => {
72
+ witness.set(index + witnessStartIndex, toACVMField(field));
73
+ return witness;
74
+ }, new Map<number, ACVMField>());
75
+ }
@@ -0,0 +1,63 @@
1
+ import { AztecAddress } from '@aztec/circuits.js';
2
+ import { Fr } from '@aztec/foundation/fields';
3
+
4
+ import { AvmExecutionEnvironment } from './avm_execution_environment.js';
5
+ import { AvmMachineState } from './avm_machine_state.js';
6
+ import { AvmWorldStateJournal } from './journal/journal.js';
7
+
8
+ /**
9
+ * An execution context includes the information necessary to initiate AVM
10
+ * execution along with all state maintained by the AVM throughout execution.
11
+ */
12
+ export class AvmContext {
13
+ /**
14
+ * Create a new AVM context
15
+ * @param worldState - Manages mutable state during execution - (caching, fetching)
16
+ * @param environment - Contains constant variables provided by the kernel
17
+ * @param machineState - VM state that is modified on an instruction-by-instruction basis
18
+ * @returns new AvmContext instance
19
+ */
20
+ constructor(
21
+ public worldState: AvmWorldStateJournal,
22
+ public environment: AvmExecutionEnvironment,
23
+ public machineState: AvmMachineState,
24
+ ) {}
25
+
26
+ /**
27
+ * Prepare a new AVM context that will be ready for an external/nested call
28
+ * - Fork the world state journal
29
+ * - Derive a machine state from the current state
30
+ * - E.g., gas metering is preserved but pc is reset
31
+ * - Derive an execution environment from the caller/parent
32
+ * - Alter both address and storageAddress
33
+ *
34
+ * @param address - The contract instance to initialize a context for
35
+ * @param calldata - Data/arguments for nested call
36
+ * @returns new AvmContext instance
37
+ */
38
+ public createNestedContractCallContext(address: AztecAddress, calldata: Fr[]): AvmContext {
39
+ const newExecutionEnvironment = this.environment.deriveEnvironmentForNestedCall(address, calldata);
40
+ const forkedWorldState = this.worldState.fork();
41
+ const machineState = AvmMachineState.fromState(this.machineState);
42
+ return new AvmContext(forkedWorldState, newExecutionEnvironment, machineState);
43
+ }
44
+
45
+ /**
46
+ * Prepare a new AVM context that will be ready for an external/nested static call
47
+ * - Fork the world state journal
48
+ * - Derive a machine state from the current state
49
+ * - E.g., gas metering is preserved but pc is reset
50
+ * - Derive an execution environment from the caller/parent
51
+ * - Alter both address and storageAddress
52
+ *
53
+ * @param address - The contract instance to initialize a context for
54
+ * @param calldata - Data/arguments for nested call
55
+ * @returns new AvmContext instance
56
+ */
57
+ public createNestedContractStaticCallContext(address: AztecAddress, calldata: Fr[]): AvmContext {
58
+ const newExecutionEnvironment = this.environment.deriveEnvironmentForNestedStaticCall(address, calldata);
59
+ const forkedWorldState = this.worldState.fork();
60
+ const machineState = AvmMachineState.fromState(this.machineState);
61
+ return new AvmContext(forkedWorldState, newExecutionEnvironment, machineState);
62
+ }
63
+ }