@aztec/txe 0.0.0-test.1 → 0.0.1-commit.b655e406

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 (86) hide show
  1. package/dest/bin/index.js +3 -2
  2. package/dest/index.d.ts.map +1 -1
  3. package/dest/index.js +78 -49
  4. package/dest/oracle/interfaces.d.ts +54 -0
  5. package/dest/oracle/interfaces.d.ts.map +1 -0
  6. package/dest/oracle/interfaces.js +3 -0
  7. package/dest/oracle/txe_oracle_public_context.d.ts +34 -0
  8. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -0
  9. package/dest/oracle/txe_oracle_public_context.js +124 -0
  10. package/dest/oracle/txe_oracle_top_level_context.d.ts +56 -0
  11. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -0
  12. package/dest/oracle/txe_oracle_top_level_context.js +423 -0
  13. package/dest/rpc_translator.d.ts +237 -0
  14. package/dest/rpc_translator.d.ts.map +1 -0
  15. package/dest/rpc_translator.js +617 -0
  16. package/dest/state_machine/archiver.d.ts +61 -0
  17. package/dest/state_machine/archiver.d.ts.map +1 -0
  18. package/dest/state_machine/archiver.js +118 -0
  19. package/dest/state_machine/dummy_p2p_client.d.ts +52 -0
  20. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -0
  21. package/dest/state_machine/dummy_p2p_client.js +133 -0
  22. package/dest/state_machine/global_variable_builder.d.ts +9 -0
  23. package/dest/state_machine/global_variable_builder.d.ts.map +1 -0
  24. package/dest/state_machine/global_variable_builder.js +10 -0
  25. package/dest/state_machine/index.d.ts +16 -0
  26. package/dest/state_machine/index.d.ts.map +1 -0
  27. package/dest/state_machine/index.js +51 -0
  28. package/dest/state_machine/mock_epoch_cache.d.ts +25 -0
  29. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -0
  30. package/dest/state_machine/mock_epoch_cache.js +50 -0
  31. package/dest/state_machine/synchronizer.d.ts +32 -0
  32. package/dest/state_machine/synchronizer.d.ts.map +1 -0
  33. package/dest/state_machine/synchronizer.js +58 -0
  34. package/dest/txe_session.d.ts +67 -0
  35. package/dest/txe_session.d.ts.map +1 -0
  36. package/dest/txe_session.js +253 -0
  37. package/dest/util/encoding.d.ts +26 -8
  38. package/dest/util/encoding.d.ts.map +1 -1
  39. package/dest/util/encoding.js +65 -10
  40. package/dest/util/txe_contract_data_provider.d.ts +12 -0
  41. package/dest/util/txe_contract_data_provider.d.ts.map +1 -0
  42. package/dest/util/txe_contract_data_provider.js +22 -0
  43. package/dest/util/txe_public_contract_data_source.d.ts +8 -8
  44. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  45. package/dest/util/txe_public_contract_data_source.js +36 -57
  46. package/dest/utils/block_creation.d.ts +13 -0
  47. package/dest/utils/block_creation.d.ts.map +1 -0
  48. package/dest/utils/block_creation.js +24 -0
  49. package/dest/utils/tx_effect_creation.d.ts +5 -0
  50. package/dest/utils/tx_effect_creation.d.ts.map +1 -0
  51. package/dest/utils/tx_effect_creation.js +16 -0
  52. package/package.json +27 -22
  53. package/src/bin/index.ts +3 -2
  54. package/src/index.ts +92 -64
  55. package/src/oracle/interfaces.ts +83 -0
  56. package/src/oracle/txe_oracle_public_context.ts +165 -0
  57. package/src/oracle/txe_oracle_top_level_context.ts +658 -0
  58. package/src/rpc_translator.ts +1013 -0
  59. package/src/state_machine/archiver.ts +151 -0
  60. package/src/state_machine/dummy_p2p_client.ts +197 -0
  61. package/src/state_machine/global_variable_builder.ts +20 -0
  62. package/src/state_machine/index.ts +77 -0
  63. package/src/state_machine/mock_epoch_cache.ts +67 -0
  64. package/src/state_machine/synchronizer.ts +87 -0
  65. package/src/txe_session.ts +432 -0
  66. package/src/util/encoding.ts +84 -10
  67. package/src/util/txe_contract_data_provider.ts +36 -0
  68. package/src/util/txe_public_contract_data_source.ts +40 -56
  69. package/src/utils/block_creation.ts +62 -0
  70. package/src/utils/tx_effect_creation.ts +37 -0
  71. package/dest/node/txe_node.d.ts +0 -358
  72. package/dest/node/txe_node.d.ts.map +0 -1
  73. package/dest/node/txe_node.js +0 -504
  74. package/dest/oracle/txe_oracle.d.ts +0 -152
  75. package/dest/oracle/txe_oracle.d.ts.map +0 -1
  76. package/dest/oracle/txe_oracle.js +0 -833
  77. package/dest/txe_service/txe_service.d.ts +0 -212
  78. package/dest/txe_service/txe_service.d.ts.map +0 -1
  79. package/dest/txe_service/txe_service.js +0 -572
  80. package/dest/util/txe_world_state_db.d.ts +0 -14
  81. package/dest/util/txe_world_state_db.d.ts.map +0 -1
  82. package/dest/util/txe_world_state_db.js +0 -27
  83. package/src/node/txe_node.ts +0 -725
  84. package/src/oracle/txe_oracle.ts +0 -1241
  85. package/src/txe_service/txe_service.ts +0 -749
  86. package/src/util/txe_world_state_db.ts +0 -38
