@aztec/txe 3.0.0-nightly.20250926 → 3.0.0-nightly.20250928

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.
@@ -1,303 +0,0 @@
1
- import { Aes128 } from '@aztec/foundation/crypto';
2
- import { Fr } from '@aztec/foundation/fields';
3
- import { applyStringFormatting, createLogger } from '@aztec/foundation/log';
4
- import { ExecutionNoteCache, HashedValuesCache, UtilityContext, pickNotes } from '@aztec/pxe/simulator';
5
- import { Body, L2Block } from '@aztec/stdlib/block';
6
- import { computeNoteHashNonce, computeUniqueNoteHash, siloNoteHash, siloNullifier } from '@aztec/stdlib/hash';
7
- import { Note } from '@aztec/stdlib/note';
8
- import { makeAppendOnlyTreeSnapshot } from '@aztec/stdlib/testing';
9
- import { MerkleTreeId } from '@aztec/stdlib/trees';
10
- import { TxEffect, TxHash } from '@aztec/stdlib/tx';
11
- import { insertTxEffectIntoWorldTrees, makeTXEBlockHeader } from '../utils/block_creation.js';
12
- export class TXE {
13
- contractAddress;
14
- pxeOracleInterface;
15
- forkedWorldTrees;
16
- anchorBlockGlobalVariables;
17
- nextBlockGlobalVariables;
18
- txRequestHash;
19
- isMisc;
20
- isUtility;
21
- isPrivate;
22
- logger;
23
- executionCache;
24
- senderForTags;
25
- noteCache;
26
- constructor(contractAddress, pxeOracleInterface, forkedWorldTrees, anchorBlockGlobalVariables, nextBlockGlobalVariables, txRequestHash){
27
- this.contractAddress = contractAddress;
28
- this.pxeOracleInterface = pxeOracleInterface;
29
- this.forkedWorldTrees = forkedWorldTrees;
30
- this.anchorBlockGlobalVariables = anchorBlockGlobalVariables;
31
- this.nextBlockGlobalVariables = nextBlockGlobalVariables;
32
- this.txRequestHash = txRequestHash;
33
- this.isMisc = true;
34
- this.isUtility = true;
35
- this.isPrivate = true;
36
- this.executionCache = new HashedValuesCache();
37
- this.logger = createLogger('txe:oracle');
38
- this.logger.debug('Entering Private/Utility context');
39
- this.noteCache = new ExecutionNoteCache(txRequestHash);
40
- }
41
- static async create(contractAddress, pxeOracleInterface, forkedWorldTrees, anchorBlockGlobalVariables, nextBlockGlobalVariables, txRequestHash) {
42
- // There is no automatic message discovery and contract-driven syncing process in inlined private or utility
43
- // contexts, which means that known nullifiers are also not searched for, since it is during the tagging sync that
44
- // we perform this. We therefore search for known nullifiers now, as otherwise notes that were nullified would not
45
- // be removed from the database.
46
- await pxeOracleInterface.removeNullifiedNotes(contractAddress);
47
- return new TXE(contractAddress, pxeOracleInterface, forkedWorldTrees, anchorBlockGlobalVariables, nextBlockGlobalVariables, txRequestHash);
48
- }
49
- // Utils
50
- async checkNullifiersNotInTree(contractAddress, nullifiers) {
51
- const siloedNullifiers = await Promise.all(nullifiers.map((nullifier)=>siloNullifier(contractAddress, nullifier)));
52
- const db = this.forkedWorldTrees;
53
- const nullifierIndexesInTree = await db.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, siloedNullifiers.map((n)=>n.toBuffer()));
54
- if (nullifierIndexesInTree.some((index)=>index !== undefined)) {
55
- throw new Error(`Rejecting tx for emitting duplicate nullifiers`);
56
- }
57
- }
58
- utilityGetRandomField() {
59
- return Fr.random();
60
- }
61
- utilityGetUtilityContext() {
62
- return Promise.resolve(UtilityContext.from({
63
- blockNumber: this.anchorBlockGlobalVariables.blockNumber,
64
- timestamp: this.anchorBlockGlobalVariables.timestamp,
65
- contractAddress: this.contractAddress,
66
- version: this.anchorBlockGlobalVariables.version,
67
- chainId: this.anchorBlockGlobalVariables.chainId
68
- }));
69
- }
70
- privateStoreInExecutionCache(values, hash) {
71
- return this.executionCache.store(values, hash);
72
- }
73
- privateLoadFromExecutionCache(hash) {
74
- const preimage = this.executionCache.getPreimage(hash);
75
- if (!preimage) {
76
- throw new Error(`Preimage for hash ${hash.toString()} not found in cache`);
77
- }
78
- return Promise.resolve(preimage);
79
- }
80
- utilityGetKeyValidationRequest(pkMHash) {
81
- return this.pxeOracleInterface.getKeyValidationRequest(pkMHash, this.contractAddress);
82
- }
83
- utilityGetContractInstance(address) {
84
- return this.pxeOracleInterface.getContractInstance(address);
85
- }
86
- utilityGetMembershipWitness(blockNumber, treeId, leafValue) {
87
- return this.pxeOracleInterface.getMembershipWitness(blockNumber, treeId, leafValue);
88
- }
89
- utilityGetNullifierMembershipWitness(blockNumber, nullifier) {
90
- return this.pxeOracleInterface.getNullifierMembershipWitness(blockNumber, nullifier);
91
- }
92
- utilityGetPublicDataWitness(blockNumber, leafSlot) {
93
- return this.pxeOracleInterface.getPublicDataWitness(blockNumber, leafSlot);
94
- }
95
- utilityGetLowNullifierMembershipWitness(blockNumber, nullifier) {
96
- return this.pxeOracleInterface.getLowNullifierMembershipWitness(blockNumber, nullifier);
97
- }
98
- async utilityGetBlockHeader(blockNumber) {
99
- return (await this.pxeOracleInterface.getBlock(blockNumber))?.header.toBlockHeader();
100
- }
101
- utilityGetPublicKeysAndPartialAddress(account) {
102
- return this.pxeOracleInterface.getCompleteAddress(account);
103
- }
104
- async utilityGetNotes(storageSlot, numSelects, selectByIndexes, selectByOffsets, selectByLengths, selectValues, selectComparators, sortByIndexes, sortByOffsets, sortByLengths, sortOrder, limit, offset, status) {
105
- // Nullified pending notes are already removed from the list.
106
- const pendingNotes = this.noteCache.getNotes(this.contractAddress, storageSlot);
107
- const pendingNullifiers = this.noteCache.getNullifiers(this.contractAddress);
108
- const dbNotes = await this.pxeOracleInterface.getNotes(this.contractAddress, storageSlot, status);
109
- const dbNotesFiltered = dbNotes.filter((n)=>!pendingNullifiers.has(n.siloedNullifier.value));
110
- const notes = pickNotes([
111
- ...dbNotesFiltered,
112
- ...pendingNotes
113
- ], {
114
- selects: selectByIndexes.slice(0, numSelects).map((index, i)=>({
115
- selector: {
116
- index,
117
- offset: selectByOffsets[i],
118
- length: selectByLengths[i]
119
- },
120
- value: selectValues[i],
121
- comparator: selectComparators[i]
122
- })),
123
- sorts: sortByIndexes.map((index, i)=>({
124
- selector: {
125
- index,
126
- offset: sortByOffsets[i],
127
- length: sortByLengths[i]
128
- },
129
- order: sortOrder[i]
130
- })),
131
- limit,
132
- offset
133
- });
134
- 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(', ')}`);
135
- if (notes.length > 0) {
136
- const noteLength = notes[0].note.items.length;
137
- if (!notes.every(({ note })=>noteLength === note.items.length)) {
138
- throw new Error('Notes should all be the same length.');
139
- }
140
- }
141
- return notes;
142
- }
143
- privateNotifyCreatedNote(storageSlot, _noteTypeId, noteItems, noteHash, counter) {
144
- const note = new Note(noteItems);
145
- this.noteCache.addNewNote({
146
- contractAddress: this.contractAddress,
147
- storageSlot,
148
- noteNonce: Fr.ZERO,
149
- note,
150
- siloedNullifier: undefined,
151
- noteHash
152
- }, counter);
153
- }
154
- async privateNotifyNullifiedNote(innerNullifier, noteHash, _counter) {
155
- await this.checkNullifiersNotInTree(this.contractAddress, [
156
- innerNullifier
157
- ]);
158
- await this.noteCache.nullifyNote(this.contractAddress, innerNullifier, noteHash);
159
- }
160
- async privateNotifyCreatedNullifier(innerNullifier) {
161
- await this.checkNullifiersNotInTree(this.contractAddress, [
162
- innerNullifier
163
- ]);
164
- await this.noteCache.nullifierCreated(this.contractAddress, innerNullifier);
165
- }
166
- async utilityCheckNullifierExists(innerNullifier) {
167
- const nullifier = await siloNullifier(this.contractAddress, innerNullifier);
168
- const index = await this.pxeOracleInterface.getNullifierIndex(nullifier);
169
- return index !== undefined;
170
- }
171
- async utilityStorageRead(contractAddress, startStorageSlot, blockNumber, numberOfElements) {
172
- const values = [];
173
- for(let i = 0n; i < numberOfElements; i++){
174
- const storageSlot = startStorageSlot.add(new Fr(i));
175
- const value = await this.pxeOracleInterface.getPublicStorageAt(blockNumber, contractAddress, storageSlot);
176
- values.push(value);
177
- }
178
- return values;
179
- }
180
- utilityDebugLog(message, fields) {
181
- this.logger.verbose(`${applyStringFormatting(message, fields)}`, {
182
- module: `${this.logger.module}:debug_log`
183
- });
184
- }
185
- async privateIncrementAppTaggingSecretIndexAsSender(sender, recipient) {
186
- await this.pxeOracleInterface.incrementAppTaggingSecretIndexAsSender(this.contractAddress, sender, recipient);
187
- }
188
- async utilityGetIndexedTaggingSecretAsSender(sender, recipient) {
189
- return await this.pxeOracleInterface.getIndexedTaggingSecretAsSender(this.contractAddress, sender, recipient);
190
- }
191
- async utilityFetchTaggedLogs(pendingTaggedLogArrayBaseSlot) {
192
- await this.pxeOracleInterface.syncTaggedLogs(this.contractAddress, pendingTaggedLogArrayBaseSlot);
193
- await this.pxeOracleInterface.removeNullifiedNotes(this.contractAddress);
194
- return Promise.resolve();
195
- }
196
- async utilityValidateEnqueuedNotesAndEvents(contractAddress, noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot) {
197
- await this.pxeOracleInterface.validateEnqueuedNotesAndEvents(contractAddress, noteValidationRequestsArrayBaseSlot, eventValidationRequestsArrayBaseSlot);
198
- }
199
- async utilityBulkRetrieveLogs(contractAddress, logRetrievalRequestsArrayBaseSlot, logRetrievalResponsesArrayBaseSlot) {
200
- return await this.pxeOracleInterface.bulkRetrieveLogs(contractAddress, logRetrievalRequestsArrayBaseSlot, logRetrievalResponsesArrayBaseSlot);
201
- }
202
- utilityStoreCapsule(contractAddress, slot, capsule) {
203
- if (!contractAddress.equals(this.contractAddress)) {
204
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
205
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
206
- }
207
- return this.pxeOracleInterface.storeCapsule(this.contractAddress, slot, capsule);
208
- }
209
- utilityLoadCapsule(contractAddress, slot) {
210
- if (!contractAddress.equals(this.contractAddress)) {
211
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
212
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
213
- }
214
- return this.pxeOracleInterface.loadCapsule(this.contractAddress, slot);
215
- }
216
- utilityDeleteCapsule(contractAddress, slot) {
217
- if (!contractAddress.equals(this.contractAddress)) {
218
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
219
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
220
- }
221
- return this.pxeOracleInterface.deleteCapsule(this.contractAddress, slot);
222
- }
223
- utilityCopyCapsule(contractAddress, srcSlot, dstSlot, numEntries) {
224
- if (!contractAddress.equals(this.contractAddress)) {
225
- // TODO(#10727): instead of this check that this.contractAddress is allowed to access the external DB
226
- throw new Error(`Contract ${contractAddress} is not allowed to access ${this.contractAddress}'s PXE DB`);
227
- }
228
- return this.pxeOracleInterface.copyCapsule(this.contractAddress, srcSlot, dstSlot, numEntries);
229
- }
230
- utilityAes128Decrypt(ciphertext, iv, symKey) {
231
- const aes128 = new Aes128();
232
- return aes128.decryptBufferCBC(ciphertext, iv, symKey);
233
- }
234
- utilityGetSharedSecret(address, ephPk) {
235
- return this.pxeOracleInterface.getSharedSecret(address, ephPk);
236
- }
237
- privateGetSenderForTags() {
238
- return Promise.resolve(this.senderForTags);
239
- }
240
- privateSetSenderForTags(senderForTags) {
241
- this.senderForTags = senderForTags;
242
- return Promise.resolve();
243
- }
244
- async close() {
245
- this.logger.debug('Exiting Private Context, building block with collected side effects', {
246
- blockNumber: this.nextBlockGlobalVariables.blockNumber
247
- });
248
- const txEffect = await this.makeTxEffect();
249
- await insertTxEffectIntoWorldTrees(txEffect, this.forkedWorldTrees);
250
- const block = new L2Block(makeAppendOnlyTreeSnapshot(), await makeTXEBlockHeader(this.forkedWorldTrees, this.nextBlockGlobalVariables), new Body([
251
- txEffect
252
- ]));
253
- await this.forkedWorldTrees.close();
254
- this.logger.debug('Exited PublicContext with built block', {
255
- blockNumber: block.number,
256
- txEffects: block.body.txEffects
257
- });
258
- return block;
259
- }
260
- async makeTxEffect() {
261
- const txEffect = TxEffect.empty();
262
- const { usedTxRequestHashForNonces } = this.noteCache.finish();
263
- const nonceGenerator = usedTxRequestHashForNonces ? this.txRequestHash : this.noteCache.getAllNullifiers()[0];
264
- txEffect.noteHashes = await Promise.all(this.noteCache.getAllNotes().map(async (pendingNote, i)=>computeUniqueNoteHash(await computeNoteHashNonce(nonceGenerator, i), await siloNoteHash(pendingNote.note.contractAddress, pendingNote.noteHashForConsumption))));
265
- // Nullifiers are already siloed
266
- txEffect.nullifiers = this.noteCache.getAllNullifiers();
267
- if (usedTxRequestHashForNonces) {
268
- txEffect.nullifiers.unshift(this.txRequestHash);
269
- }
270
- txEffect.txHash = new TxHash(new Fr(this.nextBlockGlobalVariables.blockNumber));
271
- return txEffect;
272
- }
273
- // TODO: this class will soon be replaced with the real UtilityExecutionOracle and PrivateExecutionOracle classes. The
274
- // functions below are not currently used in Noir tests, and in most cases they're caught beforehand by the RPC
275
- // translator - we just have a temporary empty implementation until we finalize the migration.
276
- utilityAssertCompatibleOracleVersion(_version) {
277
- throw new Error('Method not implemented.');
278
- }
279
- utilityGetAuthWitness(_messageHash) {
280
- throw new Error('Method not implemented.');
281
- }
282
- utilityGetL1ToL2MembershipWitness(_contractAddress, _messageHash, _secret) {
283
- throw new Error('Method not implemented.');
284
- }
285
- utilityEmitOffchainEffect(_data) {
286
- throw new Error('Method not implemented.');
287
- }
288
- privateNotifyCreatedContractClassLog(_log, _counter) {
289
- throw new Error('Method not implemented.');
290
- }
291
- privateCallPrivateFunction(_targetContractAddress, _functionSelector, _argsHash, _sideEffectCounter, _isStaticCall) {
292
- throw new Error('Method not implemented.');
293
- }
294
- privateNotifyEnqueuedPublicFunctionCall(_targetContractAddress, _calldataHash, _sideEffectCounter, _isStaticCall) {
295
- throw new Error('Method not implemented.');
296
- }
297
- privateNotifySetPublicTeardownFunctionCall(_targetContractAddress, _calldataHash, _sideEffectCounter, _isStaticCall) {
298
- throw new Error('Method not implemented.');
299
- }
300
- privateNotifySetMinRevertibleSideEffectCounter(_minRevertibleSideEffectCounter) {
301
- throw new Error('Method not implemented.');
302
- }
303
- }