@aztec/txe 4.0.0-nightly.20250907 → 4.0.0-nightly.20260107

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 (100) hide show
  1. package/dest/bin/index.d.ts +1 -1
  2. package/dest/bin/index.js +1 -1
  3. package/dest/constants.d.ts +3 -0
  4. package/dest/constants.d.ts.map +1 -0
  5. package/dest/constants.js +2 -0
  6. package/dest/index.d.ts +1 -1
  7. package/dest/index.d.ts.map +1 -1
  8. package/dest/index.js +8 -4
  9. package/dest/oracle/interfaces.d.ts +57 -0
  10. package/dest/oracle/interfaces.d.ts.map +1 -0
  11. package/dest/oracle/interfaces.js +3 -0
  12. package/dest/oracle/txe_oracle_public_context.d.ts +12 -12
  13. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  14. package/dest/oracle/txe_oracle_public_context.js +30 -34
  15. package/dest/oracle/txe_oracle_top_level_context.d.ts +65 -0
  16. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -0
  17. package/dest/oracle/txe_oracle_top_level_context.js +463 -0
  18. package/dest/rpc_translator.d.ts +246 -0
  19. package/dest/rpc_translator.d.ts.map +1 -0
  20. package/dest/{txe_service/txe_service.js → rpc_translator.js} +201 -124
  21. package/dest/state_machine/archiver.d.ts +34 -13
  22. package/dest/state_machine/archiver.d.ts.map +1 -1
  23. package/dest/state_machine/archiver.js +111 -16
  24. package/dest/state_machine/dummy_p2p_client.d.ts +5 -2
  25. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  26. package/dest/state_machine/dummy_p2p_client.js +9 -1
  27. package/dest/state_machine/global_variable_builder.d.ts +5 -16
  28. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  29. package/dest/state_machine/global_variable_builder.js +15 -22
  30. package/dest/state_machine/index.d.ts +5 -5
  31. package/dest/state_machine/index.d.ts.map +1 -1
  32. package/dest/state_machine/index.js +17 -21
  33. package/dest/state_machine/mock_epoch_cache.d.ts +6 -5
  34. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  35. package/dest/state_machine/mock_epoch_cache.js +8 -7
  36. package/dest/state_machine/synchronizer.d.ts +5 -4
  37. package/dest/state_machine/synchronizer.d.ts.map +1 -1
  38. package/dest/state_machine/synchronizer.js +5 -4
  39. package/dest/txe_session.d.ts +42 -46
  40. package/dest/txe_session.d.ts.map +1 -1
  41. package/dest/txe_session.js +241 -93
  42. package/dest/util/encoding.d.ts +623 -24
  43. package/dest/util/encoding.d.ts.map +1 -1
  44. package/dest/util/encoding.js +1 -1
  45. package/dest/util/expected_failure_error.d.ts +1 -1
  46. package/dest/util/expected_failure_error.d.ts.map +1 -1
  47. package/dest/util/txe_account_store.d.ts +10 -0
  48. package/dest/util/txe_account_store.d.ts.map +1 -0
  49. package/dest/util/{txe_account_data_provider.js → txe_account_store.js} +1 -1
  50. package/dest/util/txe_contract_store.d.ts +12 -0
  51. package/dest/util/txe_contract_store.d.ts.map +1 -0
  52. package/dest/util/{txe_contract_data_provider.js → txe_contract_store.js} +4 -4
  53. package/dest/util/txe_public_contract_data_source.d.ts +8 -6
  54. package/dest/util/txe_public_contract_data_source.d.ts.map +1 -1
  55. package/dest/util/txe_public_contract_data_source.js +14 -12
  56. package/dest/utils/block_creation.d.ts +28 -0
  57. package/dest/utils/block_creation.d.ts.map +1 -0
  58. package/dest/utils/block_creation.js +45 -0
  59. package/dest/utils/tx_effect_creation.d.ts +6 -0
  60. package/dest/utils/tx_effect_creation.d.ts.map +1 -0
  61. package/dest/utils/tx_effect_creation.js +16 -0
  62. package/package.json +18 -17
  63. package/src/bin/index.ts +1 -1
  64. package/src/constants.ts +3 -0
  65. package/src/index.ts +20 -20
  66. package/src/oracle/interfaces.ts +86 -0
  67. package/src/oracle/txe_oracle_public_context.ts +37 -75
  68. package/src/oracle/txe_oracle_top_level_context.ts +716 -0
  69. package/src/{txe_service/txe_service.ts → rpc_translator.ts} +261 -125
  70. package/src/state_machine/archiver.ts +147 -29
  71. package/src/state_machine/dummy_p2p_client.ts +13 -2
  72. package/src/state_machine/global_variable_builder.ts +24 -41
  73. package/src/state_machine/index.ts +24 -21
  74. package/src/state_machine/mock_epoch_cache.ts +12 -11
  75. package/src/state_machine/synchronizer.ts +8 -7
  76. package/src/txe_session.ts +416 -115
  77. package/src/util/encoding.ts +1 -1
  78. package/src/util/{txe_account_data_provider.ts → txe_account_store.ts} +1 -1
  79. package/src/util/{txe_contract_data_provider.ts → txe_contract_store.ts} +5 -4
  80. package/src/util/txe_public_contract_data_source.ts +16 -13
  81. package/src/utils/block_creation.ts +94 -0
  82. package/src/utils/tx_effect_creation.ts +38 -0
  83. package/dest/oracle/txe_oracle.d.ts +0 -124
  84. package/dest/oracle/txe_oracle.d.ts.map +0 -1
  85. package/dest/oracle/txe_oracle.js +0 -770
  86. package/dest/oracle/txe_typed_oracle.d.ts +0 -42
  87. package/dest/oracle/txe_typed_oracle.d.ts.map +0 -1
  88. package/dest/oracle/txe_typed_oracle.js +0 -83
  89. package/dest/txe_constants.d.ts +0 -2
  90. package/dest/txe_constants.d.ts.map +0 -1
  91. package/dest/txe_constants.js +0 -7
  92. package/dest/txe_service/txe_service.d.ts +0 -231
  93. package/dest/txe_service/txe_service.d.ts.map +0 -1
  94. package/dest/util/txe_account_data_provider.d.ts +0 -10
  95. package/dest/util/txe_account_data_provider.d.ts.map +0 -1
  96. package/dest/util/txe_contract_data_provider.d.ts +0 -11
  97. package/dest/util/txe_contract_data_provider.d.ts.map +0 -1
  98. package/src/oracle/txe_oracle.ts +0 -1287
  99. package/src/oracle/txe_typed_oracle.ts +0 -142
  100. package/src/txe_constants.ts +0 -9