@@ -1,1241 +0,0 @@
1
- import { Body, L2Block, Note } from '@aztec/aztec.js';
2
- import {
3
- type L1_TO_L2_MSG_TREE_HEIGHT,
4
- MAX_NOTE_HASHES_PER_TX,
5
- MAX_NULLIFIERS_PER_TX,
6
- NULLIFIER_SUBTREE_HEIGHT,
7
- type NULLIFIER_TREE_HEIGHT,
8
- NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
9
- PRIVATE_CONTEXT_INPUTS_LENGTH,
10
- type PUBLIC_DATA_TREE_HEIGHT,
11
- PUBLIC_DISPATCH_SELECTOR,
12
- } from '@aztec/constants';
13
- import { padArrayEnd } from '@aztec/foundation/collection';
14
- import { Aes128, Schnorr, poseidon2Hash } from '@aztec/foundation/crypto';
15
- import { Fr } from '@aztec/foundation/fields';
16
- import { type Logger, applyStringFormatting } from '@aztec/foundation/log';
17
- import { Timer } from '@aztec/foundation/timer';
18
- import { KeyStore } from '@aztec/key-store';
19
- import type { AztecAsyncKVStore } from '@aztec/kv-store';
20
- import type { ProtocolContract } from '@aztec/protocol-contracts';
21
- import {
22
- AddressDataProvider,
23
- AuthWitnessDataProvider,
24
- CapsuleDataProvider,
25
- ContractDataProvider,
26
- NoteDataProvider,
27
- PXEOracleInterface,
28
- SyncDataProvider,
29
- TaggingDataProvider,
30
- enrichPublicSimulationError,
31
- } from '@aztec/pxe/server';
32
- import {
33
- ExecutionNoteCache,
34
- HashedValuesCache,
35
- type MessageLoadOracleInputs,
36
- type NoteData,
37
- Oracle,
38
- type TypedOracle,
39
- WASMSimulator,
40
- extractCallStack,
41
- extractPrivateCircuitPublicInputs,
42
- pickNotes,
43
- toACVMWitness,
44
- witnessMapToFields,
45
- } from '@aztec/simulator/client';
46
- import { createTxForPublicCalls } from '@aztec/simulator/public/fixtures';
47
- import {
48
- ExecutionError,
49
- type PublicTxResult,
50
- PublicTxSimulator,
51
- createSimulationError,
52
- resolveAssertionMessageFromError,
53
- } from '@aztec/simulator/server';
54
- import {
55
- type ContractArtifact,
56
- type FunctionAbi,
57
- FunctionSelector,
58
- type NoteSelector,
59
- countArgumentsSize,
60
- } from '@aztec/stdlib/abi';
61
- import { AuthWitness } from '@aztec/stdlib/auth-witness';
62
- import { PublicDataWrite } from '@aztec/stdlib/avm';
63
- import { AztecAddress } from '@aztec/stdlib/aztec-address';
64
- import type { ContractInstance, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
65
- import { SimulationError } from '@aztec/stdlib/errors';
66
- import { Gas, GasFees } from '@aztec/stdlib/gas';
67
- import {
68
- computeNoteHashNonce,
69
- computePublicDataTreeLeafSlot,
70
- computeUniqueNoteHash,
71
- siloNoteHash,
72
- siloNullifier,
73
- } from '@aztec/stdlib/hash';
74
- import type { MerkleTreeReadOperations, MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
75
- import { type KeyValidationRequest, PrivateContextInputs } from '@aztec/stdlib/kernel';
76
- import { deriveKeys } from '@aztec/stdlib/keys';
77
- import { ContractClassLog, LogWithTxData } from '@aztec/stdlib/logs';
78
- import { IndexedTaggingSecret, type PrivateLog, type PublicLog } from '@aztec/stdlib/logs';
79
- import type { NoteStatus } from '@aztec/stdlib/note';
80
- import type { CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';
81
- import {
82
- makeAppendOnlyTreeSnapshot,
83
- makeContentCommitment,
84
- makeGlobalVariables,
85
- makeHeader,
86
- } from '@aztec/stdlib/testing';
87
- import {
88
- AppendOnlyTreeSnapshot,
89
- MerkleTreeId,
90
- type NullifierLeafPreimage,
91
- NullifierMembershipWitness,
92
- PublicDataTreeLeaf,
93
- type PublicDataTreeLeafPreimage,
94
- PublicDataWitness,
95
- } from '@aztec/stdlib/trees';
96
- import { BlockHeader, CallContext, GlobalVariables, PublicExecutionRequest, TxEffect, TxHash } from '@aztec/stdlib/tx';
97
- import { ForkCheckpoint, NativeWorldStateService } from '@aztec/world-state/native';
98
-
99
- import { TXENode } from '../node/txe_node.js';
100
- import { TXEAccountDataProvider } from '../util/txe_account_data_provider.js';
101
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
102
- import { TXEWorldStateDB } from '../util/txe_world_state_db.js';
103
-
104
- export class TXE implements TypedOracle {
105
- private blockNumber = 1;
106
- private sideEffectCounter = 0;
107
- private msgSender: AztecAddress;
108
- private functionSelector = FunctionSelector.fromField(new Fr(0));
109
- private isStaticCall = false;
110
- // Return/revert data of the latest nested call.
111
- private nestedCallReturndata: Fr[] = [];
112
- private nestedCallSuccess: boolean = false;
113
-
114
- private pxeOracleInterface: PXEOracleInterface;
115
-
116
- private publicDataWrites: PublicDataWrite[] = [];
117
- private uniqueNoteHashesFromPublic: Fr[] = [];
118
- private siloedNullifiersFromPublic: Fr[] = [];
119
- private privateLogs: PrivateLog[] = [];
120
- private publicLogs: PublicLog[] = [];
121
-
122
- private committedBlocks = new Set<number>();
123
-
124
- private VERSION = 1;
125
- private CHAIN_ID = 1;
126
-
127
- private node: TXENode;
128
-
129
- private simulationProvider = new WASMSimulator();
130
-
131
- private noteCache: ExecutionNoteCache;
132
-
133
- private constructor(
134
- private logger: Logger,
135
- private keyStore: KeyStore,
136
- private contractDataProvider: ContractDataProvider,
137
- private noteDataProvider: NoteDataProvider,
138
- private capsuleDataProvider: CapsuleDataProvider,
139
- private syncDataProvider: SyncDataProvider,
140
- private taggingDataProvider: TaggingDataProvider,
141
- private addressDataProvider: AddressDataProvider,
142
- private authWitnessDataProvider: AuthWitnessDataProvider,
143
- private accountDataProvider: TXEAccountDataProvider,
144
- private executionCache: HashedValuesCache,
145
- private contractAddress: AztecAddress,
146
- private nativeWorldStateService: NativeWorldStateService,
147
- private baseFork: MerkleTreeWriteOperations,
148
- ) {
149
- this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
150
-
151
- this.node = new TXENode(this.blockNumber, this.VERSION, this.CHAIN_ID, nativeWorldStateService, baseFork);
152
- // Default msg_sender (for entrypoints) is now Fr.max_value rather than 0 addr (see #7190 & #7404)
153
- this.msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE);
154
-
155
- this.pxeOracleInterface = new PXEOracleInterface(
156
- this.node,
157
- this.keyStore,
158
- this.simulationProvider,
159
- this.contractDataProvider,
160
- this.noteDataProvider,
161
- this.capsuleDataProvider,
162
- this.syncDataProvider,
163
- this.taggingDataProvider,
164
- this.addressDataProvider,
165
- this.authWitnessDataProvider,
166
- this.logger,
167
- );
168
- }
169
-
170
- static async create(logger: Logger, store: AztecAsyncKVStore, protocolContracts: ProtocolContract[]) {
171
- const executionCache = new HashedValuesCache();
172
- const nativeWorldStateService = await NativeWorldStateService.tmp();
173
- const baseFork = await nativeWorldStateService.fork();
174
-
175
- const addressDataProvider = new AddressDataProvider(store);
176
- const authWitnessDataProvider = new AuthWitnessDataProvider(store);
177
- const contractDataProvider = new ContractDataProvider(store);
178
- const noteDataProvider = await NoteDataProvider.create(store);
179
- const syncDataProvider = new SyncDataProvider(store);
180
- const taggingDataProvider = new TaggingDataProvider(store);
181
- const capsuleDataProvider = new CapsuleDataProvider(store);
182
- const keyStore = new KeyStore(store);
183
-
184
- const accountDataProvider = new TXEAccountDataProvider(store);
185
-
186
- // Register protocol contracts.
187
- for (const { contractClass, instance, artifact } of protocolContracts) {
188
- await contractDataProvider.addContractArtifact(contractClass.id, artifact);
189
- await contractDataProvider.addContractInstance(instance);
190
- }
191
-
192
- return new TXE(
193
- logger,
194
- keyStore,
195
- contractDataProvider,
196
- noteDataProvider,
197
- capsuleDataProvider,
198
- syncDataProvider,
199
- taggingDataProvider,
200
- addressDataProvider,
201
- authWitnessDataProvider,
202
- accountDataProvider,
203
- executionCache,
204
- await AztecAddress.random(),
205
- nativeWorldStateService,
206
- baseFork,
207
- );
208
- }
209
-
210
- // Utils
211
-
212
- getNativeWorldStateService() {
213
- return this.nativeWorldStateService;
214
- }
215
-
216
- getBaseFork() {
217
- return this.baseFork;
218
- }
219
-
220
- getChainId(): Promise<Fr> {
221
- return Promise.resolve(this.node.getChainId().then(id => new Fr(id)));
222
- }
223
-
224
- getVersion(): Promise<Fr> {
225
- return Promise.resolve(this.node.getVersion().then(v => new Fr(v)));
226
- }
227
-
228
- getMsgSender() {
229
- return this.msgSender;
230
- }
231
-
232
- getFunctionSelector() {
233
- return this.functionSelector;
234
- }
235
-
236
- setMsgSender(msgSender: AztecAddress) {
237
- this.msgSender = msgSender;
238
- }
239
-
240
- setFunctionSelector(functionSelector: FunctionSelector) {
241
- this.functionSelector = functionSelector;
242
- }
243
-
244
- getSideEffectsCounter() {
245
- return this.sideEffectCounter;
246
- }
247
-
248
- setSideEffectsCounter(sideEffectsCounter: number) {
249
- this.sideEffectCounter = sideEffectsCounter;
250
- }
251
-
252
- setContractAddress(contractAddress: AztecAddress) {
253
- this.contractAddress = contractAddress;
254
- }
255
-
256
- setBlockNumber(blockNumber: number) {
257
- this.blockNumber = blockNumber;
258
- this.node.setBlockNumber(blockNumber);
259
- }
260
-
261
- getContractDataProvider() {
262
- return this.contractDataProvider;
263
- }
264
-
265
- getKeyStore() {
266
- return this.keyStore;
267
- }
268
-
269
- getAccountDataProvider() {
270
- return this.accountDataProvider;
271
- }
272
-
273
- getAddressDataProvider() {
274
- return this.addressDataProvider;
275
- }
276
-
277
- async addContractInstance(contractInstance: ContractInstanceWithAddress) {
278
- await this.contractDataProvider.addContractInstance(contractInstance);
279
- }
280
-
281
- async addContractArtifact(contractClassId: Fr, artifact: ContractArtifact) {
282
- await this.contractDataProvider.addContractArtifact(contractClassId, artifact);
283
- }
284
-
285
- async getPrivateContextInputs(
286
- blockNumber: number,
287
- sideEffectsCounter = this.sideEffectCounter,
288
- isStaticCall = false,
289
- ) {
290
- if (blockNumber > this.blockNumber) {
291
- throw new Error(
292
- `Tried to request private context inputs for ${blockNumber}, which is greater than our current block number of ${this.blockNumber}`,
293
- );
294
- } else if (blockNumber === this.blockNumber) {
295
- this.logger.debug(
296
- `Tried to request private context inputs for ${blockNumber}, equal to current block of ${this.blockNumber}. Clamping to current block - 1.`,
297
- );
298
- blockNumber = this.blockNumber - 1;
299
- }
300
-
301
- const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
302
- const previousBlockState = this.nativeWorldStateService.getSnapshot(blockNumber - 1);
303
-
304
- const stateReference = await snap.getStateReference();
305
- const inputs = PrivateContextInputs.empty();
306
- inputs.txContext.chainId = new Fr(await this.node.getChainId());
307
- inputs.txContext.version = new Fr(await this.node.getVersion());
308
- inputs.historicalHeader.globalVariables.blockNumber = new Fr(blockNumber);
309
- inputs.historicalHeader.state = stateReference;
310
- inputs.historicalHeader.lastArchive.root = Fr.fromBuffer(
311
- (await previousBlockState.getTreeInfo(MerkleTreeId.ARCHIVE)).root,
312
- );
313
- inputs.callContext = new CallContext(this.msgSender, this.contractAddress, this.functionSelector, isStaticCall);
314
- inputs.startSideEffectCounter = sideEffectsCounter;
315
- return inputs;
316
- }
317
-
318
- deriveKeys(secret: Fr) {
319
- return deriveKeys(secret);
320
- }
321
-
322
- async addAuthWitness(address: AztecAddress, messageHash: Fr) {
323
- const account = await this.accountDataProvider.getAccount(address);
324
- const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
325
- const schnorr = new Schnorr();
326
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
327
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
328
- return this.authWitnessDataProvider.addAuthWitness(authWitness.requestHash, authWitness.witness);
329
- }
330
-
331
- async addPublicDataWrites(writes: PublicDataWrite[]) {
332
- this.publicDataWrites.push(...writes);
333
-
334
- await this.baseFork.sequentialInsert(
335
- MerkleTreeId.PUBLIC_DATA_TREE,
336
- writes.map(w => new PublicDataTreeLeaf(w.leafSlot, w.value).toBuffer()),
337
- );
338
- }
339
-
340
- async checkNullifiersNotInTree(contractAddress: AztecAddress, nullifiers: Fr[]) {
341
- const siloedNullifiers = await Promise.all(nullifiers.map(nullifier => siloNullifier(contractAddress, nullifier)));
342
- const db = this.baseFork;
343
- const nullifierIndexesInTree = await db.findLeafIndices(
344
- MerkleTreeId.NULLIFIER_TREE,
345
- siloedNullifiers.map(n => n.toBuffer()),
346
- );
347
- if (nullifierIndexesInTree.some(index => index !== undefined)) {
348
- throw new Error(`Rejecting tx for emitting duplicate nullifiers`);
349
- }
350
- }
351
-
352
- addSiloedNullifiersFromPublic(siloedNullifiers: Fr[]) {
353
- this.siloedNullifiersFromPublic.push(...siloedNullifiers);
354
- }
355
-
356
- addUniqueNoteHashesFromPublic(siloedNoteHashes: Fr[]) {
357
- this.uniqueNoteHashesFromPublic.push(...siloedNoteHashes);
358
- }
359
-
360
- async addPrivateLogs(contractAddress: AztecAddress, privateLogs: PrivateLog[]) {
361
- for (const privateLog of privateLogs) {
362
- privateLog.fields[0] = await poseidon2Hash([contractAddress, privateLog.fields[0]]);
363
- }
364
-
365
- this.privateLogs.push(...privateLogs);
366
- }
367
-
368
- addPublicLogs(logs: PublicLog[]) {
369
- logs.forEach(log => {
370
- try {
371
- // The first elt stores lengths => tag is in fields[1]
372
- const tag = log.log[1];
373
-
374
- this.logger.verbose(`Found tagged public log with tag ${tag.toString()} in block ${this.blockNumber}`);
375
- this.publicLogs.push(log);
376
- } catch (err) {
377
- this.logger.warn(`Failed to add tagged log to store: ${err}`);
378
- }
379
- });
380
- }
381
-
382
- // TypedOracle
383
-
384
- getBlockNumber() {
385
- return Promise.resolve(this.blockNumber);
386
- }
387
-
388
- getContractAddress() {
389
- return Promise.resolve(this.contractAddress);
390
- }
391
-
392
- setIsStaticCall(isStatic: boolean) {
393
- this.isStaticCall = isStatic;
394
- }
395
-
396
- getIsStaticCall() {
397
- return this.isStaticCall;
398
- }
399
-
400
- getRandomField() {
401
- return Fr.random();
402
- }
403
-
404
- storeInExecutionCache(values: Fr[]) {
405
- return this.executionCache.store(values);
406
- }
407
-
408
- loadFromExecutionCache(returnsHash: Fr) {
409
- return Promise.resolve(this.executionCache.getPreimage(returnsHash));
410
- }
411
-
412
- getKeyValidationRequest(pkMHash: Fr): Promise<KeyValidationRequest> {
413
- return this.keyStore.getKeyValidationRequest(pkMHash, this.contractAddress);
414
- }
415
-
416
- async getContractInstance(address: AztecAddress): Promise<ContractInstance> {
417
- const contractInstance = await this.contractDataProvider.getContractInstance(address);
418
- if (!contractInstance) {
419
- throw new Error(`Contract instance not found for address ${address}`);
420
- }
421
- return contractInstance;
422
- }
423
-
424
- async getMembershipWitness(blockNumber: number, treeId: MerkleTreeId, leafValue: Fr): Promise<Fr[] | undefined> {
425
- const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
426
- const index = (await snap.findLeafIndices(treeId, [leafValue.toBuffer()]))[0];
427
- if (index === undefined) {
428
- throw new Error(`Leaf value: ${leafValue} not found in ${MerkleTreeId[treeId]} at block ${blockNumber}`);
429
- }
430
- const siblingPath = await snap.getSiblingPath(treeId, index);
431
-
432
- return [new Fr(index), ...siblingPath.toFields()];
433
- }
434
-
435
- async getSiblingPath(blockNumber: number, treeId: MerkleTreeId, leafIndex: Fr) {
436
- const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
437
-
438
- const result = await snap.getSiblingPath(treeId, leafIndex.toBigInt());
439
- return result.toFields();
440
- }
441
-
442
- async getNullifierMembershipWitness(
443
- blockNumber: number,
444
- nullifier: Fr,
445
- ): Promise<NullifierMembershipWitness | undefined> {
446
- const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
447
-
448
- const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
449
- if (!index) {
450
- return undefined;
451
- }
452
-
453
- const leafPreimagePromise = snap.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index);
454
- const siblingPathPromise = snap.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(
455
- MerkleTreeId.NULLIFIER_TREE,
456
- BigInt(index),
457
- );
458
-
459
- const [leafPreimage, siblingPath] = await Promise.all([leafPreimagePromise, siblingPathPromise]);
460
-
461
- if (!leafPreimage) {
462
- return undefined;
463
- }
464
-
465
- return new NullifierMembershipWitness(BigInt(index), leafPreimage as NullifierLeafPreimage, siblingPath);
466
- }
467
-
468
- async getPublicDataTreeWitness(blockNumber: number, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
469
- const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
470
-
471
- const lowLeafResult = await snap.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
472
- if (!lowLeafResult) {
473
- return undefined;
474
- } else {
475
- const preimage = (await snap.getLeafPreimage(
476
- MerkleTreeId.PUBLIC_DATA_TREE,
477
- lowLeafResult.index,
478
- )) as PublicDataTreeLeafPreimage;
479
- const path = await snap.getSiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>(
480
- MerkleTreeId.PUBLIC_DATA_TREE,
481
- lowLeafResult.index,
482
- );
483
- return new PublicDataWitness(lowLeafResult.index, preimage, path);
484
- }
485
- }
486
-
487
- async getLowNullifierMembershipWitness(
488
- blockNumber: number,
489
- nullifier: Fr,
490
- ): Promise<NullifierMembershipWitness | undefined> {
491
- const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
492
-
493
- const findResult = await snap.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt());
494
- if (!findResult) {
495
- return undefined;
496
- }
497
- const { index, alreadyPresent } = findResult;
498
- if (alreadyPresent) {
499
- this.logger.warn(`Nullifier ${nullifier.toBigInt()} already exists in the tree`);
500
- }
501
- const preimageData = (await snap.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, index))!;
502
-
503
- const siblingPath = await snap.getSiblingPath<typeof NULLIFIER_TREE_HEIGHT>(
504
- MerkleTreeId.NULLIFIER_TREE,
505
- BigInt(index),
506
- );
507
- return new NullifierMembershipWitness(BigInt(index), preimageData as NullifierLeafPreimage, siblingPath);
508
- }
509
-
510
- async getBlockHeader(blockNumber: number): Promise<BlockHeader | undefined> {
511
- if (blockNumber === 1) {
512
- // TODO: Figure out why native merkle trees cannot get snapshot of 0, as it defaults to latest
513
- throw new Error('Cannot get the block header of block number 1');
514
- }
515
-
516
- const snap = this.nativeWorldStateService.getSnapshot(blockNumber);
517
- const stateReference = await snap.getStateReference();
518
-
519
- const previousState = this.nativeWorldStateService.getSnapshot(blockNumber - 1);
520
- const archiveInfo = await previousState.getTreeInfo(MerkleTreeId.ARCHIVE);
521
-
522
- const header = new BlockHeader(
523
- new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
524
- makeContentCommitment(),
525
- stateReference,
526
- makeGlobalVariables(),
527
- Fr.ZERO,
528
- Fr.ZERO,
529
- );
530
-
531
- header.globalVariables.blockNumber = new Fr(blockNumber);
532
-
533
- return header;
534
- }
535
-
536
- getCompleteAddress(account: AztecAddress) {
537
- return Promise.resolve(this.accountDataProvider.getAccount(account));
538
- }
539
-
540
- getAuthWitness(messageHash: Fr) {
541
- return this.pxeOracleInterface.getAuthWitness(messageHash);
542
- }
543
-
544
- async getNotes(
545
- storageSlot: Fr,
546
- numSelects: number,
547
- selectByIndexes: number[],
548
- selectByOffsets: number[],
549
- selectByLengths: number[],
550
- selectValues: Fr[],
551
- selectComparators: number[],
552
- sortByIndexes: number[],
553
- sortByOffsets: number[],
554
- sortByLengths: number[],
555
- sortOrder: number[],
556
- limit: number,
557
- offset: number,
558
- status: NoteStatus,
559
- ) {
560
- // Nullified pending notes are already removed from the list.
561
- const pendingNotes = this.noteCache.getNotes(this.contractAddress, storageSlot);
562
-
563
- const pendingNullifiers = this.noteCache.getNullifiers(this.contractAddress);
564
- const dbNotes = await this.pxeOracleInterface.getNotes(this.contractAddress, storageSlot, status);
565
- const dbNotesFiltered = dbNotes.filter(n => !pendingNullifiers.has((n.siloedNullifier as Fr).value));
566
-
567
- const notes = pickNotes<NoteData>([...dbNotesFiltered, ...pendingNotes], {
568
- selects: selectByIndexes.slice(0, numSelects).map((index, i) => ({
569
- selector: { index, offset: selectByOffsets[i], length: selectByLengths[i] },
570
- value: selectValues[i],
571
- comparator: selectComparators[i],
572
- })),
573
- sorts: sortByIndexes.map((index, i) => ({
574
- selector: { index, offset: sortByOffsets[i], length: sortByLengths[i] },
575
- order: sortOrder[i],
576
- })),
577
- limit,
578
- offset,
579
- });
580
-
581
- this.logger.debug(
582
- `Returning ${notes.length} notes for ${this.contractAddress} at ${storageSlot}: ${notes
583
- .map(n => `${n.nonce.toString()}:[${n.note.items.map(i => i.toString()).join(',')}]`)
584
- .join(', ')}`,
585
- );
586
-
587
- return notes;
588
- }
589
-
590
- notifyCreatedNote(storageSlot: Fr, _noteTypeId: NoteSelector, noteItems: Fr[], noteHash: Fr, counter: number) {
591
- const note = new Note(noteItems);
592
- this.noteCache.addNewNote(
593
- {
594
- contractAddress: this.contractAddress,
595
- storageSlot,
596
- nonce: Fr.ZERO, // Nonce cannot be known during private execution.
597
- note,
598
- siloedNullifier: undefined, // Siloed nullifier cannot be known for newly created note.
599
- noteHash,
600
- },
601
- counter,
602
- );
603
- this.sideEffectCounter = counter + 1;
604
- return Promise.resolve();
605
- }
606
-
607
- async notifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) {
608
- await this.checkNullifiersNotInTree(this.contractAddress, [innerNullifier]);
609
- await this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
610
- this.sideEffectCounter = counter + 1;
611
- }
612
-
613
- async notifyCreatedNullifier(innerNullifier: Fr): Promise<void> {
614
- await this.checkNullifiersNotInTree(this.contractAddress, [innerNullifier]);
615
- await this.noteCache.nullifierCreated(this.contractAddress, innerNullifier);
616
- }
617
-
618
- async checkNullifierExists(innerNullifier: Fr): Promise<boolean> {
619
- const snap = this.nativeWorldStateService.getSnapshot(this.blockNumber - 1);
620
-
621
- const nullifier = await siloNullifier(this.contractAddress, innerNullifier!);
622
- const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
623
- return index !== undefined;
624
- }
625
-
626
- getL1ToL2MembershipWitness(
627
- _contractAddress: AztecAddress,
628
- _messageHash: Fr,
629
- _secret: Fr,
630
- ): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>> {
631
- throw new Error('Method not implemented.');
632
- }
633
-
634
- async storageRead(
635
- contractAddress: AztecAddress,
636
- startStorageSlot: Fr,
637
- blockNumber: number,
638
- numberOfElements: number,
639
- ): Promise<Fr[]> {
640
- let db: MerkleTreeReadOperations;
641
- if (blockNumber === this.blockNumber) {
642
- db = this.baseFork;
643
- } else {
644
- db = this.nativeWorldStateService.getSnapshot(blockNumber);
645
- }
646
-
647
- const values = [];
648
- for (let i = 0n; i < numberOfElements; i++) {
649
- const storageSlot = startStorageSlot.add(new Fr(i));
650
- const leafSlot = (await computePublicDataTreeLeafSlot(contractAddress, storageSlot)).toBigInt();
651
-
652
- const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot);
653
-
654
- let value = Fr.ZERO;
655
- if (lowLeafResult && lowLeafResult.alreadyPresent) {
656
- const preimage = (await db.getLeafPreimage(
657
- MerkleTreeId.PUBLIC_DATA_TREE,
658
- lowLeafResult.index,
659
- )) as PublicDataTreeLeafPreimage;
660
- value = preimage.value;
661
- }
662
- this.logger.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`);
663
- values.push(value);
664
- }
665
- return values;
666
- }
667
-
668
- async storageWrite(startStorageSlot: Fr, values: Fr[]): Promise<Fr[]> {
669
- const publicDataWrites = await Promise.all(
670
- values.map(async (value, i) => {
671
- const storageSlot = startStorageSlot.add(new Fr(i));
672
- this.logger.debug(`Oracle storage write: slot=${storageSlot.toString()} value=${value}`);
673
- return new PublicDataWrite(await computePublicDataTreeLeafSlot(this.contractAddress, storageSlot), value);
674
- }),
675
- );
676
-
677
- await this.addPublicDataWrites(publicDataWrites);
678
- return publicDataWrites.map(write => write.value);
679
- }
680
-
681
- async commitState() {
682
- const blockNumber = await this.getBlockNumber();
683
- const { usedTxRequestHashForNonces } = this.noteCache.finish();
684
- if (this.committedBlocks.has(blockNumber)) {
685
- throw new Error('Already committed state');
686
- } else {
687
- this.committedBlocks.add(blockNumber);
688
- }
689
-
690
- const fork = this.baseFork;
691
-
692
- const txEffect = TxEffect.empty();
693
-
694
- const nonceGenerator = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
695
-
696
- let i = 0;
697
- const uniqueNoteHashesFromPrivate = await Promise.all(
698
- this.noteCache
699
- .getAllNotes()
700
- .map(async pendingNote =>
701
- computeUniqueNoteHash(
702
- await computeNoteHashNonce(nonceGenerator, i++),
703
- await siloNoteHash(pendingNote.note.contractAddress, pendingNote.noteHashForConsumption),
704
- ),
705
- ),
706
- );
707
- txEffect.noteHashes = [...uniqueNoteHashesFromPrivate, ...this.uniqueNoteHashesFromPublic];
708
-
709
- txEffect.nullifiers = [...this.siloedNullifiersFromPublic, ...this.noteCache.getAllNullifiers()];
710
- if (usedTxRequestHashForNonces) {
711
- txEffect.nullifiers.unshift(this.getTxRequestHash());
712
- }
713
-
714
- txEffect.publicDataWrites = this.publicDataWrites;
715
-
716
- const body = new Body([txEffect]);
717
-
718
- const l2Block = new L2Block(
719
- makeAppendOnlyTreeSnapshot(blockNumber + 1),
720
- makeHeader(0, blockNumber, blockNumber),
721
- body,
722
- );
723
-
724
- const paddedTxEffects = l2Block.body.txEffects;
725
-
726
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
727
-
728
- {
729
- const noteHashesPadded = paddedTxEffects.flatMap(txEffect =>
730
- padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
731
- );
732
- await fork.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashesPadded);
733
-
734
- await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
735
- }
736
-
737
- {
738
- for (const txEffect of paddedTxEffects) {
739
- // We do not need to add public data writes because we apply them as we go. We use the sequentialInsert because
740
- // the batchInsert was not working when updating a previously updated slot.
741
- // FIXME: public data writes, note hashes, nullifiers, messages should all be handled in the same way.
742
- // They are all relevant to subsequent enqueued calls and txs.
743
-
744
- const nullifiersPadded = padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX);
745
-
746
- await fork.batchInsert(
747
- MerkleTreeId.NULLIFIER_TREE,
748
- nullifiersPadded.map(nullifier => nullifier.toBuffer()),
749
- NULLIFIER_SUBTREE_HEIGHT,
750
- );
751
- }
752
- }
753
-
754
- await this.node.setTxEffect(blockNumber, new TxHash(new Fr(blockNumber)), txEffect);
755
- this.node.setNullifiersIndexesWithBlock(blockNumber, txEffect.nullifiers);
756
- this.node.addNoteLogsByTags(this.blockNumber, this.privateLogs);
757
- this.node.addPublicLogsByTags(this.blockNumber, this.publicLogs);
758
-
759
- const stateReference = await fork.getStateReference();
760
- const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
761
- const header = new BlockHeader(
762
- new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
763
- makeContentCommitment(),
764
- stateReference,
765
- makeGlobalVariables(),
766
- Fr.ZERO,
767
- Fr.ZERO,
768
- );
769
-
770
- header.globalVariables.blockNumber = new Fr(blockNumber);
771
-
772
- l2Block.header = header;
773
-
774
- await fork.updateArchive(l2Block.header);
775
-
776
- // We've built a block with all of our state changes in a "fork".
777
- // Now emulate a "sync" to this block, by letting cpp reapply the block's
778
- // changes to the underlying unforked world state and comparing the results
779
- // against the block's state reference (which is this state reference here in the fork).
780
- // This essentially commits the state updates to the unforked state and sanity checks the roots.
781
- await this.nativeWorldStateService.handleL2BlockAndMessages(l2Block, l1ToL2Messages);
782
-
783
- this.publicDataWrites = [];
784
- this.privateLogs = [];
785
- this.publicLogs = [];
786
- this.uniqueNoteHashesFromPublic = [];
787
- this.siloedNullifiersFromPublic = [];
788
- this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
789
- }
790
-
791
- getTxRequestHash() {
792
- // Using block number itself is invalid since indexed trees come prefilled with the first slots.
793
- return new Fr(this.blockNumber + 6969);
794
- }
795
-
796
- notifyCreatedContractClassLog(_log: ContractClassLog, _counter: number): Fr {
797
- throw new Error('Method not implemented.');
798
- }
799
-
800
- async callPrivateFunction(
801
- targetContractAddress: AztecAddress,
802
- functionSelector: FunctionSelector,
803
- argsHash: Fr,
804
- sideEffectCounter: number,
805
- isStaticCall: boolean,
806
- ) {
807
- this.logger.verbose(
808
- `Executing external function ${await this.getDebugFunctionName(
809
- targetContractAddress,
810
- functionSelector,
811
- )}@${targetContractAddress} isStaticCall=${isStaticCall}`,
812
- );
813
-
814
- // Store and modify env
815
- const currentContractAddress = this.contractAddress;
816
- const currentMessageSender = this.msgSender;
817
- const currentFunctionSelector = FunctionSelector.fromField(this.functionSelector.toField());
818
- this.setMsgSender(this.contractAddress);
819
- this.setContractAddress(targetContractAddress);
820
- this.setFunctionSelector(functionSelector);
821
-
822
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
823
-
824
- const acir = artifact.bytecode;
825
- const initialWitness = await this.getInitialWitness(artifact, argsHash, sideEffectCounter, isStaticCall);
826
- const acvmCallback = new Oracle(this);
827
- const timer = new Timer();
828
- const acirExecutionResult = await this.simulationProvider
829
- .executeUserCircuit(acir, initialWitness, acvmCallback)
830
- .catch((err: Error) => {
831
- err.message = resolveAssertionMessageFromError(err, artifact);
832
-
833
- const execError = new ExecutionError(
834
- err.message,
835
- {
836
- contractAddress: targetContractAddress,
837
- functionSelector,
838
- },
839
- extractCallStack(err, artifact.debug),
840
- { cause: err },
841
- );
842
- this.logger.debug(`Error executing private function ${targetContractAddress}:${functionSelector}`);
843
- throw createSimulationError(execError);
844
- });
845
- const duration = timer.ms();
846
- const publicInputs = extractPrivateCircuitPublicInputs(artifact, acirExecutionResult.partialWitness);
847
-
848
- const initialWitnessSize = witnessMapToFields(initialWitness).length * Fr.SIZE_IN_BYTES;
849
- this.logger.debug(`Ran external function ${targetContractAddress.toString()}:${functionSelector}`, {
850
- circuitName: 'app-circuit',
851
- duration,
852
- eventName: 'circuit-witness-generation',
853
- inputSize: initialWitnessSize,
854
- outputSize: publicInputs.toBuffer().length,
855
- appCircuitName: 'noname',
856
- } satisfies CircuitWitnessGenerationStats);
857
-
858
- // Apply side effects
859
- const endSideEffectCounter = publicInputs.endSideEffectCounter;
860
- this.sideEffectCounter = endSideEffectCounter.toNumber() + 1;
861
-
862
- await this.addPrivateLogs(
863
- targetContractAddress,
864
- publicInputs.privateLogs.filter(privateLog => !privateLog.isEmpty()).map(privateLog => privateLog.log),
865
- );
866
-
867
- this.setContractAddress(currentContractAddress);
868
- this.setMsgSender(currentMessageSender);
869
- this.setFunctionSelector(currentFunctionSelector);
870
-
871
- return { endSideEffectCounter, returnsHash: publicInputs.returnsHash };
872
- }
873
-
874
- async getInitialWitness(abi: FunctionAbi, argsHash: Fr, sideEffectCounter: number, isStaticCall: boolean) {
875
- const argumentsSize = countArgumentsSize(abi);
876
-
877
- const args = this.executionCache.getPreimage(argsHash);
878
-
879
- if (args.length !== argumentsSize) {
880
- throw new Error('Invalid arguments size');
881
- }
882
-
883
- const privateContextInputs = await this.getPrivateContextInputs(
884
- this.blockNumber - 1,
885
- sideEffectCounter,
886
- isStaticCall,
887
- );
888
- const privateContextInputsAsFields = privateContextInputs.toFields();
889
- if (privateContextInputsAsFields.length !== PRIVATE_CONTEXT_INPUTS_LENGTH) {
890
- throw new Error('Invalid private context inputs size');
891
- }
892
-
893
- const fields = [...privateContextInputsAsFields, ...args];
894
- return toACVMWitness(0, fields);
895
- }
896
-
897
- public async getDebugFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
898
- const instance = await this.contractDataProvider.getContractInstance(address);
899
- if (!instance) {
900
- return undefined;
901
- }
902
- const artifact = await this.contractDataProvider.getContractArtifact(instance!.currentContractClassId);
903
- if (!artifact) {
904
- return undefined;
905
- }
906
- const functionSelectorsAndNames = await Promise.all(
907
- artifact.functions.map(async f => ({
908
- name: f.name,
909
- selector: await FunctionSelector.fromNameAndParameters(f.name, f.parameters),
910
- })),
911
- );
912
- const functionSelectorAndName = functionSelectorsAndNames.find(f => f.selector.equals(selector));
913
- if (!functionSelectorAndName) {
914
- return undefined;
915
- }
916
-
917
- return `${artifact.name}:${functionSelectorAndName.name}`;
918
- }
919
-
920
- private async executePublicFunction(args: Fr[], callContext: CallContext, isTeardown: boolean = false) {
921
- const executionRequest = new PublicExecutionRequest(callContext, args);
922
-
923
- const db = this.baseFork;
924
-
925
- const globalVariables = GlobalVariables.empty();
926
- globalVariables.chainId = new Fr(await this.node.getChainId());
927
- globalVariables.version = new Fr(await this.node.getVersion());
928
- globalVariables.blockNumber = new Fr(this.blockNumber);
929
- globalVariables.gasFees = new GasFees(1, 1);
930
-
931
- let result: PublicTxResult;
932
- // Checkpoint here so that we can revert merkle ops after simulation.
933
- // See note at revert below.
934
- const checkpoint = await ForkCheckpoint.new(db);
935
- try {
936
- const simulator = new PublicTxSimulator(
937
- db,
938
- new TXEWorldStateDB(db, new TXEPublicContractDataSource(this), this),
939
- globalVariables,
940
- /*doMerkleOperations=*/ true,
941
- );
942
-
943
- const { usedTxRequestHashForNonces } = this.noteCache.finish();
944
- const firstNullifier = usedTxRequestHashForNonces
945
- ? this.getTxRequestHash()
946
- : this.noteCache.getAllNullifiers()[0];
947
-
948
- // When setting up a teardown call, we tell it that
949
- // private execution used Gas(1, 1) so it can compute a tx fee.
950
- const gasUsedByPrivate = isTeardown ? new Gas(1, 1) : Gas.empty();
951
- const tx = await createTxForPublicCalls(
952
- firstNullifier,
953
- /*setupExecutionRequests=*/ [],
954
- /*appExecutionRequests=*/ isTeardown ? [] : [executionRequest],
955
- /*teardownExecutionRequests=*/ isTeardown ? executionRequest : undefined,
956
- /*feePayer=*/ AztecAddress.zero(),
957
- gasUsedByPrivate,
958
- );
959
-
960
- result = await simulator.simulate(tx);
961
- } finally {
962
- // NOTE: Don't accept any merkle updates from the AVM since this was just 1 enqueued call
963
- // and the TXE will re-apply all txEffects after entire execution (all enqueued calls)
964
- // complete.
965
- await checkpoint.revert();
966
- // If an error is thrown during the above simulation, this revert is the last
967
- // thing executed and we skip the postprocessing below.
968
- }
969
-
970
- const noteHashes = result.avmProvingRequest.inputs.publicInputs.accumulatedData.noteHashes.filter(
971
- s => !s.isEmpty(),
972
- );
973
-
974
- const publicDataWrites = result.avmProvingRequest.inputs.publicInputs.accumulatedData.publicDataWrites.filter(
975
- s => !s.isEmpty(),
976
- );
977
- // For now, public data writes are the only merkle operations that are readable by later enqueued calls in the TXE.
978
- await this.addPublicDataWrites(publicDataWrites);
979
-
980
- this.addUniqueNoteHashesFromPublic(noteHashes);
981
-
982
- this.addPublicLogs(
983
- result.avmProvingRequest.inputs.publicInputs.accumulatedData.publicLogs.filter(
984
- log => !log.contractAddress.equals(AztecAddress.ZERO),
985
- ),
986
- );
987
-
988
- return Promise.resolve(result);
989
- }
990
-
991
- async enqueuePublicFunctionCall(
992
- targetContractAddress: AztecAddress,
993
- functionSelector: FunctionSelector,
994
- argsHash: Fr,
995
- _sideEffectCounter: number,
996
- isStaticCall: boolean,
997
- isTeardown = false,
998
- ): Promise<Fr> {
999
- // Store and modify env
1000
- const currentContractAddress = this.contractAddress;
1001
- const currentMessageSender = this.msgSender;
1002
- const currentFunctionSelector = FunctionSelector.fromField(this.functionSelector.toField());
1003
- this.setMsgSender(this.contractAddress);
1004
- this.setContractAddress(targetContractAddress);
1005
- this.setFunctionSelector(functionSelector);
1006
-
1007
- const callContext = new CallContext(
1008
- /* msgSender */ currentContractAddress,
1009
- targetContractAddress,
1010
- FunctionSelector.fromField(new Fr(PUBLIC_DISPATCH_SELECTOR)),
1011
- isStaticCall,
1012
- );
1013
-
1014
- const args = [this.functionSelector.toField(), ...this.executionCache.getPreimage(argsHash)];
1015
- const newArgsHash = await this.executionCache.store(args);
1016
-
1017
- const executionResult = await this.executePublicFunction(args, callContext, isTeardown);
1018
-
1019
- // Poor man's revert handling
1020
- if (!executionResult.revertCode.isOK()) {
1021
- if (executionResult.revertReason && executionResult.revertReason instanceof SimulationError) {
1022
- await enrichPublicSimulationError(executionResult.revertReason, this.contractDataProvider, this.logger);
1023
- throw new Error(executionResult.revertReason.message);
1024
- } else {
1025
- throw new Error(`Enqueued public function call reverted: ${executionResult.revertReason}`);
1026
- }
1027
- }
1028
-
1029
- // Apply side effects
1030
- const sideEffects = executionResult.avmProvingRequest.inputs.publicInputs.accumulatedData;
1031
-
1032
- const { usedTxRequestHashForNonces } = this.noteCache.finish();
1033
- const firstNullifier = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
1034
- const nullifiers = sideEffects.nullifiers.filter(s => !s.isEmpty()).filter(s => !s.equals(firstNullifier));
1035
-
1036
- // For some reason we cannot move this up to 'executePublicFunction'. It gives us an error of trying to modify the same nullifier twice.
1037
- this.addSiloedNullifiersFromPublic(nullifiers);
1038
-
1039
- this.setContractAddress(currentContractAddress);
1040
- this.setMsgSender(currentMessageSender);
1041
- this.setFunctionSelector(currentFunctionSelector);
1042
-
1043
- return newArgsHash;
1044
- }
1045
-
1046
- async setPublicTeardownFunctionCall(
1047
- targetContractAddress: AztecAddress,
1048
- functionSelector: FunctionSelector,
1049
- argsHash: Fr,
1050
- sideEffectCounter: number,
1051
- isStaticCall: boolean,
1052
- ): Promise<Fr> {
1053
- // Definitely not right, in that the teardown should always be last.
1054
- // But useful for executing flows.
1055
- return await this.enqueuePublicFunctionCall(
1056
- targetContractAddress,
1057
- functionSelector,
1058
- argsHash,
1059
- sideEffectCounter,
1060
- isStaticCall,
1061
- /*isTeardown=*/ true,
1062
- );
1063
- }
1064
-
1065
- async notifySetMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter: number) {
1066
- await this.noteCache.setMinRevertibleSideEffectCounter(minRevertibleSideEffectCounter);
1067
- }
1068
-
1069
- debugLog(message: string, fields: Fr[]): void {
1070
- this.logger.verbose(`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
1071
- }
1072
-
1073
- async incrementAppTaggingSecretIndexAsSender(sender: AztecAddress, recipient: AztecAddress): Promise<void> {
1074
- await this.pxeOracleInterface.incrementAppTaggingSecretIndexAsSender(this.contractAddress, sender, recipient);
1075
- }
1076
-
1077
- async getIndexedTaggingSecretAsSender(sender: AztecAddress, recipient: AztecAddress): Promise<IndexedTaggingSecret> {
1078
- return await this.pxeOracleInterface.getIndexedTaggingSecretAsSender(this.contractAddress, sender, recipient);
1079
- }
1080
-
1081
- async syncNotes() {
1082
- const taggedLogsByRecipient = await this.pxeOracleInterface.syncTaggedLogs(
1083
- this.contractAddress,
1084
- await this.getBlockNumber(),
1085
- undefined,
1086
- );
1087
-
1088
- for (const [recipient, taggedLogs] of taggedLogsByRecipient.entries()) {
1089
- await this.pxeOracleInterface.processTaggedLogs(taggedLogs, AztecAddress.fromString(recipient));
1090
- }
1091
-
1092
- await this.pxeOracleInterface.removeNullifiedNotes(this.contractAddress);
1093
-
1094
- return Promise.resolve();
1095
- }
1096
-
1097
- deliverNote(
1098
- _contractAddress: AztecAddress,
1099
- _storageSlot: Fr,
1100
- _nonce: Fr,
1101
- _content: Fr[],
1102
- _noteHash: Fr,
1103
- _nullifier: Fr,
1104
- _txHash: Fr,
1105
- _recipient: AztecAddress,
1106
- ): Promise<void> {
1107
- throw new Error('deliverNote');
1108
- }
1109
-
1110
- async getLogByTag(tag: Fr): Promise<LogWithTxData | null> {
1111
- return await this.pxeOracleInterface.getLogByTag(tag);
1112
- }
1113
-
1114
- // AVM oracles
1115
-
1116
- async avmOpcodeCall(targetContractAddress: AztecAddress, args: Fr[], isStaticCall: boolean): Promise<PublicTxResult> {
1117
- // Store and modify env
1118
- const currentContractAddress = this.contractAddress;
1119
- const currentMessageSender = this.msgSender;
1120
- this.setMsgSender(this.contractAddress);
1121
- this.setContractAddress(targetContractAddress);
1122
-
1123
- const callContext = new CallContext(
1124
- /* msgSender */ currentContractAddress,
1125
- targetContractAddress,
1126
- FunctionSelector.fromField(new Fr(PUBLIC_DISPATCH_SELECTOR)),
1127
- isStaticCall,
1128
- );
1129
-
1130
- const executionResult = await this.executePublicFunction(args, callContext);
1131
- // Save return/revert data for later.
1132
- this.nestedCallReturndata = executionResult.processedPhases[0]!.returnValues[0].values!;
1133
- this.nestedCallSuccess = executionResult.revertCode.isOK();
1134
-
1135
- // Apply side effects
1136
- if (executionResult.revertCode.isOK()) {
1137
- const sideEffects = executionResult.avmProvingRequest.inputs.publicInputs.accumulatedData;
1138
- const publicDataWrites = sideEffects.publicDataWrites.filter(s => !s.isEmpty());
1139
- const noteHashes = sideEffects.noteHashes.filter(s => !s.isEmpty());
1140
- const { usedTxRequestHashForNonces } = this.noteCache.finish();
1141
- const firstNullifier = usedTxRequestHashForNonces
1142
- ? this.getTxRequestHash()
1143
- : this.noteCache.getAllNullifiers()[0];
1144
- const nullifiers = sideEffects.nullifiers.filter(s => !s.isEmpty()).filter(s => !s.equals(firstNullifier));
1145
- await this.addPublicDataWrites(publicDataWrites);
1146
- this.addUniqueNoteHashesFromPublic(noteHashes);
1147
- this.addSiloedNullifiersFromPublic(nullifiers);
1148
- }
1149
-
1150
- this.setContractAddress(currentContractAddress);
1151
- this.setMsgSender(currentMessageSender);
1152
-
1153
- return executionResult;
1154
- }
1155
-
1156
- avmOpcodeSuccessCopy(): boolean {
1157
- return this.nestedCallSuccess;
1158
- }
1159
-
1160
- avmOpcodeReturndataSize(): number {
1161
- return this.nestedCallReturndata.length;
1162
- }
1163
-
1164
- avmOpcodeReturndataCopy(rdOffset: number, copySize: number): Fr[] {
1165
- return this.nestedCallReturndata.slice(rdOffset, rdOffset + copySize);
1166
- }
1167
-
1168
- async avmOpcodeNullifierExists(innerNullifier: Fr, targetAddress: AztecAddress): Promise<boolean> {
1169
- const nullifier = await siloNullifier(targetAddress, innerNullifier!);
1170
- const db = this.baseFork;
1171
- const index = (await db.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]))[0];
1172
- return index !== undefined;
1173
- }
1174
-
1175
- async avmOpcodeEmitNullifier(nullifier: Fr) {
1176
- const siloedNullifier = await siloNullifier(this.contractAddress, nullifier);
1177
- this.addSiloedNullifiersFromPublic([siloedNullifier]);
1178
-
1179
- return Promise.resolve();
1180
- }
1181
-
1182
- // Doesn't this need to get hashed w/ the nonce ?
1183
- async avmOpcodeEmitNoteHash(noteHash: Fr) {
1184
- const siloedNoteHash = await siloNoteHash(this.contractAddress, noteHash);
1185
- this.addUniqueNoteHashesFromPublic([siloedNoteHash]);
1186
- return Promise.resolve();
1187
- }
1188
-
1189
- async avmOpcodeStorageRead(slot: Fr) {
1190
- const leafSlot = await computePublicDataTreeLeafSlot(this.contractAddress, slot);
1191
-
1192
- const lowLeafResult = await this.baseFork.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot.toBigInt());
1193
- if (!lowLeafResult || !lowLeafResult.alreadyPresent) {
1194
- return Fr.ZERO;
1195
- }
1196
-
1197
- const preimage = (await this.baseFork.getLeafPreimage(
1198
- MerkleTreeId.PUBLIC_DATA_TREE,
1199
- lowLeafResult.index,
1200
- )) as PublicDataTreeLeafPreimage;
1201
-
1202
- return preimage.value;
1203
- }
1204
-
1205
- storeCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise<void> {
1206
- if (!contractAddress.equals(this.contractAddress)) {
1207
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
1208
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
1209
- }
1210
- return this.pxeOracleInterface.storeCapsule(this.contractAddress, slot, capsule);
1211
- }
1212
-
1213
- loadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
1214
- if (!contractAddress.equals(this.contractAddress)) {
1215
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
1216
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
1217
- }
1218
- return this.pxeOracleInterface.loadCapsule(this.contractAddress, slot);
1219
- }
1220
-
1221
- deleteCapsule(contractAddress: AztecAddress, slot: Fr): Promise<void> {
1222
- if (!contractAddress.equals(this.contractAddress)) {
1223
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
1224
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
1225
- }
1226
- return this.pxeOracleInterface.deleteCapsule(this.contractAddress, slot);
1227
- }
1228
-
1229
- copyCapsule(contractAddress: AztecAddress, srcSlot: Fr, dstSlot: Fr, numEntries: number): Promise<void> {
1230
- if (!contractAddress.equals(this.contractAddress)) {
1231
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
1232
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
1233
- }
1234
- return this.pxeOracleInterface.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries);
1235
- }
1236
-
1237
- aes128Decrypt(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
1238
- const aes128 = new Aes128();
1239
- return aes128.decryptBufferCBC(ciphertext, iv, symKey);
1240
- }
1241
- }