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

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 +6 -17
  28. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  29. package/dest/state_machine/global_variable_builder.js +16 -23
  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 +25 -42
  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,770 +0,0 @@
1
- import { Body, L2Block, Note } from '@aztec/aztec.js';
2
- import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS, DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT, DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, NULLIFIER_SUBTREE_HEIGHT, NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, PRIVATE_CONTEXT_INPUTS_LENGTH } from '@aztec/constants';
3
- import { padArrayEnd } from '@aztec/foundation/collection';
4
- import { Aes128, Schnorr } from '@aztec/foundation/crypto';
5
- import { Fr } from '@aztec/foundation/fields';
6
- import { applyStringFormatting, createLogger } from '@aztec/foundation/log';
7
- import { TestDateProvider } from '@aztec/foundation/timer';
8
- import { ORACLE_VERSION, PXEOracleInterface, enrichPublicSimulationError } from '@aztec/pxe/server';
9
- import { ExecutionNoteCache, HashedValuesCache, Oracle, PrivateExecutionOracle, UtilityExecutionOracle, executePrivateFunction, generateSimulatedProvingResult, pickNotes } from '@aztec/pxe/simulator';
10
- import { WASMSimulator, extractCallStack, toACVMWitness, witnessMapToFields } from '@aztec/simulator/client';
11
- import { ExecutionError, GuardedMerkleTreeOperations, PublicContractsDB, PublicProcessor, PublicTxSimulator, createSimulationError, resolveAssertionMessageFromError } from '@aztec/simulator/server';
12
- import { FunctionSelector, FunctionType, countArgumentsSize } from '@aztec/stdlib/abi';
13
- import { AuthWitness } from '@aztec/stdlib/auth-witness';
14
- import { AztecAddress } from '@aztec/stdlib/aztec-address';
15
- import { computePartialAddress } from '@aztec/stdlib/contract';
16
- import { Gas, GasFees, GasSettings } from '@aztec/stdlib/gas';
17
- import { computeCalldataHash, computeNoteHashNonce, computePublicDataTreeLeafSlot, computeUniqueNoteHash, computeVarArgsHash, siloNoteHash, siloNullifier } from '@aztec/stdlib/hash';
18
- import { PartialPrivateTailPublicInputsForPublic, PrivateContextInputs, PrivateKernelTailCircuitPublicInputs, PrivateToPublicAccumulatedData, PublicCallRequest } from '@aztec/stdlib/kernel';
19
- import { ClientIvcProof } from '@aztec/stdlib/proofs';
20
- import { makeAppendOnlyTreeSnapshot, makeContentCommitment, makeGlobalVariables, makeHeader } from '@aztec/stdlib/testing';
21
- import { AppendOnlyTreeSnapshot, MerkleTreeId } from '@aztec/stdlib/trees';
22
- import { BlockHeader, CallContext, HashedValues, PrivateExecutionResult, Tx, TxConstantData, TxContext, TxEffect, TxHash, collectNested } from '@aztec/stdlib/tx';
23
- import { ForkCheckpoint } from '@aztec/world-state/native';
24
- import { GENESIS_TIMESTAMP } from '../txe_constants.js';
25
- import { TXEPublicContractDataSource } from '../util/txe_public_contract_data_source.js';
26
- import { TXETypedOracle } from './txe_typed_oracle.js';
27
- export class TXE extends TXETypedOracle {
28
- keyStore;
29
- contractDataProvider;
30
- noteDataProvider;
31
- capsuleDataProvider;
32
- taggingDataProvider;
33
- addressDataProvider;
34
- privateEventDataProvider;
35
- accountDataProvider;
36
- contractAddress;
37
- baseFork;
38
- stateMachine;
39
- logger;
40
- blockNumber;
41
- timestamp;
42
- sideEffectCounter;
43
- msgSender;
44
- functionSelector;
45
- pxeOracleInterface;
46
- privateLogs;
47
- committedBlocks;
48
- ROLLUP_VERSION;
49
- CHAIN_ID;
50
- node;
51
- simulator;
52
- noteCache;
53
- authwits;
54
- // Used by privateSetSenderForTags and privateGetSenderForTags oracles.
55
- senderForTags;
56
- executionCache;
57
- constructor(keyStore, contractDataProvider, noteDataProvider, capsuleDataProvider, taggingDataProvider, addressDataProvider, privateEventDataProvider, accountDataProvider, contractAddress, baseFork, stateMachine){
58
- super(), this.keyStore = keyStore, this.contractDataProvider = contractDataProvider, this.noteDataProvider = noteDataProvider, this.capsuleDataProvider = capsuleDataProvider, this.taggingDataProvider = taggingDataProvider, this.addressDataProvider = addressDataProvider, this.privateEventDataProvider = privateEventDataProvider, this.accountDataProvider = accountDataProvider, this.contractAddress = contractAddress, this.baseFork = baseFork, this.stateMachine = stateMachine, this.blockNumber = 1, this.timestamp = GENESIS_TIMESTAMP, this.sideEffectCounter = 0, this.functionSelector = FunctionSelector.fromField(new Fr(0)), this.privateLogs = [], this.committedBlocks = new Set(), this.ROLLUP_VERSION = 1, this.CHAIN_ID = 1, this.simulator = new WASMSimulator(), this.authwits = new Map();
59
- this.logger = createLogger('txe:oracle');
60
- this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
61
- this.node = stateMachine.node;
62
- // Default msg_sender (for entrypoints) is now Fr.max_value rather than 0 addr (see #7190 & #7404)
63
- this.msgSender = AztecAddress.fromField(Fr.MAX_FIELD_VALUE);
64
- this.executionCache = new HashedValuesCache();
65
- this.pxeOracleInterface = new PXEOracleInterface(this.node, this.keyStore, this.contractDataProvider, this.noteDataProvider, this.capsuleDataProvider, this.stateMachine.syncDataProvider, this.taggingDataProvider, this.addressDataProvider, this.privateEventDataProvider, this.logger);
66
- }
67
- // Utils
68
- utilityGetChainId() {
69
- return Promise.resolve(new Fr(this.CHAIN_ID));
70
- }
71
- utilityGetVersion() {
72
- return Promise.resolve(new Fr(this.ROLLUP_VERSION));
73
- }
74
- getMsgSender() {
75
- return this.msgSender;
76
- }
77
- txeSetContractAddress(contractAddress) {
78
- this.contractAddress = contractAddress;
79
- }
80
- // TODO: Currently this is only ever used to increment this.blockNumber by 1. Refactor this as `advanceBlock()`.
81
- setBlockNumber(blockNumber) {
82
- this.blockNumber = blockNumber;
83
- }
84
- async txeAdvanceBlocksBy(blocks) {
85
- this.logger.debug(`time traveling ${blocks} blocks`);
86
- for(let i = 0; i < blocks; i++){
87
- const blockNumber = await this.utilityGetBlockNumber();
88
- await this.commitState();
89
- this.setBlockNumber(blockNumber + 1);
90
- }
91
- }
92
- txeAdvanceTimestampBy(duration) {
93
- this.logger.debug(`time traveling ${duration} seconds`);
94
- this.timestamp = this.timestamp + duration;
95
- }
96
- async txeDeploy(artifact, instance, secret) {
97
- // Emit deployment nullifier
98
- await this.noteCache.nullifierCreated(AztecAddress.fromNumber(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), instance.address.toField());
99
- // Make sure the deployment nullifier gets included in a tx in a block
100
- const blockNumber = await this.utilityGetBlockNumber();
101
- await this.commitState();
102
- this.setBlockNumber(blockNumber + 1);
103
- if (!secret.equals(Fr.ZERO)) {
104
- await this.txeAddAccount(artifact, instance, secret);
105
- } else {
106
- await this.addContractInstance(instance);
107
- await this.addContractArtifact(instance.currentContractClassId, artifact);
108
- this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
109
- }
110
- }
111
- async txeAddAccount(artifact, instance, secret) {
112
- const partialAddress = await computePartialAddress(instance);
113
- this.logger.debug(`Deployed ${artifact.name} at ${instance.address}`);
114
- await this.addContractInstance(instance);
115
- await this.addContractArtifact(instance.currentContractClassId, artifact);
116
- const keyStore = this.getKeyStore();
117
- const completeAddress = await keyStore.addAccount(secret, partialAddress);
118
- const accountDataProvider = this.getAccountDataProvider();
119
- await accountDataProvider.setAccount(completeAddress.address, completeAddress);
120
- const addressDataProvider = this.getAddressDataProvider();
121
- await addressDataProvider.addCompleteAddress(completeAddress);
122
- this.logger.debug(`Created account ${completeAddress.address}`);
123
- return completeAddress;
124
- }
125
- async txeCreateAccount(secret) {
126
- const keyStore = this.getKeyStore();
127
- // This is a footgun !
128
- const completeAddress = await keyStore.addAccount(secret, secret);
129
- const accountDataProvider = this.getAccountDataProvider();
130
- await accountDataProvider.setAccount(completeAddress.address, completeAddress);
131
- const addressDataProvider = this.getAddressDataProvider();
132
- await addressDataProvider.addCompleteAddress(completeAddress);
133
- this.logger.debug(`Created account ${completeAddress.address}`);
134
- return completeAddress;
135
- }
136
- getContractDataProvider() {
137
- return this.contractDataProvider;
138
- }
139
- getKeyStore() {
140
- return this.keyStore;
141
- }
142
- getAccountDataProvider() {
143
- return this.accountDataProvider;
144
- }
145
- getAddressDataProvider() {
146
- return this.addressDataProvider;
147
- }
148
- async addContractInstance(contractInstance) {
149
- await this.contractDataProvider.addContractInstance(contractInstance);
150
- }
151
- async addContractArtifact(contractClassId, artifact) {
152
- await this.contractDataProvider.addContractArtifact(contractClassId, artifact);
153
- }
154
- async txeGetPrivateContextInputs(blockNumber, sideEffectsCounter = this.sideEffectCounter, isStaticCall = false) {
155
- // If blockNumber or timestamp is null, use the values corresponding to the latest historical block (number of
156
- // the block being built - 1)
157
- blockNumber = blockNumber ?? this.blockNumber - 1;
158
- const snap = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(blockNumber);
159
- const previousBlockState = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(blockNumber - 1);
160
- const stateReference = await snap.getStateReference();
161
- const inputs = PrivateContextInputs.empty();
162
- inputs.txContext.chainId = new Fr(this.CHAIN_ID);
163
- inputs.txContext.version = new Fr(this.ROLLUP_VERSION);
164
- inputs.historicalHeader.globalVariables.blockNumber = blockNumber;
165
- inputs.historicalHeader.globalVariables.timestamp = await this.getBlockTimestamp(blockNumber);
166
- inputs.historicalHeader.state = stateReference;
167
- inputs.historicalHeader.lastArchive.root = Fr.fromBuffer((await previousBlockState.getTreeInfo(MerkleTreeId.ARCHIVE)).root);
168
- inputs.callContext = new CallContext(this.msgSender, this.contractAddress, this.functionSelector, isStaticCall);
169
- inputs.startSideEffectCounter = sideEffectsCounter;
170
- this.logger.info(`Created private context for block ${blockNumber}`);
171
- return inputs;
172
- }
173
- async txeAddAuthWitness(address, messageHash) {
174
- const account = await this.accountDataProvider.getAccount(address);
175
- const privateKey = await this.keyStore.getMasterSecretKey(account.publicKeys.masterIncomingViewingPublicKey);
176
- const schnorr = new Schnorr();
177
- const signature = await schnorr.constructSignature(messageHash.toBuffer(), privateKey);
178
- const authWitness = new AuthWitness(messageHash, [
179
- ...signature.toBuffer()
180
- ]);
181
- this.authwits.set(authWitness.requestHash.toString(), authWitness);
182
- }
183
- async checkNullifiersNotInTree(contractAddress, nullifiers) {
184
- const siloedNullifiers = await Promise.all(nullifiers.map((nullifier)=>siloNullifier(contractAddress, nullifier)));
185
- const db = this.baseFork;
186
- const nullifierIndexesInTree = await db.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, siloedNullifiers.map((n)=>n.toBuffer()));
187
- if (nullifierIndexesInTree.some((index)=>index !== undefined)) {
188
- throw new Error(`Rejecting tx for emitting duplicate nullifiers`);
189
- }
190
- }
191
- // TypedOracle
192
- utilityAssertCompatibleOracleVersion(version) {
193
- if (version !== ORACLE_VERSION) {
194
- throw new Error(`Incompatible oracle version. PXE is using version '${ORACLE_VERSION}', but got a request for '${version}'.`);
195
- }
196
- }
197
- utilityGetBlockNumber() {
198
- return Promise.resolve(this.blockNumber);
199
- }
200
- utilityGetTimestamp() {
201
- return Promise.resolve(this.timestamp);
202
- }
203
- txeGetLastBlockTimestamp() {
204
- return this.getBlockTimestamp(this.blockNumber - 1);
205
- }
206
- utilityGetContractAddress() {
207
- return Promise.resolve(this.contractAddress);
208
- }
209
- utilityGetRandomField() {
210
- return Fr.random();
211
- }
212
- privateStoreInExecutionCache(values, hash) {
213
- return this.executionCache.store(values, hash);
214
- }
215
- privateLoadFromExecutionCache(hash) {
216
- const preimage = this.executionCache.getPreimage(hash);
217
- if (!preimage) {
218
- throw new Error(`Preimage for hash ${hash.toString()} not found in cache`);
219
- }
220
- return Promise.resolve(preimage);
221
- }
222
- utilityGetKeyValidationRequest(pkMHash) {
223
- return this.keyStore.getKeyValidationRequest(pkMHash, this.contractAddress);
224
- }
225
- utilityGetContractInstance(address) {
226
- return this.pxeOracleInterface.getContractInstance(address);
227
- }
228
- utilityGetMembershipWitness(blockNumber, treeId, leafValue) {
229
- return this.pxeOracleInterface.getMembershipWitness(blockNumber, treeId, leafValue);
230
- }
231
- utilityGetNullifierMembershipWitness(blockNumber, nullifier) {
232
- return this.pxeOracleInterface.getNullifierMembershipWitness(blockNumber, nullifier);
233
- }
234
- utilityGetPublicDataWitness(blockNumber, leafSlot) {
235
- return this.pxeOracleInterface.getPublicDataWitness(blockNumber, leafSlot);
236
- }
237
- utilityGetLowNullifierMembershipWitness(blockNumber, nullifier) {
238
- return this.pxeOracleInterface.getLowNullifierMembershipWitness(blockNumber, nullifier);
239
- }
240
- utilityGetBlockHeader(blockNumber) {
241
- return this.stateMachine.archiver.getBlockHeader(blockNumber);
242
- }
243
- utilityGetCompleteAddress(account) {
244
- return Promise.resolve(this.accountDataProvider.getAccount(account));
245
- }
246
- utilityGetAuthWitness(messageHash) {
247
- const authwit = this.authwits.get(messageHash.toString());
248
- return Promise.resolve(authwit?.witness);
249
- }
250
- async utilityGetNotes(storageSlot, numSelects, selectByIndexes, selectByOffsets, selectByLengths, selectValues, selectComparators, sortByIndexes, sortByOffsets, sortByLengths, sortOrder, limit, offset, status) {
251
- // Nullified pending notes are already removed from the list.
252
- const pendingNotes = this.noteCache.getNotes(this.contractAddress, storageSlot);
253
- const pendingNullifiers = this.noteCache.getNullifiers(this.contractAddress);
254
- const dbNotes = await this.pxeOracleInterface.getNotes(this.contractAddress, storageSlot, status);
255
- const dbNotesFiltered = dbNotes.filter((n)=>!pendingNullifiers.has(n.siloedNullifier.value));
256
- const notes = pickNotes([
257
- ...dbNotesFiltered,
258
- ...pendingNotes
259
- ], {
260
- selects: selectByIndexes.slice(0, numSelects).map((index, i)=>({
261
- selector: {
262
- index,
263
- offset: selectByOffsets[i],
264
- length: selectByLengths[i]
265
- },
266
- value: selectValues[i],
267
- comparator: selectComparators[i]
268
- })),
269
- sorts: sortByIndexes.map((index, i)=>({
270
- selector: {
271
- index,
272
- offset: sortByOffsets[i],
273
- length: sortByLengths[i]
274
- },
275
- order: sortOrder[i]
276
- })),
277
- limit,
278
- offset
279
- });
280
- this.logger.debug(`Returning ${notes.length} notes for ${this.contractAddress} at ${storageSlot}: ${notes.map((n)=>`${n.noteNonce.toString()}:[${n.note.items.map((i)=>i.toString()).join(',')}]`).join(', ')}`);
281
- if (notes.length > 0) {
282
- const noteLength = notes[0].note.items.length;
283
- if (!notes.every(({ note })=>noteLength === note.items.length)) {
284
- throw new Error('Notes should all be the same length.');
285
- }
286
- }
287
- return notes;
288
- }
289
- privateNotifyCreatedNote(storageSlot, _noteTypeId, noteItems, noteHash, counter) {
290
- const note = new Note(noteItems);
291
- this.noteCache.addNewNote({
292
- contractAddress: this.contractAddress,
293
- storageSlot,
294
- noteNonce: Fr.ZERO,
295
- note,
296
- siloedNullifier: undefined,
297
- noteHash
298
- }, counter);
299
- this.sideEffectCounter = counter + 1;
300
- }
301
- async privateNotifyNullifiedNote(innerNullifier, noteHash, counter) {
302
- await this.checkNullifiersNotInTree(this.contractAddress, [
303
- innerNullifier
304
- ]);
305
- await this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
306
- this.sideEffectCounter = counter + 1;
307
- }
308
- async privateNotifyCreatedNullifier(innerNullifier) {
309
- await this.checkNullifiersNotInTree(this.contractAddress, [
310
- innerNullifier
311
- ]);
312
- await this.noteCache.nullifierCreated(this.contractAddress, innerNullifier);
313
- }
314
- async utilityCheckNullifierExists(innerNullifier) {
315
- const snap = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(this.blockNumber - 1);
316
- const nullifier = await siloNullifier(this.contractAddress, innerNullifier);
317
- const [index] = await snap.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, [
318
- nullifier.toBuffer()
319
- ]);
320
- const inPendingCache = this.noteCache.getNullifiers(this.contractAddress).has(nullifier.toBigInt());
321
- return index !== undefined || inPendingCache;
322
- }
323
- getL1ToL2MembershipWitness(_contractAddress, _messageHash, _secret) {
324
- throw new Error('Method not implemented.');
325
- }
326
- async utilityStorageRead(contractAddress, startStorageSlot, blockNumber, numberOfElements) {
327
- let db;
328
- if (blockNumber === this.blockNumber) {
329
- db = this.baseFork;
330
- } else {
331
- db = this.stateMachine.synchronizer.nativeWorldStateService.getSnapshot(blockNumber);
332
- }
333
- const values = [];
334
- for(let i = 0n; i < numberOfElements; i++){
335
- const storageSlot = startStorageSlot.add(new Fr(i));
336
- const leafSlot = (await computePublicDataTreeLeafSlot(contractAddress, storageSlot)).toBigInt();
337
- const lowLeafResult = await db.getPreviousValueIndex(MerkleTreeId.PUBLIC_DATA_TREE, leafSlot);
338
- let value = Fr.ZERO;
339
- if (lowLeafResult && lowLeafResult.alreadyPresent) {
340
- const preimage = await db.getLeafPreimage(MerkleTreeId.PUBLIC_DATA_TREE, lowLeafResult.index);
341
- value = preimage.leaf.value;
342
- }
343
- this.logger.debug(`Oracle storage read: slot=${storageSlot.toString()} value=${value}`);
344
- values.push(value);
345
- }
346
- return values;
347
- }
348
- async commitState() {
349
- const blockNumber = await this.utilityGetBlockNumber();
350
- const { usedTxRequestHashForNonces } = this.noteCache.finish();
351
- if (this.committedBlocks.has(blockNumber)) {
352
- throw new Error('Already committed state');
353
- } else {
354
- this.committedBlocks.add(blockNumber);
355
- }
356
- const fork = this.baseFork;
357
- const txEffect = TxEffect.empty();
358
- const nonceGenerator = usedTxRequestHashForNonces ? this.getTxRequestHash() : this.noteCache.getAllNullifiers()[0];
359
- let i = 0;
360
- const uniqueNoteHashesFromPrivate = await Promise.all(this.noteCache.getAllNotes().map(async (pendingNote)=>computeUniqueNoteHash(await computeNoteHashNonce(nonceGenerator, i++), await siloNoteHash(pendingNote.note.contractAddress, pendingNote.noteHashForConsumption))));
361
- txEffect.noteHashes = uniqueNoteHashesFromPrivate;
362
- txEffect.nullifiers = this.noteCache.getAllNullifiers();
363
- if (usedTxRequestHashForNonces) {
364
- txEffect.nullifiers.unshift(this.getTxRequestHash());
365
- }
366
- txEffect.privateLogs = this.privateLogs;
367
- txEffect.txHash = new TxHash(new Fr(blockNumber));
368
- const body = new Body([
369
- txEffect
370
- ]);
371
- const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(blockNumber + 1), makeHeader(0, blockNumber, blockNumber), body);
372
- const paddedTxEffects = l2Block.body.txEffects;
373
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
374
- {
375
- const noteHashesPadded = paddedTxEffects.flatMap((txEffect)=>padArrayEnd(txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX));
376
- await fork.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, noteHashesPadded);
377
- await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
378
- }
379
- {
380
- for (const txEffect of paddedTxEffects){
381
- // We do not need to add public data writes because we apply them as we go. We use the sequentialInsert because
382
- // the batchInsert was not working when updating a previously updated slot.
383
- // FIXME: public data writes, note hashes, nullifiers, messages should all be handled in the same way.
384
- // They are all relevant to subsequent enqueued calls and txs.
385
- const nullifiersPadded = padArrayEnd(txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX);
386
- await fork.batchInsert(MerkleTreeId.NULLIFIER_TREE, nullifiersPadded.map((nullifier)=>nullifier.toBuffer()), NULLIFIER_SUBTREE_HEIGHT);
387
- }
388
- }
389
- const stateReference = await fork.getStateReference();
390
- const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
391
- const header = new BlockHeader(new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)), makeContentCommitment(), stateReference, makeGlobalVariables(), Fr.ZERO, Fr.ZERO);
392
- header.globalVariables.blockNumber = blockNumber;
393
- header.globalVariables.timestamp = await this.utilityGetTimestamp();
394
- header.globalVariables.version = new Fr(this.ROLLUP_VERSION);
395
- header.globalVariables.chainId = new Fr(this.CHAIN_ID);
396
- this.logger.info(`Created block ${blockNumber} with timestamp ${header.globalVariables.timestamp}`);
397
- l2Block.header = header;
398
- await fork.updateArchive(l2Block.header);
399
- await this.stateMachine.handleL2Block(l2Block);
400
- this.privateLogs = [];
401
- this.noteCache = new ExecutionNoteCache(this.getTxRequestHash());
402
- }
403
- getTxRequestHash() {
404
- // Using block number itself is invalid since indexed trees come prefilled with the first slots.
405
- return new Fr(this.blockNumber + 6969);
406
- }
407
- notifyCreatedContractClassLog(_log, _counter) {
408
- throw new Error('Method not implemented.');
409
- }
410
- async simulateUtilityFunction(targetContractAddress, functionSelector, argsHash) {
411
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
412
- if (!artifact) {
413
- throw new Error(`Cannot call ${functionSelector} as there is artifact found at ${targetContractAddress}.`);
414
- }
415
- const call = {
416
- name: artifact.name,
417
- selector: functionSelector,
418
- to: targetContractAddress
419
- };
420
- const entryPointArtifact = await this.pxeOracleInterface.getFunctionArtifact(call.to, call.selector);
421
- if (entryPointArtifact.functionType !== FunctionType.UTILITY) {
422
- throw new Error(`Cannot run ${entryPointArtifact.functionType} function as utility`);
423
- }
424
- const oracle = new UtilityExecutionOracle(call.to, [], [], this.pxeOracleInterface, undefined, undefined);
425
- try {
426
- this.logger.verbose(`Executing utility function ${entryPointArtifact.name}`, {
427
- contract: call.to,
428
- selector: call.selector
429
- });
430
- const args = await this.privateLoadFromExecutionCache(argsHash);
431
- const initialWitness = toACVMWitness(0, args);
432
- const acirExecutionResult = await this.simulator.executeUserCircuit(initialWitness, entryPointArtifact, new Oracle(oracle).toACIRCallback()).catch((err)=>{
433
- err.message = resolveAssertionMessageFromError(err, entryPointArtifact);
434
- throw new ExecutionError(err.message, {
435
- contractAddress: call.to,
436
- functionSelector: call.selector
437
- }, extractCallStack(err, entryPointArtifact.debug), {
438
- cause: err
439
- });
440
- });
441
- const returnWitness = witnessMapToFields(acirExecutionResult.returnWitness);
442
- this.logger.verbose(`Utility simulation for ${call.to}.${call.selector} completed`);
443
- const returnHash = await computeVarArgsHash(returnWitness);
444
- this.privateStoreInExecutionCache(returnWitness, returnHash);
445
- return returnHash;
446
- } catch (err) {
447
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
448
- }
449
- }
450
- async getInitialWitness(abi, argsHash, sideEffectCounter, isStaticCall) {
451
- const argumentsSize = countArgumentsSize(abi);
452
- const args = this.executionCache.getPreimage(argsHash);
453
- if (args?.length !== argumentsSize) {
454
- throw new Error('Invalid arguments size');
455
- }
456
- const historicalBlockNumber = this.blockNumber - 1; // i.e. last
457
- const privateContextInputs = await this.txeGetPrivateContextInputs(historicalBlockNumber, sideEffectCounter, isStaticCall);
458
- const privateContextInputsAsFields = privateContextInputs.toFields();
459
- if (privateContextInputsAsFields.length !== PRIVATE_CONTEXT_INPUTS_LENGTH) {
460
- throw new Error('Invalid private context inputs size');
461
- }
462
- const fields = [
463
- ...privateContextInputsAsFields,
464
- ...args
465
- ];
466
- return toACVMWitness(0, fields);
467
- }
468
- async getDebugFunctionName(address, selector) {
469
- return await this.contractDataProvider.getDebugFunctionName(address, selector);
470
- }
471
- utilityDebugLog(message, fields) {
472
- this.logger.verbose(`${applyStringFormatting(message, fields)}`, {
473
- module: `${this.logger.module}:debug_log`
474
- });
475
- }
476
- async privateIncrementAppTaggingSecretIndexAsSender(sender, recipient) {
477
- await this.pxeOracleInterface.incrementAppTaggingSecretIndexAsSender(this.contractAddress, sender, recipient);
478
- }
479
- async utilityGetIndexedTaggingSecretAsSender(sender, recipient) {
480
- return await this.pxeOracleInterface.getIndexedTaggingSecretAsSender(this.contractAddress, sender, recipient);
481
- }
482
- async utilityFetchTaggedLogs(pendingTaggedLogArrayBaseSlot) {
483
- await this.pxeOracleInterface.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot);
484
- await this.pxeOracleInterface.removeNullifiedNotes(this.contractAddress);
485
- return Promise.resolve();
486
- }
487
- async utilityValidateEnqueuedNotesAndEvents(contractAddress, noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot) {
488
- await this.pxeOracleInterface.validateEnqueuedNotesAndEvents(contractAddress, noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot);
489
- }
490
- async utilityBulkRetrieveLogs(contractAddress, logRetrievalRequestsArrayBaseSlot, logRetrievalResponsesArrayBaseSlot) {
491
- return await this.pxeOracleInterface.bulkRetrieveLogs(contractAddress, logRetrievalRequestsArrayBaseSlot, logRetrievalResponsesArrayBaseSlot);
492
- }
493
- utilityStoreCapsule(contractAddress, slot, capsule) {
494
- if (!contractAddress.equals(this.contractAddress)) {
495
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
496
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
497
- }
498
- return this.pxeOracleInterface.storeCapsule(this.contractAddress, slot, capsule);
499
- }
500
- utilityLoadCapsule(contractAddress, slot) {
501
- if (!contractAddress.equals(this.contractAddress)) {
502
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
503
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
504
- }
505
- return this.pxeOracleInterface.loadCapsule(this.contractAddress, slot);
506
- }
507
- utilityDeleteCapsule(contractAddress, slot) {
508
- if (!contractAddress.equals(this.contractAddress)) {
509
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
510
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
511
- }
512
- return this.pxeOracleInterface.deleteCapsule(this.contractAddress, slot);
513
- }
514
- utilityCopyCapsule(contractAddress, srcSlot, dstSlot, numEntries) {
515
- if (!contractAddress.equals(this.contractAddress)) {
516
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
517
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
518
- }
519
- return this.pxeOracleInterface.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries);
520
- }
521
- utilityAes128Decrypt(ciphertext, iv, symKey) {
522
- const aes128 = new Aes128();
523
- return aes128.decryptBufferCBC(ciphertext, iv, symKey);
524
- }
525
- utilityGetSharedSecret(address, ephPk) {
526
- return this.pxeOracleInterface.getSharedSecret(address, ephPk);
527
- }
528
- privateGetSenderForTags() {
529
- return Promise.resolve(this.senderForTags);
530
- }
531
- privateSetSenderForTags(senderForTags) {
532
- this.senderForTags = senderForTags;
533
- return Promise.resolve();
534
- }
535
- async txePrivateCallNewFlow(from, targetContractAddress = AztecAddress.zero(), functionSelector = FunctionSelector.empty(), args, argsHash = Fr.zero(), isStaticCall = false) {
536
- this.logger.verbose(`Executing external function ${await this.getDebugFunctionName(targetContractAddress, functionSelector)}@${targetContractAddress} isStaticCall=${isStaticCall}`);
537
- const artifact = await this.contractDataProvider.getFunctionArtifact(targetContractAddress, functionSelector);
538
- if (artifact === undefined) {
539
- if (functionSelector.equals(await FunctionSelector.fromSignature('verify_private_authwit(Field)'))) {
540
- throw new Error('Found no account contract artifact for a private authwit check - use `create_contract_account` instead of `create_light_account` for authwit support.');
541
- } else {
542
- throw new Error('Function Artifact does not exist');
543
- }
544
- }
545
- const callContext = new CallContext(from, targetContractAddress, functionSelector, isStaticCall);
546
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
547
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
548
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
549
- const txContext = new TxContext(this.CHAIN_ID, this.ROLLUP_VERSION, gasSettings);
550
- const blockHeader = await this.pxeOracleInterface.getBlockHeader();
551
- const noteCache = new ExecutionNoteCache(this.getTxRequestHash());
552
- const privateExecutionOracle = new PrivateExecutionOracle(argsHash, txContext, callContext, /** Header of a block whose state is used during private execution (not the block the transaction is included in). */ blockHeader, /** List of transient auth witnesses to be used during this simulation */ Array.from(this.authwits.values()), /** List of transient auth witnesses to be used during this simulation */ [], HashedValuesCache.create(), noteCache, this.pxeOracleInterface, this.simulator, 0, 1, undefined, undefined, /**
553
- * In TXE, the typical transaction entrypoint is skipped, so we need to simulate the actions that such a
554
- * contract would perform, including setting senderForTags.
555
- */ from);
556
- privateExecutionOracle.privateStoreInExecutionCache(args, argsHash);
557
- // 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.
558
- let result;
559
- let executionResult;
560
- try {
561
- executionResult = await executePrivateFunction(this.simulator, privateExecutionOracle, artifact, targetContractAddress, functionSelector);
562
- const { usedTxRequestHashForNonces } = noteCache.finish();
563
- const firstNullifierHint = usedTxRequestHashForNonces ? Fr.ZERO : noteCache.getAllNullifiers()[0];
564
- const publicCallRequests = collectNested([
565
- executionResult
566
- ], (r)=>r.publicInputs.publicCallRequests.getActiveItems().map((r)=>r.inner).concat(r.publicInputs.publicTeardownCallRequest.isEmpty() ? [] : [
567
- r.publicInputs.publicTeardownCallRequest
568
- ]));
569
- const publicFunctionsCalldata = await Promise.all(publicCallRequests.map(async (r)=>{
570
- const calldata = await privateExecutionOracle.privateLoadFromExecutionCache(r.calldataHash);
571
- return new HashedValues(calldata, r.calldataHash);
572
- }));
573
- result = new PrivateExecutionResult(executionResult, firstNullifierHint, publicFunctionsCalldata);
574
- } catch (err) {
575
- throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
576
- }
577
- if (executionResult.returnValues !== undefined) {
578
- const { returnValues } = executionResult;
579
- // This is a bit of a hack to not deal with returning a slice in nr which is what normally happens.
580
- // Investigate whether it is faster to do this or return from the oracle directly.
581
- const returnValuesHash = await computeVarArgsHash(returnValues);
582
- this.privateStoreInExecutionCache(returnValues, returnValuesHash);
583
- }
584
- // According to the protocol rules, the nonce generator for the note hashes
585
- // can either be the first nullifier in the tx or the hash of the initial tx request
586
- // if there are none.
587
- const nonceGenerator = result.firstNullifier.equals(Fr.ZERO) ? this.getTxRequestHash() : result.firstNullifier;
588
- const { publicInputs } = await generateSimulatedProvingResult(result, nonceGenerator, this.contractDataProvider);
589
- const globals = makeGlobalVariables();
590
- globals.blockNumber = this.blockNumber;
591
- globals.timestamp = this.timestamp;
592
- globals.chainId = new Fr(this.CHAIN_ID);
593
- globals.version = new Fr(this.ROLLUP_VERSION);
594
- globals.gasFees = GasFees.empty();
595
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(this));
596
- const guardedMerkleTrees = new GuardedMerkleTreeOperations(this.baseFork);
597
- const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, true, true);
598
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
599
- const tx = await Tx.create({
600
- data: publicInputs,
601
- clientIvcProof: ClientIvcProof.empty(),
602
- contractClassLogFields: [],
603
- publicFunctionCalldata: result.publicFunctionCalldata
604
- });
605
- let checkpoint;
606
- if (isStaticCall) {
607
- checkpoint = await ForkCheckpoint.new(this.baseFork);
608
- }
609
- const results = await processor.process([
610
- tx
611
- ]);
612
- const [processedTx] = results[0];
613
- const failedTxs = results[1];
614
- if (failedTxs.length !== 0) {
615
- throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
616
- } else if (!processedTx.revertCode.isOK()) {
617
- if (processedTx.revertReason) {
618
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
619
- throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
620
- } else {
621
- throw new Error('Contract execution has reverted');
622
- }
623
- }
624
- if (isStaticCall) {
625
- await checkpoint.revert();
626
- return {
627
- endSideEffectCounter: result.entrypoint.publicInputs.endSideEffectCounter,
628
- returnsHash: result.entrypoint.publicInputs.returnsHash,
629
- txHash: tx.getTxHash()
630
- };
631
- }
632
- const fork = this.baseFork;
633
- const txEffect = TxEffect.empty();
634
- txEffect.noteHashes = processedTx.txEffect.noteHashes;
635
- txEffect.nullifiers = processedTx.txEffect.nullifiers;
636
- txEffect.privateLogs = processedTx.txEffect.privateLogs;
637
- txEffect.publicLogs = processedTx.txEffect.publicLogs;
638
- txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
639
- txEffect.txHash = new TxHash(new Fr(this.blockNumber));
640
- const body = new Body([
641
- txEffect
642
- ]);
643
- const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(this.blockNumber + 1), makeHeader(0, this.blockNumber, this.blockNumber), body);
644
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
645
- await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
646
- const stateReference = await fork.getStateReference();
647
- const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
648
- const header = new BlockHeader(new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)), makeContentCommitment(), stateReference, globals, Fr.ZERO, Fr.ZERO);
649
- header.globalVariables.blockNumber = this.blockNumber;
650
- l2Block.header = header;
651
- await fork.updateArchive(l2Block.header);
652
- await this.stateMachine.handleL2Block(l2Block);
653
- this.setBlockNumber(this.blockNumber + 1);
654
- return {
655
- endSideEffectCounter: result.entrypoint.publicInputs.endSideEffectCounter,
656
- returnsHash: result.entrypoint.publicInputs.returnsHash,
657
- txHash: tx.getTxHash()
658
- };
659
- }
660
- async txePublicCallNewFlow(from, targetContractAddress, calldata, isStaticCall) {
661
- this.logger.verbose(`Executing public function ${await this.getDebugFunctionName(targetContractAddress, FunctionSelector.fromField(calldata[0]))}@${targetContractAddress} isStaticCall=${isStaticCall}`);
662
- const gasLimits = new Gas(DEFAULT_DA_GAS_LIMIT, DEFAULT_L2_GAS_LIMIT);
663
- const teardownGasLimits = new Gas(DEFAULT_TEARDOWN_DA_GAS_LIMIT, DEFAULT_TEARDOWN_L2_GAS_LIMIT);
664
- const gasSettings = new GasSettings(gasLimits, teardownGasLimits, GasFees.empty(), GasFees.empty());
665
- const txContext = new TxContext(this.CHAIN_ID, this.ROLLUP_VERSION, gasSettings);
666
- const blockHeader = await this.pxeOracleInterface.getBlockHeader();
667
- const calldataHash = await computeCalldataHash(calldata);
668
- const calldataHashedValues = new HashedValues(calldata, calldataHash);
669
- const globals = makeGlobalVariables();
670
- globals.blockNumber = this.blockNumber;
671
- globals.timestamp = this.timestamp;
672
- globals.chainId = new Fr(this.CHAIN_ID);
673
- globals.version = new Fr(this.ROLLUP_VERSION);
674
- globals.gasFees = GasFees.empty();
675
- const contractsDB = new PublicContractsDB(new TXEPublicContractDataSource(this));
676
- const guardedMerkleTrees = new GuardedMerkleTreeOperations(this.baseFork);
677
- const simulator = new PublicTxSimulator(guardedMerkleTrees, contractsDB, globals, true, true);
678
- const processor = new PublicProcessor(globals, guardedMerkleTrees, contractsDB, simulator, new TestDateProvider());
679
- // We're simulating a scenario in which private execution immediately enqueues a public call and halts. The private
680
- // kernel init would in this case inject a nullifier with the transaction request hash as a non-revertible
681
- // side-effect, which the AVM then expects to exist in order to use it as the nonce generator when siloing notes as
682
- // unique.
683
- const nonRevertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
684
- if (!isStaticCall) {
685
- nonRevertibleAccumulatedData.nullifiers[0] = this.getTxRequestHash();
686
- }
687
- // The enqueued public call itself we make be revertible so that the public execution is itself revertible, as tests
688
- // may require producing reverts.
689
- const revertibleAccumulatedData = PrivateToPublicAccumulatedData.empty();
690
- revertibleAccumulatedData.publicCallRequests[0] = new PublicCallRequest(from, targetContractAddress, isStaticCall, calldataHash);
691
- const inputsForPublic = new PartialPrivateTailPublicInputsForPublic(nonRevertibleAccumulatedData, revertibleAccumulatedData, PublicCallRequest.empty());
692
- const constantData = new TxConstantData(blockHeader, txContext, Fr.zero(), Fr.zero());
693
- const txData = new PrivateKernelTailCircuitPublicInputs(constantData, /*gasUsed=*/ new Gas(0, 0), /*feePayer=*/ AztecAddress.zero(), /*includeByTimestamp=*/ 0n, inputsForPublic, undefined);
694
- const tx = await Tx.create({
695
- data: txData,
696
- clientIvcProof: ClientIvcProof.empty(),
697
- contractClassLogFields: [],
698
- publicFunctionCalldata: [
699
- calldataHashedValues
700
- ]
701
- });
702
- let checkpoint;
703
- if (isStaticCall) {
704
- checkpoint = await ForkCheckpoint.new(this.baseFork);
705
- }
706
- const results = await processor.process([
707
- tx
708
- ]);
709
- const [processedTx] = results[0];
710
- const failedTxs = results[1];
711
- if (failedTxs.length !== 0) {
712
- throw new Error(`Public execution has failed: ${failedTxs[0].error}`);
713
- } else if (!processedTx.revertCode.isOK()) {
714
- if (processedTx.revertReason) {
715
- await enrichPublicSimulationError(processedTx.revertReason, this.contractDataProvider, this.logger);
716
- throw new Error(`Contract execution has reverted: ${processedTx.revertReason.getMessage()}`);
717
- } else {
718
- throw new Error('Contract execution has reverted');
719
- }
720
- }
721
- const returnValues = results[3][0].values;
722
- let returnValuesHash;
723
- if (returnValues !== undefined) {
724
- // This is a bit of a hack to not deal with returning a slice in nr which is what normally happens.
725
- // Investigate whether it is faster to do this or return from the oracle directly.
726
- returnValuesHash = await computeVarArgsHash(returnValues);
727
- this.privateStoreInExecutionCache(returnValues, returnValuesHash);
728
- }
729
- if (isStaticCall) {
730
- await checkpoint.revert();
731
- return {
732
- returnsHash: returnValuesHash ?? Fr.ZERO,
733
- txHash: tx.getTxHash()
734
- };
735
- }
736
- const fork = this.baseFork;
737
- const txEffect = TxEffect.empty();
738
- txEffect.noteHashes = processedTx.txEffect.noteHashes;
739
- txEffect.nullifiers = processedTx.txEffect.nullifiers;
740
- txEffect.privateLogs = processedTx.txEffect.privateLogs;
741
- txEffect.publicLogs = processedTx.txEffect.publicLogs;
742
- txEffect.publicDataWrites = processedTx.txEffect.publicDataWrites;
743
- txEffect.txHash = new TxHash(new Fr(this.blockNumber));
744
- const body = new Body([
745
- txEffect
746
- ]);
747
- const l2Block = new L2Block(makeAppendOnlyTreeSnapshot(this.blockNumber + 1), makeHeader(0, this.blockNumber, this.blockNumber), body);
748
- const l1ToL2Messages = Array(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP).fill(0).map(Fr.zero);
749
- await fork.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2Messages);
750
- const stateReference = await fork.getStateReference();
751
- const archiveInfo = await fork.getTreeInfo(MerkleTreeId.ARCHIVE);
752
- const header = new BlockHeader(new AppendOnlyTreeSnapshot(new Fr(archiveInfo.root), Number(archiveInfo.size)), makeContentCommitment(), stateReference, globals, Fr.ZERO, Fr.ZERO);
753
- header.globalVariables.blockNumber = this.blockNumber;
754
- l2Block.header = header;
755
- await fork.updateArchive(l2Block.header);
756
- await this.stateMachine.handleL2Block(l2Block);
757
- this.setBlockNumber(this.blockNumber + 1);
758
- return {
759
- returnsHash: returnValuesHash ?? Fr.ZERO,
760
- txHash: tx.getTxHash()
761
- };
762
- }
763
- async getBlockTimestamp(blockNumber) {
764
- const blockHeader = await this.stateMachine.archiver.getBlockHeader(blockNumber);
765
- if (!blockHeader) {
766
- throw new Error(`Requested timestamp for block ${blockNumber}, which does not exist`);
767
- }
768
- return blockHeader.globalVariables.timestamp;
769
- }
770
- }