@@ -1,1287 +0,0 @@
1
- import { type AztecNode, Body, L2Block, Note } from '@aztec/aztec.js';
2
- import {
3
- CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS,
4
- DEFAULT_DA_GAS_LIMIT,
5
- DEFAULT_L2_GAS_LIMIT,
6
- DEFAULT_TEARDOWN_DA_GAS_LIMIT,
7
- DEFAULT_TEARDOWN_L2_GAS_LIMIT,
8
- type L1_TO_L2_MSG_TREE_HEIGHT,
9
- MAX_NOTE_HASHES_PER_TX,
10
- MAX_NULLIFIERS_PER_TX,
11
- NULLIFIER_SUBTREE_HEIGHT,
12
- NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
13
- PRIVATE_CONTEXT_INPUTS_LENGTH,
14
- } from '@aztec/constants';
15
- import { padArrayEnd } from '@aztec/foundation/collection';
16
- import { Aes128, Schnorr } from '@aztec/foundation/crypto';
17
- import { Fr, Point } from '@aztec/foundation/fields';
18
- import { type Logger, applyStringFormatting, createLogger } from '@aztec/foundation/log';
19
- import { TestDateProvider } from '@aztec/foundation/timer';
20
- import { KeyStore } from '@aztec/key-store';
21
- import {
22
- AddressDataProvider,
23
- CapsuleDataProvider,
24
- NoteDataProvider,
25
- ORACLE_VERSION,
26
- PXEOracleInterface,
27
- PrivateEventDataProvider,
28
- TaggingDataProvider,
29
- enrichPublicSimulationError,
30
- } from '@aztec/pxe/server';
31
- import {
32
- ExecutionNoteCache,
33
- HashedValuesCache,
34
- MessageLoadOracleInputs,
35
- type NoteData,
36
- Oracle,
37
- PrivateExecutionOracle,
38
- UtilityExecutionOracle,
39
- executePrivateFunction,
40
- generateSimulatedProvingResult,
41
- pickNotes,
42
- } from '@aztec/pxe/simulator';
43
- import { WASMSimulator, extractCallStack, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
44
- import {
45
- ExecutionError,
46
- GuardedMerkleTreeOperations,
47
- PublicContractsDB,
48
- PublicProcessor,
49
- PublicTxSimulator,
50
- createSimulationError,
51
- resolveAssertionMessageFromError,
52
- } from '@aztec/simulator/server';
53
- import {
54
- type ContractArtifact,
55
- type FunctionAbi,
56
- FunctionSelector,
57
- FunctionType,
58
- type NoteSelector,
59
- countArgumentsSize,
60
- } from '@aztec/stdlib/abi';
61
- import { AuthWitness } from '@aztec/stdlib/auth-witness';
62
- import { AztecAddress } from '@aztec/stdlib/aztec-address';
63
- import { type ContractInstance, type ContractInstanceWithAddress, computePartialAddress } from '@aztec/stdlib/contract';
64
- import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
65
- import {
66
- computeCalldataHash,
67
- computeNoteHashNonce,
68
- computePublicDataTreeLeafSlot,
69
- computeUniqueNoteHash,
70
- computeVarArgsHash,
71
- siloNoteHash,
72
- siloNullifier,
73
- } from '@aztec/stdlib/hash';
74
- import type { MerkleTreeReadOperations, MerkleTreeWriteOperations } from '@aztec/stdlib/interfaces/server';
75
- import {
76
- type KeyValidationRequest,
77
- PartialPrivateTailPublicInputsForPublic,
78
- PrivateContextInputs,
79
- PrivateKernelTailCircuitPublicInputs,
80
- PrivateToPublicAccumulatedData,
81
- PublicCallRequest,
82
- } from '@aztec/stdlib/kernel';
83
- import { ContractClassLog, IndexedTaggingSecret, PrivateLog } from '@aztec/stdlib/logs';
84
- import type { NoteStatus } from '@aztec/stdlib/note';
85
- import { ClientIvcProof } from '@aztec/stdlib/proofs';
86
- import {
87
- makeAppendOnlyTreeSnapshot,
88
- makeContentCommitment,
89
- makeGlobalVariables,
90
- makeHeader,
91
- } from '@aztec/stdlib/testing';
92
- import {
93
- AppendOnlyTreeSnapshot,
94
- MerkleTreeId,
95
- NullifierMembershipWitness,
96
- type PublicDataTreeLeafPreimage,
97
- PublicDataWitness,
98
- } from '@aztec/stdlib/trees';
99
- import {
100
- BlockHeader,
101
- CallContext,
102
- HashedValues,
103
- PrivateCallExecutionResult,
104
- PrivateExecutionResult,
105
- Tx,
106
- TxConstantData,
107
- TxContext,
108
- TxEffect,
109
- TxHash,
110
- collectNested,
111
- } from '@aztec/stdlib/tx';
112
- import type { UInt64 } from '@aztec/stdlib/types';
113
- import { ForkCheckpoint } from '@aztec/world-state/native';
114
-
115
- import { TXEStateMachine } from '../state_machine/index.js';
116
- import { GENESIS_TIMESTAMP } from '../txe_constants.js';
117
- import { TXEAccountDataProvider } from '../util/txe_account_data_provider.js';
118
- import { TXEContractDataProvider } from '../util/txe_contract_data_provider.js';
119
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
120
- import { TXETypedOracle } from './txe_typed_oracle.js';
121
-
122
- export class TXE extends TXETypedOracle {
123
- private logger: Logger;
124
-
125
- private blockNumber = 1;
126
- private timestamp = GENESIS_TIMESTAMP;
127
-
128
- private sideEffectCounter = 0;
129
- private msgSender: AztecAddress;
130
- private functionSelector = FunctionSelector.fromField(new Fr(0));
131
-
132
- private pxeOracleInterface: PXEOracleInterface;
133
-
134
- private privateLogs: PrivateLog[] = [];
135
-
136
- private committedBlocks = new Set<number>();
137
-
138
- private ROLLUP_VERSION = 1;
139
- private CHAIN_ID = 1;
140
-
141
- private node: AztecNode;
142
-
143
- private simulator = new WASMSimulator();
144
-
145
- public noteCache: ExecutionNoteCache;
146
-
147
- private authwits: Map<string, AuthWitness> = new Map();
148
-
149
- // Used by privateSetSenderForTags and privateGetSenderForTags oracles.
150
- private senderForTags?: AztecAddress;
151
-
152
- private executionCache: HashedValuesCache;
153
-
154
- constructor(
155
- private keyStore: KeyStore,
156
- private contractDataProvider: TXEContractDataProvider,
157
- private noteDataProvider: NoteDataProvider,
158
- private capsuleDataProvider: CapsuleDataProvider,
159
- private taggingDataProvider: TaggingDataProvider,
160
- private addressDataProvider: AddressDataProvider,
161
- private privateEventDataProvider: PrivateEventDataProvider,
162
- private accountDataProvider: TXEAccountDataProvider,
163
- private contractAddress: AztecAddress,
164
- public baseFork: MerkleTreeWriteOperations,
165
- private stateMachine: TXEStateMachine,
166
- ) {
167
- super();
168
-
169
- this.logger = createLogger('txe:oracle');
170
-
171
- this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
172
-
173
- this.node = stateMachine.node;
174
-
175
- // Default msg_sender (for entrypoints) is now Fr.max_value rather than 0 addr (see #7190 & #7404)
176
- this.msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE);
177
-
178
- this.executionCache = new HashedValuesCache();
179
-
180
- this.pxeOracleInterface = new PXEOracleInterface(
181
- this.node,
182
- this.keyStore,
183
- this.contractDataProvider,
184
- this.noteDataProvider,
185
- this.capsuleDataProvider,
186
- this.stateMachine.syncDataProvider,
187
- this.taggingDataProvider,
188
- this.addressDataProvider,
189
- this.privateEventDataProvider,
190
- this.logger,
191
- );
192
- }
193
-
194
- // Utils
195
-
196
- override utilityGetChainId(): Promise<Fr> {
197
- return Promise.resolve(new Fr(this.CHAIN_ID));
198
- }
199
-
200
- override utilityGetVersion(): Promise<Fr> {
201
- return Promise.resolve(new Fr(this.ROLLUP_VERSION));
202
- }
203
-
204
- override getMsgSender() {
205
- return this.msgSender;
206
- }
207
-
208
- override txeSetContractAddress(contractAddress: AztecAddress) {
209
- this.contractAddress = contractAddress;
210
- }
211
-
212
- // TODO: Currently this is only ever used to increment this.blockNumber by 1. Refactor this as `advanceBlock()`.
213
- setBlockNumber(blockNumber: number) {
214
- this.blockNumber = blockNumber;
215
- }
216
-
217
- override async txeAdvanceBlocksBy(blocks: number) {
218
- this.logger.debug(`time traveling ${blocks} blocks`);
219
-
220
- for (let i = 0; i < blocks; i++) {
221
- const blockNumber = await this.utilityGetBlockNumber();
222
- await this.commitState();
223
- this.setBlockNumber(blockNumber + 1);
224
- }
225
- }
226
-
227
- override txeAdvanceTimestampBy(duration: UInt64) {
228
- this.logger.debug(`time traveling ${duration} seconds`);
229
- this.timestamp = this.timestamp + duration;
230
- }
231
-
232
- override async txeDeploy(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
233
- // Emit deployment nullifier
234
- await this.noteCache.nullifierCreated(
235
- AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
236
- instance.address.toField(),
237
- );
238
-
239
- // Make sure the deployment nullifier gets included in a tx in a block
240
- const blockNumber = await this.utilityGetBlockNumber();
241
- await this.commitState();
242
- this.setBlockNumber(blockNumber + 1);
243
-
244
- if (!secret.equals(Fr.ZERO)) {
245
- await this.txeAddAccount(artifact, instance, secret);
246
- } else {
247
- await this.addContractInstance(instance);
248
- await this.addContractArtifact(instance.currentContractClassId, artifact);
249
- this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
250
- }
251
- }
252
-
253
- override async txeAddAccount(artifact: ContractArtifact, instance: ContractInstanceWithAddress, secret: Fr) {
254
- const partialAddress = await computePartialAddress(instance);
255
-
256
- this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
257
- await this.addContractInstance(instance);
258
- await this.addContractArtifact(instance.currentContractClassId, artifact);
259
-
260
- const keyStore = this.getKeyStore();
261
- const completeAddress = await keyStore.addAccount(secret, partialAddress);
262
- const accountDataProvider = this.getAccountDataProvider();
263
- await accountDataProvider.setAccount(completeAddress.address, completeAddress);
264
- const addressDataProvider = this.getAddressDataProvider();
265
- await addressDataProvider.addCompleteAddress(completeAddress);
266
- this.logger.debug(`Created account ${completeAddress.address}`);
267
-
268
- return completeAddress;
269
- }
270
-
271
- override async txeCreateAccount(secret: Fr) {
272
- const keyStore = this.getKeyStore();
273
- // This is a footgun !
274
- const completeAddress = await keyStore.addAccount(secret, secret);
275
- const accountDataProvider = this.getAccountDataProvider();
276
- await accountDataProvider.setAccount(completeAddress.address, completeAddress);
277
- const addressDataProvider = this.getAddressDataProvider();
278
- await addressDataProvider.addCompleteAddress(completeAddress);
279
- this.logger.debug(`Created account ${completeAddress.address}`);
280
-
281
- return completeAddress;
282
- }
283
-
284
- getContractDataProvider() {
285
- return this.contractDataProvider;
286
- }
287
-
288
- getKeyStore() {
289
- return this.keyStore;
290
- }
291
-
292
- getAccountDataProvider() {
293
- return this.accountDataProvider;
294
- }
295
-
296
- getAddressDataProvider() {
297
- return this.addressDataProvider;
298
- }
299
-
300
- async addContractInstance(contractInstance: ContractInstanceWithAddress) {
301
- await this.contractDataProvider.addContractInstance(contractInstance);
302
- }
303
-
304
- async addContractArtifact(contractClassId: Fr, artifact: ContractArtifact) {
305
- await this.contractDataProvider.addContractArtifact(contractClassId, artifact);
306
- }
307
-
308
- override async txeGetPrivateContextInputs(
309
- blockNumber?: number,
310
- sideEffectsCounter = this.sideEffectCounter,
311
- isStaticCall = false,
312
- ) {
313
- // If blockNumber or timestamp is null, use the values corresponding to the latest historical block (number of
314
- // the block being built - 1)
315
- blockNumber = blockNumber ?? this.blockNumber - 1;
316
-
317
- const snap = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(blockNumber);
318
- const previousBlockState = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(blockNumber - 1);
319
-
320
- const stateReference = await snap.getStateReference();
321
- const inputs = PrivateContextInputs.empty();
322
- inputs.txContext.chainId = new Fr(this.CHAIN_ID);
323
- inputs.txContext.version = new Fr(this.ROLLUP_VERSION);
324
- inputs.historicalHeader.globalVariables.blockNumber = blockNumber;
325
- inputs.historicalHeader.globalVariables.timestamp = await this.getBlockTimestamp(blockNumber);
326
- inputs.historicalHeader.state = stateReference;
327
- inputs.historicalHeader.lastArchive.root = Fr.fromBuffer(
328
- (await previousBlockState.getTreeInfo(MerkleTreeId.ARCHIVE)).root,
329
- );
330
- inputs.callContext = new CallContext(this.msgSender, this.contractAddress, this.functionSelector, isStaticCall);
331
- inputs.startSideEffectCounter = sideEffectsCounter;
332
-
333
- this.logger.info(`Created private context for block ${blockNumber}`);
334
-
335
- return inputs;
336
- }
337
-
338
- override async txeAddAuthWitness(address: AztecAddress, messageHash: Fr) {
339
- const account = await this.accountDataProvider.getAccount(address);
340
- const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
341
- const schnorr = new Schnorr();
342
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
343
- const authWitness = new AuthWitness(messageHash, [...signature.toBuffer()]);
344
-
345
- this.authwits.set(authWitness.requestHash.toString(), authWitness);
346
- }
347
-
348
- async checkNullifiersNotInTree(contractAddress: AztecAddress, nullifiers: Fr[]) {
349
- const siloedNullifiers = await Promise.all(nullifiers.map(nullifier => siloNullifier(contractAddress, nullifier)));
350
- const db = this.baseFork;
351
- const nullifierIndexesInTree = await db.findLeafIndices(
352
- MerkleTreeId.NULLIFIER_TREE,
353
- siloedNullifiers.map(n => n.toBuffer()),
354
- );
355
- if (nullifierIndexesInTree.some(index => index !== undefined)) {
356
- throw new Error(`Rejecting tx for emitting duplicate nullifiers`);
357
- }
358
- }
359
-
360
- // TypedOracle
361
-
362
- override utilityAssertCompatibleOracleVersion(version: number): void {
363
- if (version !== ORACLE_VERSION) {
364
- throw new Error(
365
- `Incompatible oracle version. PXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`,
366
- );
367
- }
368
- }
369
-
370
- override utilityGetBlockNumber() {
371
- return Promise.resolve(this.blockNumber);
372
- }
373
-
374
- override utilityGetTimestamp() {
375
- return Promise.resolve(this.timestamp);
376
- }
377
-
378
- override txeGetLastBlockTimestamp() {
379
- return this.getBlockTimestamp(this.blockNumber - 1);
380
- }
381
-
382
- override utilityGetContractAddress() {
383
- return Promise.resolve(this.contractAddress);
384
- }
385
-
386
- override utilityGetRandomField() {
387
- return Fr.random();
388
- }
389
-
390
- override privateStoreInExecutionCache(values: Fr[], hash: Fr) {
391
- return this.executionCache.store(values, hash);
392
- }
393
-
394
- override privateLoadFromExecutionCache(hash: Fr) {
395
- const preimage = this.executionCache.getPreimage(hash);
396
- if (!preimage) {
397
- throw new Error(`Preimage for hash ${hash.toString()} not found in cache`);
398
- }
399
- return Promise.resolve(preimage);
400
- }
401
-
402
- override utilityGetKeyValidationRequest(pkMHash: Fr): Promise<KeyValidationRequest> {
403
- return this.keyStore.getKeyValidationRequest(pkMHash, this.contractAddress);
404
- }
405
-
406
- override utilityGetContractInstance(address: AztecAddress): Promise<ContractInstance> {
407
- return this.pxeOracleInterface.getContractInstance(address);
408
- }
409
-
410
- override utilityGetMembershipWitness(
411
- blockNumber: number,
412
- treeId: MerkleTreeId,
413
- leafValue: Fr,
414
- ): Promise<Fr[] | undefined> {
415
- return this.pxeOracleInterface.getMembershipWitness(blockNumber, treeId, leafValue);
416
- }
417
-
418
- override utilityGetNullifierMembershipWitness(
419
- blockNumber: number,
420
- nullifier: Fr,
421
- ): Promise<NullifierMembershipWitness | undefined> {
422
- return this.pxeOracleInterface.getNullifierMembershipWitness(blockNumber, nullifier);
423
- }
424
-
425
- override utilityGetPublicDataWitness(blockNumber: number, leafSlot: Fr): Promise<PublicDataWitness | undefined> {
426
- return this.pxeOracleInterface.getPublicDataWitness(blockNumber, leafSlot);
427
- }
428
-
429
- override utilityGetLowNullifierMembershipWitness(
430
- blockNumber: number,
431
- nullifier: Fr,
432
- ): Promise<NullifierMembershipWitness | undefined> {
433
- return this.pxeOracleInterface.getLowNullifierMembershipWitness(blockNumber, nullifier);
434
- }
435
-
436
- override utilityGetBlockHeader(blockNumber: number): Promise<BlockHeader | undefined> {
437
- return this.stateMachine.archiver.getBlockHeader(blockNumber);
438
- }
439
-
440
- override utilityGetCompleteAddress(account: AztecAddress) {
441
- return Promise.resolve(this.accountDataProvider.getAccount(account));
442
- }
443
-
444
- override utilityGetAuthWitness(messageHash: Fr) {
445
- const authwit = this.authwits.get(messageHash.toString());
446
- return Promise.resolve(authwit?.witness);
447
- }
448
-
449
- override async utilityGetNotes(
450
- storageSlot: Fr,
451
- numSelects: number,
452
- selectByIndexes: number[],
453
- selectByOffsets: number[],
454
- selectByLengths: number[],
455
- selectValues: Fr[],
456
- selectComparators: number[],
457
- sortByIndexes: number[],
458
- sortByOffsets: number[],
459
- sortByLengths: number[],
460
- sortOrder: number[],
461
- limit: number,
462
- offset: number,
463
- status: NoteStatus,
464
- ) {
465
- // Nullified pending notes are already removed from the list.
466
- const pendingNotes = this.noteCache.getNotes(this.contractAddress, storageSlot);
467
-
468
- const pendingNullifiers = this.noteCache.getNullifiers(this.contractAddress);
469
- const dbNotes = await this.pxeOracleInterface.getNotes(this.contractAddress, storageSlot, status);
470
- const dbNotesFiltered = dbNotes.filter(n => !pendingNullifiers.has((n.siloedNullifier as Fr).value));
471
-
472
- const notes = pickNotes<NoteData>([...dbNotesFiltered, ...pendingNotes], {
473
- selects: selectByIndexes.slice(0, numSelects).map((index, i) => ({
474
- selector: { index, offset: selectByOffsets[i], length: selectByLengths[i] },
475
- value: selectValues[i],
476
- comparator: selectComparators[i],
477
- })),
478
- sorts: sortByIndexes.map((index, i) => ({
479
- selector: { index, offset: sortByOffsets[i], length: sortByLengths[i] },
480
- order: sortOrder[i],
481
- })),
482
- limit,
483
- offset,
484
- });
485
-
486
- this.logger.debug(
487
- `Returning ${notes.length} notes for ${this.contractAddress} at ${storageSlot}: ${notes
488
- .map(n => `${n.noteNonce.toString()}:[${n.note.items.map(i => i.toString()).join(',')}]`)
489
- .join(', ')}`,
490
- );
491
-
492
- if (notes.length > 0) {
493
- const noteLength = notes[0].note.items.length;
494
- if (!notes.every(({ note }) => noteLength === note.items.length)) {
495
- throw new Error('Notes should all be the same length.');
496
- }
497
- }
498
-
499
- return notes;
500
- }
501
-
502
- override privateNotifyCreatedNote(
503
- storageSlot: Fr,
504
- _noteTypeId: NoteSelector,
505
- noteItems: Fr[],
506
- noteHash: Fr,
507
- counter: number,
508
- ) {
509
- const note = new Note(noteItems);
510
- this.noteCache.addNewNote(
511
- {
512
- contractAddress: this.contractAddress,
513
- storageSlot,
514
- noteNonce: Fr.ZERO, // Nonce cannot be known during private execution.
515
- note,
516
- siloedNullifier: undefined, // Siloed nullifier cannot be known for newly created note.
517
- noteHash,
518
- },
519
- counter,
520
- );
521
- this.sideEffectCounter = counter + 1;
522
- }
523
-
524
- override async privateNotifyNullifiedNote(innerNullifier: Fr, noteHash: Fr, counter: number) {
525
- await this.checkNullifiersNotInTree(this.contractAddress, [innerNullifier]);
526
- await this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
527
- this.sideEffectCounter = counter + 1;
528
- }
529
-
530
- override async privateNotifyCreatedNullifier(innerNullifier: Fr): Promise<void> {
531
- await this.checkNullifiersNotInTree(this.contractAddress, [innerNullifier]);
532
- await this.noteCache.nullifierCreated(this.contractAddress, innerNullifier);
533
- }
534
-
535
- override async utilityCheckNullifierExists(innerNullifier: Fr): Promise<boolean> {
536
- const snap = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(this.blockNumber - 1);
537
-
538
- const nullifier = await siloNullifier(this.contractAddress, innerNullifier!);
539
- const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [nullifier.toBuffer()]);
540
-
541
- const inPendingCache = this.noteCache.getNullifiers(this.contractAddress).has(nullifier.toBigInt());
542
-
543
- return index !== undefined || inPendingCache;
544
- }
545
-
546
- getL1ToL2MembershipWitness(
547
- _contractAddress: AztecAddress,
548
- _messageHash: Fr,
549
- _secret: Fr,
550
- ): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>> {
551
- throw new Error('Method not implemented.');
552
- }
553
-
554
- override async utilityStorageRead(
555
- contractAddress: AztecAddress,
556
- startStorageSlot: Fr,
557
- blockNumber: number,
558
- numberOfElements: number,
559
- ): Promise<Fr[]> {
560
- let db: MerkleTreeReadOperations;
561
- if (blockNumber === this.blockNumber) {
562
- db = this.baseFork;
563
- } else {
564
- db = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(blockNumber);
565
- }
566
-
567
- const values = [];
568
- for (let i = 0n; i < numberOfElements; i++) {
569
- const storageSlot = startStorageSlot.add(new Fr(i));
570
- const leafSlot = (await computePublicDataTreeLeafSlot(contractAddress, storageSlot)).toBigInt();
571
-
572
- const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot);
573
-
574
- let value = Fr.ZERO;
575
- if (lowLeafResult && lowLeafResult.alreadyPresent) {
576
- const preimage = (await db.getLeafPreimage(
577
- MerkleTreeId.PUBLIC_DATA_TREE,
578
- lowLeafResult.index,
579
- )) as PublicDataTreeLeafPreimage;
580
- value = preimage.leaf.value;
581
- }
582
- this.logger.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`);
583
- values.push(value);
584
- }
585
- return values;
586
- }
587
-
588
- async commitState() {
589
- const blockNumber = await this.utilityGetBlockNumber();
590
- const { usedTxRequestHashForNonces } = this.noteCache.finish();
591
- if (this.committedBlocks.has(blockNumber)) {
592
- throw new Error('Already committed state');
593
- } else {
594
- this.committedBlocks.add(blockNumber);
595
- }
596
-
597
- const fork = this.baseFork;
598
-
599
- const txEffect = TxEffect.empty();
600
-
601
- const nonceGenerator = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
602
-
603
- let i = 0;
604
- const uniqueNoteHashesFromPrivate = await Promise.all(
605
- this.noteCache
606
- .getAllNotes()
607
- .map(async pendingNote =>
608
- computeUniqueNoteHash(
609
- await computeNoteHashNonce(nonceGenerator, i++),
610
- await siloNoteHash(pendingNote.note.contractAddress, pendingNote.noteHashForConsumption),
611
- ),
612
- ),
613
- );
614
- txEffect.noteHashes = uniqueNoteHashesFromPrivate;
615
- txEffect.nullifiers = this.noteCache.getAllNullifiers();
616
-
617
- if (usedTxRequestHashForNonces) {
618
- txEffect.nullifiers.unshift(this.getTxRequestHash());
619
- }
620
-
621
- txEffect.privateLogs = this.privateLogs;
622
- txEffect.txHash = new TxHash(new Fr(blockNumber));
623
-
624
- const body = new Body([txEffect]);
625
-
626
- const l2Block = new L2Block(
627
- makeAppendOnlyTreeSnapshot(blockNumber + 1),
628
- makeHeader(0, blockNumber, blockNumber),
629
- body,
630
- );
631
-
632
- const paddedTxEffects = l2Block.body.txEffects;
633
-
634
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
635
-
636
- {
637
- const noteHashesPadded = paddedTxEffects.flatMap(txEffect =>
638
- padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
639
- );
640
- await fork.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashesPadded);
641
-
642
- await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
643
- }
644
-
645
- {
646
- for (const txEffect of paddedTxEffects) {
647
- // We do not need to add public data writes because we apply them as we go. We use the sequentialInsert because
648
- // the batchInsert was not working when updating a previously updated slot.
649
- // FIXME: public data writes, note hashes, nullifiers, messages should all be handled in the same way.
650
- // They are all relevant to subsequent enqueued calls and txs.
651
-
652
- const nullifiersPadded = padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX);
653
-
654
- await fork.batchInsert(
655
- MerkleTreeId.NULLIFIER_TREE,
656
- nullifiersPadded.map(nullifier => nullifier.toBuffer()),
657
- NULLIFIER_SUBTREE_HEIGHT,
658
- );
659
- }
660
- }
661
-
662
- const stateReference = await fork.getStateReference();
663
- const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
664
- const header = new BlockHeader(
665
- new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
666
- makeContentCommitment(),
667
- stateReference,
668
- makeGlobalVariables(),
669
- Fr.ZERO,
670
- Fr.ZERO,
671
- );
672
-
673
- header.globalVariables.blockNumber = blockNumber;
674
- header.globalVariables.timestamp = await this.utilityGetTimestamp();
675
- header.globalVariables.version = new Fr(this.ROLLUP_VERSION);
676
- header.globalVariables.chainId = new Fr(this.CHAIN_ID);
677
-
678
- this.logger.info(`Created block ${blockNumber} with timestamp ${header.globalVariables.timestamp}`);
679
-
680
- l2Block.header = header;
681
-
682
- await fork.updateArchive(l2Block.header);
683
-
684
- await this.stateMachine.handleL2Block(l2Block);
685
-
686
- this.privateLogs = [];
687
- this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
688
- }
689
-
690
- getTxRequestHash() {
691
- // Using block number itself is invalid since indexed trees come prefilled with the first slots.
692
- return new Fr(this.blockNumber + 6969);
693
- }
694
-
695
- notifyCreatedContractClassLog(_log: ContractClassLog, _counter: number): Fr {
696
- throw new Error('Method not implemented.');
697
- }
698
-
699
- override async simulateUtilityFunction(
700
- targetContractAddress: AztecAddress,
701
- functionSelector: FunctionSelector,
702
- argsHash: Fr,
703
- ) {
704
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
705
- if (!artifact) {
706
- throw new Error(`Cannot call ${functionSelector} as there is artifact found at ${targetContractAddress}.`);
707
- }
708
-
709
- const call = {
710
- name: artifact.name,
711
- selector: functionSelector,
712
- to: targetContractAddress,
713
- };
714
-
715
- const entryPointArtifact = await this.pxeOracleInterface.getFunctionArtifact(call.to, call.selector);
716
-
717
- if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
718
- throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
719
- }
720
-
721
- const oracle = new UtilityExecutionOracle(call.to, [], [], this.pxeOracleInterface, undefined, undefined);
722
-
723
- try {
724
- this.logger.verbose(`Executing utility function ${entryPointArtifact.name}`, {
725
- contract: call.to,
726
- selector: call.selector,
727
- });
728
-
729
- const args = await this.privateLoadFromExecutionCache(argsHash);
730
- const initialWitness = toACVMWitness(0, args);
731
- const acirExecutionResult = await this.simulator
732
- .executeUserCircuit(initialWitness, entryPointArtifact, new Oracle(oracle).toACIRCallback())
733
- .catch((err: Error) => {
734
- err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
735
- throw new ExecutionError(
736
- err.message,
737
- {
738
- contractAddress: call.to,
739
- functionSelector: call.selector,
740
- },
741
- extractCallStack(err, entryPointArtifact.debug),
742
- { cause: err },
743
- );
744
- });
745
-
746
- const returnWitness = witnessMapToFields(acirExecutionResult.returnWitness);
747
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
748
-
749
- const returnHash = await computeVarArgsHash(returnWitness);
750
-
751
- this.privateStoreInExecutionCache(returnWitness, returnHash);
752
- return returnHash;
753
- } catch (err) {
754
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
755
- }
756
- }
757
-
758
- async getInitialWitness(abi: FunctionAbi, argsHash: Fr, sideEffectCounter: number, isStaticCall: boolean) {
759
- const argumentsSize = countArgumentsSize(abi);
760
-
761
- const args = this.executionCache.getPreimage(argsHash);
762
-
763
- if (args?.length !== argumentsSize) {
764
- throw new Error('Invalid arguments size');
765
- }
766
-
767
- const historicalBlockNumber = this.blockNumber - 1; // i.e. last
768
-
769
- const privateContextInputs = await this.txeGetPrivateContextInputs(
770
- historicalBlockNumber,
771
- sideEffectCounter,
772
- isStaticCall,
773
- );
774
- const privateContextInputsAsFields = privateContextInputs.toFields();
775
- if (privateContextInputsAsFields.length !== PRIVATE_CONTEXT_INPUTS_LENGTH) {
776
- throw new Error('Invalid private context inputs size');
777
- }
778
-
779
- const fields = [...privateContextInputsAsFields, ...args];
780
- return toACVMWitness(0, fields);
781
- }
782
-
783
- public async getDebugFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
784
- return await this.contractDataProvider.getDebugFunctionName(address, selector);
785
- }
786
-
787
- override utilityDebugLog(message: string, fields: Fr[]): void {
788
- this.logger.verbose(`${applyStringFormatting(message, fields)}`, { module: `${this.logger.module}:debug_log` });
789
- }
790
-
791
- override async privateIncrementAppTaggingSecretIndexAsSender(
792
- sender: AztecAddress,
793
- recipient: AztecAddress,
794
- ): Promise<void> {
795
- await this.pxeOracleInterface.incrementAppTaggingSecretIndexAsSender(this.contractAddress, sender, recipient);
796
- }
797
-
798
- override async utilityGetIndexedTaggingSecretAsSender(
799
- sender: AztecAddress,
800
- recipient: AztecAddress,
801
- ): Promise<IndexedTaggingSecret> {
802
- return await this.pxeOracleInterface.getIndexedTaggingSecretAsSender(this.contractAddress, sender, recipient);
803
- }
804
-
805
- override async utilityFetchTaggedLogs(pendingTaggedLogArrayBaseSlot: Fr) {
806
- await this.pxeOracleInterface.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot);
807
-
808
- await this.pxeOracleInterface.removeNullifiedNotes(this.contractAddress);
809
-
810
- return Promise.resolve();
811
- }
812
-
813
- public override async utilityValidateEnqueuedNotesAndEvents(
814
- contractAddress: AztecAddress,
815
- noteValidationRequestsArrayBaseSlot: Fr,
816
- eventValidationRequestsArrayBaseSlot: Fr,
817
- ): Promise<void> {
818
- await this.pxeOracleInterface.validateEnqueuedNotesAndEvents(
819
- contractAddress,
820
- noteValidationRequestsArrayBaseSlot,
821
- eventValidationRequestsArrayBaseSlot,
822
- );
823
- }
824
-
825
- override async utilityBulkRetrieveLogs(
826
- contractAddress: AztecAddress,
827
- logRetrievalRequestsArrayBaseSlot: Fr,
828
- logRetrievalResponsesArrayBaseSlot: Fr,
829
- ): Promise<void> {
830
- return await this.pxeOracleInterface.bulkRetrieveLogs(
831
- contractAddress,
832
- logRetrievalRequestsArrayBaseSlot,
833
- logRetrievalResponsesArrayBaseSlot,
834
- );
835
- }
836
-
837
- override utilityStoreCapsule(contractAddress: AztecAddress, slot: Fr, capsule: Fr[]): Promise<void> {
838
- if (!contractAddress.equals(this.contractAddress)) {
839
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
840
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
841
- }
842
- return this.pxeOracleInterface.storeCapsule(this.contractAddress, slot, capsule);
843
- }
844
-
845
- override utilityLoadCapsule(contractAddress: AztecAddress, slot: Fr): Promise<Fr[] | null> {
846
- if (!contractAddress.equals(this.contractAddress)) {
847
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
848
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
849
- }
850
- return this.pxeOracleInterface.loadCapsule(this.contractAddress, slot);
851
- }
852
-
853
- override utilityDeleteCapsule(contractAddress: AztecAddress, slot: Fr): Promise<void> {
854
- if (!contractAddress.equals(this.contractAddress)) {
855
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
856
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
857
- }
858
- return this.pxeOracleInterface.deleteCapsule(this.contractAddress, slot);
859
- }
860
-
861
- override utilityCopyCapsule(
862
- contractAddress: AztecAddress,
863
- srcSlot: Fr,
864
- dstSlot: Fr,
865
- numEntries: number,
866
- ): Promise<void> {
867
- if (!contractAddress.equals(this.contractAddress)) {
868
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
869
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
870
- }
871
- return this.pxeOracleInterface.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries);
872
- }
873
-
874
- override utilityAes128Decrypt(ciphertext: Buffer, iv: Buffer, symKey: Buffer): Promise<Buffer> {
875
- const aes128 = new Aes128();
876
- return aes128.decryptBufferCBC(ciphertext, iv, symKey);
877
- }
878
-
879
- override utilityGetSharedSecret(address: AztecAddress, ephPk: Point): Promise<Point> {
880
- return this.pxeOracleInterface.getSharedSecret(address, ephPk);
881
- }
882
-
883
- override privateGetSenderForTags(): Promise<AztecAddress | undefined> {
884
- return Promise.resolve(this.senderForTags);
885
- }
886
-
887
- override privateSetSenderForTags(senderForTags: AztecAddress): Promise<void> {
888
- this.senderForTags = senderForTags;
889
- return Promise.resolve();
890
- }
891
-
892
- override async txePrivateCallNewFlow(
893
- from: AztecAddress,
894
- targetContractAddress: AztecAddress = AztecAddress.zero(),
895
- functionSelector: FunctionSelector = FunctionSelector.empty(),
896
- args: Fr[],
897
- argsHash: Fr = Fr.zero(),
898
- isStaticCall: boolean = false,
899
- ) {
900
- this.logger.verbose(
901
- `Executing external function ${await this.getDebugFunctionName(
902
- targetContractAddress,
903
- functionSelector,
904
- )}@${targetContractAddress} isStaticCall=${isStaticCall}`,
905
- );
906
-
907
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
908
-
909
- if (artifact === undefined) {
910
- if (functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))) {
911
- throw new Error(
912
- 'Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.',
913
- );
914
- } else {
915
- throw new Error('Function Artifact does not exist');
916
- }
917
- }
918
-
919
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
920
-
921
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
922
-
923
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
924
-
925
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
926
-
927
- const txContext = new TxContext(this.CHAIN_ID, this.ROLLUP_VERSION, gasSettings);
928
-
929
- const blockHeader = await this.pxeOracleInterface.getBlockHeader();
930
-
931
- const noteCache = new ExecutionNoteCache(this.getTxRequestHash());
932
-
933
- const privateExecutionOracle = new PrivateExecutionOracle(
934
- argsHash,
935
- txContext,
936
- callContext,
937
- /** Header of a block whose state is used during private execution (not the block the transaction is included in). */
938
- blockHeader,
939
- /** List of transient auth witnesses to be used during this simulation */
940
- Array.from(this.authwits.values()),
941
- /** List of transient auth witnesses to be used during this simulation */
942
- [],
943
- HashedValuesCache.create(),
944
- noteCache,
945
- this.pxeOracleInterface,
946
- this.simulator,
947
- 0,
948
- 1,
949
- undefined, // log
950
- undefined, // scopes
951
- /**
952
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
953
- * contract would perform, including setting senderForTags.
954
- */
955
- from,
956
- );
957
-
958
- privateExecutionOracle.privateStoreInExecutionCache(args, argsHash);
959
-
960
- // Note: This is a slight modification of simulator.run without any of the checks. Maybe we should modify simulator.run with a boolean value to skip checks.
961
- let result: PrivateExecutionResult;
962
- let executionResult: PrivateCallExecutionResult;
963
- try {
964
- executionResult = await executePrivateFunction(
965
- this.simulator,
966
- privateExecutionOracle,
967
- artifact,
968
- targetContractAddress,
969
- functionSelector,
970
- );
971
- const { usedTxRequestHashForNonces } = noteCache.finish();
972
- const firstNullifierHint = usedTxRequestHashForNonces ? Fr.ZERO : noteCache.getAllNullifiers()[0];
973
-
974
- const publicCallRequests = collectNested([executionResult], r =>
975
- r.publicInputs.publicCallRequests
976
- .getActiveItems()
977
- .map(r => r.inner)
978
- .concat(r.publicInputs.publicTeardownCallRequest.isEmpty() ? [] : [r.publicInputs.publicTeardownCallRequest]),
979
- );
980
- const publicFunctionsCalldata = await Promise.all(
981
- publicCallRequests.map(async r => {
982
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
983
- return new HashedValues(calldata, r.calldataHash);
984
- }),
985
- );
986
-
987
- result = new PrivateExecutionResult(executionResult, firstNullifierHint, publicFunctionsCalldata);
988
- } catch (err) {
989
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
990
- }
991
-
992
- if (executionResult.returnValues !== undefined) {
993
- const { returnValues } = executionResult;
994
- // This is a bit of a hack to not deal with returning a slice in nr which is what normally happens.
995
- // Investigate whether it is faster to do this or return from the oracle directly.
996
- const returnValuesHash = await computeVarArgsHash(returnValues);
997
- this.privateStoreInExecutionCache(returnValues, returnValuesHash);
998
- }
999
-
1000
- // According to the protocol rules, the nonce generator for the note hashes
1001
- // can either be the first nullifier in the tx or the hash of the initial tx request
1002
- // if there are none.
1003
- const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? this.getTxRequestHash() : result.firstNullifier;
1004
- const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractDataProvider);
1005
-
1006
- const globals = makeGlobalVariables();
1007
- globals.blockNumber = this.blockNumber;
1008
- globals.timestamp = this.timestamp;
1009
- globals.chainId = new Fr(this.CHAIN_ID);
1010
- globals.version = new Fr(this.ROLLUP_VERSION);
1011
- globals.gasFees = GasFees.empty();
1012
-
1013
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(this));
1014
- const guardedMerkleTrees = new GuardedMerkleTreeOperations(this.baseFork);
1015
- const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, true, true);
1016
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
1017
-
1018
- const tx = await Tx.create({
1019
- data: publicInputs,
1020
- clientIvcProof: ClientIvcProof.empty(),
1021
- contractClassLogFields: [],
1022
- publicFunctionCalldata: result.publicFunctionCalldata,
1023
- });
1024
-
1025
- let checkpoint;
1026
- if (isStaticCall) {
1027
- checkpoint = await ForkCheckpoint.new(this.baseFork);
1028
- }
1029
-
1030
- const results = await processor.process([tx]);
1031
-
1032
- const [processedTx] = results[0];
1033
- const failedTxs = results[1];
1034
-
1035
- if (failedTxs.length !== 0) {
1036
- throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
1037
- } else if (!processedTx.revertCode.isOK()) {
1038
- if (processedTx.revertReason) {
1039
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
1040
- throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
1041
- } else {
1042
- throw new Error('Contract execution has reverted');
1043
- }
1044
- }
1045
-
1046
- if (isStaticCall) {
1047
- await checkpoint!.revert();
1048
-
1049
- return {
1050
- endSideEffectCounter: result.entrypoint.publicInputs.endSideEffectCounter,
1051
- returnsHash: result.entrypoint.publicInputs.returnsHash,
1052
- txHash: tx.getTxHash(),
1053
- };
1054
- }
1055
-
1056
- const fork = this.baseFork;
1057
-
1058
- const txEffect = TxEffect.empty();
1059
-
1060
- txEffect.noteHashes = processedTx!.txEffect.noteHashes;
1061
- txEffect.nullifiers = processedTx!.txEffect.nullifiers;
1062
- txEffect.privateLogs = processedTx!.txEffect.privateLogs;
1063
- txEffect.publicLogs = processedTx!.txEffect.publicLogs;
1064
- txEffect.publicDataWrites = processedTx!.txEffect.publicDataWrites;
1065
-
1066
- txEffect.txHash = new TxHash(new Fr(this.blockNumber));
1067
-
1068
- const body = new Body([txEffect]);
1069
-
1070
- const l2Block = new L2Block(
1071
- makeAppendOnlyTreeSnapshot(this.blockNumber + 1),
1072
- makeHeader(0, this.blockNumber, this.blockNumber),
1073
- body,
1074
- );
1075
-
1076
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
1077
- await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
1078
-
1079
- const stateReference = await fork.getStateReference();
1080
- const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
1081
-
1082
- const header = new BlockHeader(
1083
- new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
1084
- makeContentCommitment(),
1085
- stateReference,
1086
- globals,
1087
- Fr.ZERO,
1088
- Fr.ZERO,
1089
- );
1090
-
1091
- header.globalVariables.blockNumber = this.blockNumber;
1092
-
1093
- l2Block.header = header;
1094
-
1095
- await fork.updateArchive(l2Block.header);
1096
-
1097
- await this.stateMachine.handleL2Block(l2Block);
1098
-
1099
- this.setBlockNumber(this.blockNumber + 1);
1100
- return {
1101
- endSideEffectCounter: result.entrypoint.publicInputs.endSideEffectCounter,
1102
- returnsHash: result.entrypoint.publicInputs.returnsHash,
1103
- txHash: tx.getTxHash(),
1104
- };
1105
- }
1106
-
1107
- override async txePublicCallNewFlow(
1108
- from: AztecAddress,
1109
- targetContractAddress: AztecAddress,
1110
- calldata: Fr[],
1111
- isStaticCall: boolean,
1112
- ) {
1113
- this.logger.verbose(
1114
- `Executing public function ${await this.getDebugFunctionName(
1115
- targetContractAddress,
1116
- FunctionSelector.fromField(calldata[0]),
1117
- )}@${targetContractAddress} isStaticCall=${isStaticCall}`,
1118
- );
1119
-
1120
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
1121
-
1122
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
1123
-
1124
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
1125
-
1126
- const txContext = new TxContext(this.CHAIN_ID, this.ROLLUP_VERSION, gasSettings);
1127
-
1128
- const blockHeader = await this.pxeOracleInterface.getBlockHeader();
1129
-
1130
- const calldataHash = await computeCalldataHash(calldata);
1131
- const calldataHashedValues = new HashedValues(calldata, calldataHash);
1132
-
1133
- const globals = makeGlobalVariables();
1134
- globals.blockNumber = this.blockNumber;
1135
- globals.timestamp = this.timestamp;
1136
- globals.chainId = new Fr(this.CHAIN_ID);
1137
- globals.version = new Fr(this.ROLLUP_VERSION);
1138
- globals.gasFees = GasFees.empty();
1139
-
1140
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(this));
1141
- const guardedMerkleTrees = new GuardedMerkleTreeOperations(this.baseFork);
1142
- const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, true, true);
1143
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
1144
-
1145
- // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
1146
- // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
1147
- // side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
1148
- // unique.
1149
- const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
1150
- if (!isStaticCall) {
1151
- nonRevertibleAccumulatedData.nullifiers[0] = this.getTxRequestHash();
1152
- }
1153
-
1154
- // The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
1155
- // may require producing reverts.
1156
- const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
1157
- revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(
1158
- from,
1159
- targetContractAddress,
1160
- isStaticCall,
1161
- calldataHash,
1162
- );
1163
-
1164
- const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(
1165
- nonRevertibleAccumulatedData,
1166
- revertibleAccumulatedData,
1167
- PublicCallRequest.empty(),
1168
- );
1169
-
1170
- const constantData = new TxConstantData(blockHeader, txContext, Fr.zero(), Fr.zero());
1171
-
1172
- const txData = new PrivateKernelTailCircuitPublicInputs(
1173
- constantData,
1174
- /*gasUsed=*/ new Gas(0, 0),
1175
- /*feePayer=*/ AztecAddress.zero(),
1176
- /*includeByTimestamp=*/ 0n,
1177
- inputsForPublic,
1178
- undefined,
1179
- );
1180
-
1181
- const tx = await Tx.create({
1182
- data: txData,
1183
- clientIvcProof: ClientIvcProof.empty(),
1184
- contractClassLogFields: [],
1185
- publicFunctionCalldata: [calldataHashedValues],
1186
- });
1187
-
1188
- let checkpoint;
1189
- if (isStaticCall) {
1190
- checkpoint = await ForkCheckpoint.new(this.baseFork);
1191
- }
1192
-
1193
- const results = await processor.process([tx]);
1194
-
1195
- const [processedTx] = results[0];
1196
- const failedTxs = results[1];
1197
-
1198
- if (failedTxs.length !== 0) {
1199
- throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
1200
- } else if (!processedTx.revertCode.isOK()) {
1201
- if (processedTx.revertReason) {
1202
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
1203
- throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
1204
- } else {
1205
- throw new Error('Contract execution has reverted');
1206
- }
1207
- }
1208
-
1209
- const returnValues = results[3][0].values;
1210
- let returnValuesHash;
1211
-
1212
- if (returnValues !== undefined) {
1213
- // This is a bit of a hack to not deal with returning a slice in nr which is what normally happens.
1214
- // Investigate whether it is faster to do this or return from the oracle directly.
1215
- returnValuesHash = await computeVarArgsHash(returnValues);
1216
- this.privateStoreInExecutionCache(returnValues, returnValuesHash);
1217
- }
1218
-
1219
- if (isStaticCall) {
1220
- await checkpoint!.revert();
1221
-
1222
- return {
1223
- returnsHash: returnValuesHash ?? Fr.ZERO,
1224
- txHash: tx.getTxHash(),
1225
- };
1226
- }
1227
-
1228
- const fork = this.baseFork;
1229
-
1230
- const txEffect = TxEffect.empty();
1231
-
1232
- txEffect.noteHashes = processedTx!.txEffect.noteHashes;
1233
- txEffect.nullifiers = processedTx!.txEffect.nullifiers;
1234
- txEffect.privateLogs = processedTx!.txEffect.privateLogs;
1235
- txEffect.publicLogs = processedTx!.txEffect.publicLogs;
1236
- txEffect.publicDataWrites = processedTx!.txEffect.publicDataWrites;
1237
-
1238
- txEffect.txHash = new TxHash(new Fr(this.blockNumber));
1239
-
1240
- const body = new Body([txEffect]);
1241
-
1242
- const l2Block = new L2Block(
1243
- makeAppendOnlyTreeSnapshot(this.blockNumber + 1),
1244
- makeHeader(0, this.blockNumber, this.blockNumber),
1245
- body,
1246
- );
1247
-
1248
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
1249
- await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
1250
-
1251
- const stateReference = await fork.getStateReference();
1252
- const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
1253
-
1254
- const header = new BlockHeader(
1255
- new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)),
1256
- makeContentCommitment(),
1257
- stateReference,
1258
- globals,
1259
- Fr.ZERO,
1260
- Fr.ZERO,
1261
- );
1262
-
1263
- header.globalVariables.blockNumber = this.blockNumber;
1264
-
1265
- l2Block.header = header;
1266
-
1267
- await fork.updateArchive(l2Block.header);
1268
-
1269
- await this.stateMachine.handleL2Block(l2Block);
1270
-
1271
- this.setBlockNumber(this.blockNumber + 1);
1272
-
1273
- return {
1274
- returnsHash: returnValuesHash ?? Fr.ZERO,
1275
- txHash: tx.getTxHash(),
1276
- };
1277
- }
1278
-
1279
- private async getBlockTimestamp(blockNumber: number) {
1280
- const blockHeader = await this.stateMachine.archiver.getBlockHeader(blockNumber);
1281
- if (!blockHeader) {
1282
- throw new Error(`Requested timestamp for block ${blockNumber}, which does not exist`);
1283
- }
1284
-
1285
- return blockHeader.globalVariables.timestamp;
1286
- }
1287
- }