@aztec/archiver 0.80.0 → 0.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dest/archiver/archiver.d.ts +8 -20
  2. package/dest/archiver/archiver.d.ts.map +1 -1
  3. package/dest/archiver/archiver.js +72 -102
  4. package/dest/archiver/archiver_store.d.ts +5 -19
  5. package/dest/archiver/archiver_store.d.ts.map +1 -1
  6. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  7. package/dest/archiver/archiver_store_test_suite.js +105 -142
  8. package/dest/archiver/config.d.ts +2 -0
  9. package/dest/archiver/config.d.ts.map +1 -1
  10. package/dest/archiver/config.js +5 -0
  11. package/dest/archiver/data_retrieval.d.ts +3 -4
  12. package/dest/archiver/data_retrieval.d.ts.map +1 -1
  13. package/dest/archiver/data_retrieval.js +8 -3
  14. package/dest/archiver/index.d.ts +1 -2
  15. package/dest/archiver/index.d.ts.map +1 -1
  16. package/dest/archiver/index.js +0 -1
  17. package/dest/archiver/kv_archiver_store/block_store.d.ts +6 -6
  18. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  19. package/dest/archiver/kv_archiver_store/block_store.js +24 -21
  20. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +6 -14
  21. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  22. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +2 -19
  23. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  24. package/dest/archiver/kv_archiver_store/log_store.js +11 -42
  25. package/dest/archiver/structs/published.d.ts +1 -10
  26. package/dest/archiver/structs/published.d.ts.map +1 -1
  27. package/dest/archiver/structs/published.js +1 -1
  28. package/dest/factory.d.ts +1 -1
  29. package/dest/factory.d.ts.map +1 -1
  30. package/dest/factory.js +6 -24
  31. package/dest/test/mock_l2_block_source.d.ts +10 -0
  32. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  33. package/dest/test/mock_l2_block_source.js +16 -0
  34. package/package.json +12 -13
  35. package/src/archiver/archiver.ts +86 -124
  36. package/src/archiver/archiver_store.ts +5 -21
  37. package/src/archiver/archiver_store_test_suite.ts +116 -147
  38. package/src/archiver/config.ts +8 -0
  39. package/src/archiver/data_retrieval.ts +12 -11
  40. package/src/archiver/index.ts +1 -2
  41. package/src/archiver/kv_archiver_store/block_store.ts +28 -27
  42. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +6 -27
  43. package/src/archiver/kv_archiver_store/log_store.ts +12 -59
  44. package/src/archiver/structs/published.ts +1 -11
  45. package/src/factory.ts +3 -28
  46. package/src/test/mock_l2_block_source.ts +18 -0
  47. package/dest/archiver/kv_archiver_store/nullifier_store.d.ts +0 -12
  48. package/dest/archiver/kv_archiver_store/nullifier_store.d.ts.map +0 -1
  49. package/dest/archiver/kv_archiver_store/nullifier_store.js +0 -73
  50. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +0 -175
  51. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +0 -1
  52. package/dest/archiver/memory_archiver_store/memory_archiver_store.js +0 -636
  53. package/src/archiver/kv_archiver_store/nullifier_store.ts +0 -97
  54. package/src/archiver/memory_archiver_store/memory_archiver_store.ts +0 -801
@@ -1,636 +0,0 @@
1
- import { INITIAL_L2_BLOCK_NUM, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, PUBLIC_LOG_DATA_SIZE_IN_FIELDS } from '@aztec/constants';
2
- import { Fr } from '@aztec/foundation/fields';
3
- import { createLogger } from '@aztec/foundation/log';
4
- import { FunctionSelector } from '@aztec/stdlib/abi';
5
- import { L2BlockHash, wrapInBlock } from '@aztec/stdlib/block';
6
- import { ExtendedContractClassLog, ExtendedPublicLog, LogId, TxScopedL2Log } from '@aztec/stdlib/logs';
7
- import { TxReceipt } from '@aztec/stdlib/tx';
8
- import { L1ToL2MessageStore } from './l1_to_l2_message_store.js';
9
- /**
10
- * Simple, in-memory implementation of an archiver data store.
11
- */ export class MemoryArchiverStore {
12
- maxLogs;
13
- /**
14
- * An array containing all the L2 blocks that have been fetched so far.
15
- */ l2Blocks;
16
- /**
17
- * An array containing all the tx effects in the L2 blocks that have been fetched so far.
18
- */ txEffects;
19
- taggedLogs;
20
- logTagsPerBlock;
21
- privateLogsPerBlock;
22
- publicLogsPerBlock;
23
- contractClassLogsPerBlock;
24
- blockScopedNullifiers;
25
- /**
26
- * Contains all L1 to L2 messages.
27
- */ l1ToL2Messages;
28
- contractClasses;
29
- bytecodeCommitments;
30
- privateFunctions;
31
- unconstrainedFunctions;
32
- contractInstances;
33
- contractInstanceUpdates;
34
- lastL1BlockNewBlocks;
35
- lastL1BlockNewMessages;
36
- lastProvenL2BlockNumber;
37
- lastProvenL2EpochNumber;
38
- functionNames;
39
- #log;
40
- constructor(/** The max number of logs that can be obtained in 1 "getPublicLogs" call. */ maxLogs){
41
- this.maxLogs = maxLogs;
42
- this.l2Blocks = [];
43
- this.txEffects = [];
44
- this.taggedLogs = new Map();
45
- this.logTagsPerBlock = new Map();
46
- this.privateLogsPerBlock = new Map();
47
- this.publicLogsPerBlock = new Map();
48
- this.contractClassLogsPerBlock = new Map();
49
- this.blockScopedNullifiers = new Map();
50
- this.l1ToL2Messages = new L1ToL2MessageStore();
51
- this.contractClasses = new Map();
52
- this.bytecodeCommitments = new Map();
53
- this.privateFunctions = new Map();
54
- this.unconstrainedFunctions = new Map();
55
- this.contractInstances = new Map();
56
- this.contractInstanceUpdates = new Map();
57
- this.lastL1BlockNewBlocks = undefined;
58
- this.lastL1BlockNewMessages = undefined;
59
- this.lastProvenL2BlockNumber = 0;
60
- this.lastProvenL2EpochNumber = 0;
61
- this.functionNames = new Map();
62
- this.#log = createLogger('archiver:data-store');
63
- }
64
- getContractClass(id) {
65
- const contractClass = this.contractClasses.get(id.toString());
66
- return Promise.resolve(contractClass && {
67
- ...contractClass,
68
- privateFunctions: this.privateFunctions.get(id.toString()) ?? [],
69
- unconstrainedFunctions: this.unconstrainedFunctions.get(id.toString()) ?? []
70
- });
71
- }
72
- getContractClassIds() {
73
- return Promise.resolve(Array.from(this.contractClasses.keys()).map((key)=>Fr.fromHexString(key)));
74
- }
75
- getContractInstance(address) {
76
- const instance = this.contractInstances.get(address.toString());
77
- if (!instance) {
78
- return Promise.resolve(undefined);
79
- }
80
- const updates = this.contractInstanceUpdates.get(address.toString()) || [];
81
- if (updates.length > 0) {
82
- const lastUpdate = updates[0];
83
- const currentBlockNumber = this.getLastBlockNumber();
84
- if (currentBlockNumber >= lastUpdate.blockOfChange) {
85
- instance.currentContractClassId = lastUpdate.newContractClassId;
86
- } else if (!lastUpdate.prevContractClassId.isZero()) {
87
- instance.currentContractClassId = lastUpdate.prevContractClassId;
88
- } else {
89
- instance.currentContractClassId = instance.originalContractClassId;
90
- }
91
- }
92
- return Promise.resolve(instance);
93
- }
94
- getBytecodeCommitment(contractClassId) {
95
- return Promise.resolve(this.bytecodeCommitments.get(contractClassId.toString()));
96
- }
97
- addFunctions(contractClassId, newPrivateFunctions, newUnconstrainedFunctions) {
98
- const privateFunctions = this.privateFunctions.get(contractClassId.toString()) ?? [];
99
- const unconstrainedFunctions = this.unconstrainedFunctions.get(contractClassId.toString()) ?? [];
100
- const updatedPrivateFunctions = [
101
- ...privateFunctions,
102
- ...newPrivateFunctions.filter((newFn)=>!privateFunctions.find((f)=>f.selector.equals(newFn.selector)))
103
- ];
104
- const updatedUnconstrainedFunctions = [
105
- ...unconstrainedFunctions,
106
- ...newUnconstrainedFunctions.filter((newFn)=>!unconstrainedFunctions.find((f)=>f.selector.equals(newFn.selector)))
107
- ];
108
- this.privateFunctions.set(contractClassId.toString(), updatedPrivateFunctions);
109
- this.unconstrainedFunctions.set(contractClassId.toString(), updatedUnconstrainedFunctions);
110
- return Promise.resolve(true);
111
- }
112
- addContractClasses(data, bytecodeCommitments, blockNumber) {
113
- for(let i = 0; i < data.length; i++){
114
- const contractClass = data[i];
115
- if (!this.contractClasses.has(contractClass.id.toString())) {
116
- this.contractClasses.set(contractClass.id.toString(), {
117
- ...contractClass,
118
- l2BlockNumber: blockNumber
119
- });
120
- }
121
- if (!this.bytecodeCommitments.has(contractClass.id.toString())) {
122
- this.bytecodeCommitments.set(contractClass.id.toString(), bytecodeCommitments[i]);
123
- }
124
- }
125
- return Promise.resolve(true);
126
- }
127
- deleteContractClasses(data, blockNumber) {
128
- for (const contractClass of data){
129
- const restored = this.contractClasses.get(contractClass.id.toString());
130
- if (restored && restored.l2BlockNumber >= blockNumber) {
131
- this.contractClasses.delete(contractClass.id.toString());
132
- this.bytecodeCommitments.delete(contractClass.id.toString());
133
- }
134
- }
135
- return Promise.resolve(true);
136
- }
137
- addContractInstances(data, _blockNumber) {
138
- for (const contractInstance of data){
139
- this.contractInstances.set(contractInstance.address.toString(), contractInstance);
140
- }
141
- return Promise.resolve(true);
142
- }
143
- deleteContractInstances(data, _blockNumber) {
144
- for (const contractInstance of data){
145
- this.contractInstances.delete(contractInstance.address.toString());
146
- }
147
- return Promise.resolve(true);
148
- }
149
- addContractInstanceUpdates(data, blockNumber) {
150
- for(let logIndex = 0; logIndex < data.length; logIndex++){
151
- const contractInstanceUpdate = data[logIndex];
152
- const updates = this.contractInstanceUpdates.get(contractInstanceUpdate.address.toString()) || [];
153
- updates.unshift({
154
- ...contractInstanceUpdate,
155
- blockNumber,
156
- logIndex
157
- });
158
- this.contractInstanceUpdates.set(contractInstanceUpdate.address.toString(), updates);
159
- }
160
- return Promise.resolve(true);
161
- }
162
- deleteContractInstanceUpdates(data, blockNumber) {
163
- for(let logIndex = 0; logIndex < data.length; logIndex++){
164
- const contractInstanceUpdate = data[logIndex];
165
- let updates = this.contractInstanceUpdates.get(contractInstanceUpdate.address.toString()) || [];
166
- updates = updates.filter((update)=>!(update.blockNumber === blockNumber && update.logIndex === logIndex));
167
- this.contractInstanceUpdates.set(contractInstanceUpdate.address.toString(), updates);
168
- }
169
- return Promise.resolve(true);
170
- }
171
- /**
172
- * Append new blocks to the store's list.
173
- * @param blocks - The L2 blocks to be added to the store and the last processed L1 block.
174
- * @returns True if the operation is successful.
175
- */ async addBlocks(blocks) {
176
- if (blocks.length === 0) {
177
- return Promise.resolve(true);
178
- }
179
- this.lastL1BlockNewBlocks = blocks[blocks.length - 1].l1.blockNumber;
180
- this.l2Blocks.push(...blocks);
181
- const flatTxEffects = blocks.flatMap((b)=>b.data.body.txEffects.map((txEffect)=>({
182
- block: b,
183
- txEffect
184
- })));
185
- const wrappedTxEffects = await Promise.all(flatTxEffects.map((flatTxEffect)=>wrapInBlock(flatTxEffect.txEffect, flatTxEffect.block.data)));
186
- this.txEffects.push(...wrappedTxEffects);
187
- return Promise.resolve(true);
188
- }
189
- /**
190
- * Unwinds blocks from the database
191
- * @param from - The tip of the chain, passed for verification purposes,
192
- * ensuring that we don't end up deleting something we did not intend
193
- * @param blocksToUnwind - The number of blocks we are to unwind
194
- * @returns True if the operation is successful
195
- */ async unwindBlocks(from, blocksToUnwind) {
196
- const last = await this.getSynchedL2BlockNumber();
197
- if (from != last) {
198
- throw new Error(`Can only unwind blocks from the tip (requested ${from} but current tip is ${last})`);
199
- }
200
- const stopAt = from - blocksToUnwind;
201
- while(await this.getSynchedL2BlockNumber() > stopAt){
202
- const block = this.l2Blocks.pop();
203
- if (block == undefined) {
204
- break;
205
- }
206
- block.data.body.txEffects.forEach(()=>this.txEffects.pop());
207
- }
208
- return Promise.resolve(true);
209
- }
210
- #storeTaggedLogsFromPrivate(block) {
211
- const dataStartIndexForBlock = block.header.state.partial.noteHashTree.nextAvailableLeafIndex - block.body.txEffects.length * MAX_NOTE_HASHES_PER_TX;
212
- block.body.txEffects.forEach((txEffect, txIndex)=>{
213
- const txHash = txEffect.txHash;
214
- const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
215
- txEffect.privateLogs.forEach((log)=>{
216
- const tag = log.fields[0];
217
- const currentLogs = this.taggedLogs.get(tag.toString()) || [];
218
- this.taggedLogs.set(tag.toString(), [
219
- ...currentLogs,
220
- new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ false, log.toBuffer())
221
- ]);
222
- const currentTagsInBlock = this.logTagsPerBlock.get(block.number) || [];
223
- this.logTagsPerBlock.set(block.number, [
224
- ...currentTagsInBlock,
225
- tag
226
- ]);
227
- });
228
- });
229
- }
230
- #storeTaggedLogsFromPublic(block) {
231
- const dataStartIndexForBlock = block.header.state.partial.noteHashTree.nextAvailableLeafIndex - block.body.txEffects.length * MAX_NOTE_HASHES_PER_TX;
232
- block.body.txEffects.forEach((txEffect, txIndex)=>{
233
- const txHash = txEffect.txHash;
234
- const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NOTE_HASHES_PER_TX;
235
- txEffect.publicLogs.forEach((log)=>{
236
- // Check that each log stores 3 lengths in its first field. If not, it's not a tagged log:
237
- // See macros/note/mod/ and see how finalization_log[0] is constructed, to understand this monstrosity. (It wasn't me).
238
- // Search the codebase for "disgusting encoding" to see other hardcoded instances of this encoding, that you might need to change if you ever find yourself here.
239
- const firstFieldBuf = log.log[0].toBuffer();
240
- if (!firstFieldBuf.subarray(0, 27).equals(Buffer.alloc(27)) || firstFieldBuf[29] !== 0) {
241
- // See parseLogFromPublic - the first field of a tagged log is 8 bytes structured:
242
- // [ publicLen[0], publicLen[1], 0, privateLen[0], privateLen[1]]
243
- this.#log.warn(`Skipping public log with invalid first field: ${log.log[0]}`);
244
- return;
245
- }
246
- // Check that the length values line up with the log contents
247
- const publicValuesLength = firstFieldBuf.subarray(-5).readUint16BE();
248
- const privateValuesLength = firstFieldBuf.subarray(-5).readUint16BE(3);
249
- // Add 1 for the first field holding lengths
250
- const totalLogLength = 1 + publicValuesLength + privateValuesLength;
251
- // Note that zeroes can be valid log values, so we can only assert that we do not go over the given length
252
- if (totalLogLength > PUBLIC_LOG_DATA_SIZE_IN_FIELDS || log.log.slice(totalLogLength).find((f)=>!f.isZero())) {
253
- this.#log.warn(`Skipping invalid tagged public log with first field: ${log.log[0]}`);
254
- return;
255
- }
256
- // The first elt stores lengths => tag is in fields[1]
257
- const tag = log.log[1];
258
- this.#log.verbose(`Storing public tagged log with tag ${tag.toString()} in block ${block.number}`);
259
- const currentLogs = this.taggedLogs.get(tag.toString()) || [];
260
- this.taggedLogs.set(tag.toString(), [
261
- ...currentLogs,
262
- new TxScopedL2Log(txHash, dataStartIndexForTx, block.number, /* isFromPublic */ true, log.toBuffer())
263
- ]);
264
- const currentTagsInBlock = this.logTagsPerBlock.get(block.number) || [];
265
- this.logTagsPerBlock.set(block.number, [
266
- ...currentTagsInBlock,
267
- tag
268
- ]);
269
- });
270
- });
271
- }
272
- /**
273
- * Append new logs to the store's list.
274
- * @param block - The block for which to add the logs.
275
- * @returns True if the operation is successful.
276
- */ addLogs(blocks) {
277
- blocks.forEach((block)=>{
278
- this.#storeTaggedLogsFromPrivate(block);
279
- this.#storeTaggedLogsFromPublic(block);
280
- this.privateLogsPerBlock.set(block.number, block.body.txEffects.map((txEffect)=>txEffect.privateLogs).flat());
281
- this.publicLogsPerBlock.set(block.number, block.body.txEffects.map((txEffect)=>txEffect.publicLogs).flat());
282
- this.contractClassLogsPerBlock.set(block.number, block.body.txEffects.map((txEffect)=>txEffect.contractClassLogs).flat());
283
- });
284
- return Promise.resolve(true);
285
- }
286
- deleteLogs(blocks) {
287
- const tagsToDelete = blocks.flatMap((block)=>this.logTagsPerBlock.get(block.number));
288
- tagsToDelete.filter((tag)=>tag != undefined).forEach((tag)=>{
289
- this.taggedLogs.delete(tag.toString());
290
- });
291
- blocks.forEach((block)=>{
292
- this.privateLogsPerBlock.delete(block.number);
293
- this.publicLogsPerBlock.delete(block.number);
294
- this.logTagsPerBlock.delete(block.number);
295
- this.contractClassLogsPerBlock.delete(block.number);
296
- });
297
- return Promise.resolve(true);
298
- }
299
- async addNullifiers(blocks) {
300
- await Promise.all(blocks.map(async (block)=>{
301
- const dataStartIndexForBlock = block.header.state.partial.nullifierTree.nextAvailableLeafIndex - block.body.txEffects.length * MAX_NULLIFIERS_PER_TX;
302
- const blockHash = await block.hash();
303
- block.body.txEffects.forEach((txEffects, txIndex)=>{
304
- const dataStartIndexForTx = dataStartIndexForBlock + txIndex * MAX_NULLIFIERS_PER_TX;
305
- txEffects.nullifiers.forEach((nullifier, nullifierIndex)=>{
306
- this.blockScopedNullifiers.set(nullifier.toString(), {
307
- index: BigInt(dataStartIndexForTx + nullifierIndex),
308
- blockNumber: block.number,
309
- blockHash: blockHash.toString()
310
- });
311
- });
312
- });
313
- }));
314
- return Promise.resolve(true);
315
- }
316
- deleteNullifiers(blocks) {
317
- blocks.forEach((block)=>{
318
- block.body.txEffects.forEach((txEffect)=>{
319
- txEffect.nullifiers.forEach((nullifier)=>{
320
- this.blockScopedNullifiers.delete(nullifier.toString());
321
- });
322
- });
323
- });
324
- return Promise.resolve(true);
325
- }
326
- findNullifiersIndexesWithBlock(blockNumber, nullifiers) {
327
- const blockScopedNullifiers = nullifiers.map((nullifier)=>{
328
- const nullifierData = this.blockScopedNullifiers.get(nullifier.toString());
329
- if (nullifierData !== undefined && nullifierData.blockNumber <= blockNumber) {
330
- return {
331
- data: nullifierData.index,
332
- l2BlockHash: nullifierData.blockHash,
333
- l2BlockNumber: nullifierData.blockNumber
334
- };
335
- }
336
- return undefined;
337
- });
338
- return Promise.resolve(blockScopedNullifiers);
339
- }
340
- getTotalL1ToL2MessageCount() {
341
- return Promise.resolve(this.l1ToL2Messages.getTotalL1ToL2MessageCount());
342
- }
343
- /**
344
- * Append L1 to L2 messages to the store.
345
- * @param messages - The L1 to L2 messages to be added to the store and the last processed L1 block.
346
- * @returns True if the operation is successful.
347
- */ addL1ToL2Messages(messages) {
348
- if (typeof this.lastL1BlockNewMessages === 'bigint' && messages.lastProcessedL1BlockNumber <= this.lastL1BlockNewMessages) {
349
- return Promise.resolve(false);
350
- }
351
- this.lastL1BlockNewMessages = messages.lastProcessedL1BlockNumber;
352
- for (const message of messages.retrievedData){
353
- this.l1ToL2Messages.addMessage(message);
354
- }
355
- return Promise.resolve(true);
356
- }
357
- /**
358
- * Gets the L1 to L2 message index in the L1 to L2 message tree.
359
- * @param l1ToL2Message - The L1 to L2 message.
360
- * @returns The index of the L1 to L2 message in the L1 to L2 message tree (undefined if not found).
361
- */ getL1ToL2MessageIndex(l1ToL2Message) {
362
- return Promise.resolve(this.l1ToL2Messages.getMessageIndex(l1ToL2Message));
363
- }
364
- /**
365
- * Gets up to `limit` amount of L2 blocks starting from `from`.
366
- * @param from - Number of the first block to return (inclusive).
367
- * @param limit - The number of blocks to return.
368
- * @returns The requested L2 blocks.
369
- * @remarks When "from" is smaller than genesis block number, blocks from the beginning are returned.
370
- */ getBlocks(from, limit) {
371
- if (limit < 1) {
372
- return Promise.reject(new Error(`Invalid limit: ${limit}`));
373
- }
374
- if (from < INITIAL_L2_BLOCK_NUM) {
375
- return Promise.reject(new Error(`Invalid start: ${from}`));
376
- }
377
- const fromIndex = from - INITIAL_L2_BLOCK_NUM;
378
- if (fromIndex >= this.l2Blocks.length) {
379
- return Promise.resolve([]);
380
- }
381
- const toIndex = fromIndex + limit;
382
- return Promise.resolve(this.l2Blocks.slice(fromIndex, toIndex));
383
- }
384
- async getBlockHeaders(from, limit) {
385
- const blocks = await this.getBlocks(from, limit);
386
- return blocks.map((block)=>block.data.header);
387
- }
388
- /**
389
- * Gets a tx effect.
390
- * @param txHash - The txHash of the tx effect.
391
- * @returns The requested tx effect.
392
- */ getTxEffect(txHash) {
393
- const txEffect = this.txEffects.find((tx)=>tx.data.txHash.equals(txHash));
394
- return Promise.resolve(txEffect);
395
- }
396
- /**
397
- * Gets a receipt of a settled tx.
398
- * @param txHash - The hash of a tx we try to get the receipt for.
399
- * @returns The requested tx receipt (or undefined if not found).
400
- */ async getSettledTxReceipt(txHash) {
401
- for (const block of this.l2Blocks){
402
- for (const txEffect of block.data.body.txEffects){
403
- if (txEffect.txHash.equals(txHash)) {
404
- return new TxReceipt(txHash, TxReceipt.statusFromRevertCode(txEffect.revertCode), '', txEffect.transactionFee.toBigInt(), L2BlockHash.fromField(await block.data.hash()), block.data.number);
405
- }
406
- }
407
- }
408
- return undefined;
409
- }
410
- /**
411
- * Gets L1 to L2 message (to be) included in a given block.
412
- * @param blockNumber - L2 block number to get messages for.
413
- * @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found).
414
- */ getL1ToL2Messages(blockNumber) {
415
- return Promise.resolve(this.l1ToL2Messages.getMessages(blockNumber));
416
- }
417
- /**
418
- * Retrieves all private logs from up to `limit` blocks, starting from the block number `from`.
419
- * @param from - The block number from which to begin retrieving logs.
420
- * @param limit - The maximum number of blocks to retrieve logs from.
421
- * @returns An array of private logs from the specified range of blocks.
422
- */ getPrivateLogs(from, limit) {
423
- if (from < INITIAL_L2_BLOCK_NUM || limit < 1) {
424
- return Promise.resolve([]);
425
- }
426
- if (from > this.l2Blocks.length) {
427
- return Promise.resolve([]);
428
- }
429
- const startIndex = from;
430
- const endIndex = startIndex + limit;
431
- const upper = Math.min(endIndex, this.l2Blocks.length + INITIAL_L2_BLOCK_NUM);
432
- const logsInBlocks = [];
433
- for(let i = startIndex; i < upper; i++){
434
- const logs = this.privateLogsPerBlock.get(i);
435
- if (logs) {
436
- logsInBlocks.push(logs);
437
- }
438
- }
439
- return Promise.resolve(logsInBlocks.flat());
440
- }
441
- /**
442
- * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag).
443
- * @param tags - The tags to filter the logs by.
444
- * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
445
- * that tag.
446
- */ getLogsByTags(tags) {
447
- const noteLogs = tags.map((tag)=>this.taggedLogs.get(tag.toString()) || []);
448
- return Promise.resolve(noteLogs);
449
- }
450
- /**
451
- * Gets public logs based on the provided filter.
452
- * @param filter - The filter to apply to the logs.
453
- * @returns The requested logs.
454
- * @remarks Works by doing an intersection of all params in the filter.
455
- */ getPublicLogs(filter) {
456
- let txHash;
457
- let fromBlock = 0;
458
- let toBlock = this.l2Blocks.length + INITIAL_L2_BLOCK_NUM;
459
- let txIndexInBlock = 0;
460
- let logIndexInTx = 0;
461
- if (filter.afterLog) {
462
- // Continuation parameter is set --> tx hash is ignored
463
- if (filter.fromBlock == undefined || filter.fromBlock <= filter.afterLog.blockNumber) {
464
- fromBlock = filter.afterLog.blockNumber;
465
- txIndexInBlock = filter.afterLog.txIndex;
466
- logIndexInTx = filter.afterLog.logIndex + 1; // We want to start from the next log
467
- } else {
468
- fromBlock = filter.fromBlock;
469
- }
470
- } else {
471
- txHash = filter.txHash;
472
- if (filter.fromBlock !== undefined) {
473
- fromBlock = filter.fromBlock;
474
- }
475
- }
476
- if (filter.toBlock !== undefined) {
477
- toBlock = filter.toBlock;
478
- }
479
- // Ensure the indices are within block array bounds
480
- fromBlock = Math.max(fromBlock, INITIAL_L2_BLOCK_NUM);
481
- toBlock = Math.min(toBlock, this.l2Blocks.length + INITIAL_L2_BLOCK_NUM);
482
- if (fromBlock > this.l2Blocks.length || toBlock < fromBlock || toBlock <= 0) {
483
- return Promise.resolve({
484
- logs: [],
485
- maxLogsHit: false
486
- });
487
- }
488
- const contractAddress = filter.contractAddress;
489
- const logs = [];
490
- for(; fromBlock < toBlock; fromBlock++){
491
- const block = this.l2Blocks[fromBlock - INITIAL_L2_BLOCK_NUM];
492
- const blockLogs = this.publicLogsPerBlock.get(fromBlock);
493
- if (blockLogs) {
494
- for(let logIndex = 0; logIndex < blockLogs.length; logIndex++){
495
- const log = blockLogs[logIndex];
496
- const thisTxEffect = block.data.body.txEffects.filter((effect)=>effect.publicLogs.includes(log))[0];
497
- const thisTxIndexInBlock = block.data.body.txEffects.indexOf(thisTxEffect);
498
- const thisLogIndexInTx = thisTxEffect.publicLogs.indexOf(log);
499
- if ((!txHash || thisTxEffect.txHash.equals(txHash)) && (!contractAddress || log.contractAddress.equals(contractAddress)) && thisTxIndexInBlock >= txIndexInBlock && thisLogIndexInTx >= logIndexInTx) {
500
- logs.push(new ExtendedPublicLog(new LogId(block.data.number, thisTxIndexInBlock, thisLogIndexInTx), log));
501
- if (logs.length === this.maxLogs) {
502
- return Promise.resolve({
503
- logs,
504
- maxLogsHit: true
505
- });
506
- }
507
- }
508
- }
509
- }
510
- }
511
- return Promise.resolve({
512
- logs,
513
- maxLogsHit: false
514
- });
515
- }
516
- /**
517
- * Gets contract class logs based on the provided filter.
518
- * NB: clone of the above fn, but for contract class logs
519
- * @param filter - The filter to apply to the logs.
520
- * @returns The requested logs.
521
- * @remarks Works by doing an intersection of all params in the filter.
522
- */ getContractClassLogs(filter) {
523
- let txHash;
524
- let fromBlock = 0;
525
- let toBlock = this.l2Blocks.length + INITIAL_L2_BLOCK_NUM;
526
- let txIndexInBlock = 0;
527
- let logIndexInTx = 0;
528
- if (filter.afterLog) {
529
- // Continuation parameter is set --> tx hash is ignored
530
- if (filter.fromBlock == undefined || filter.fromBlock <= filter.afterLog.blockNumber) {
531
- fromBlock = filter.afterLog.blockNumber;
532
- txIndexInBlock = filter.afterLog.txIndex;
533
- logIndexInTx = filter.afterLog.logIndex + 1; // We want to start from the next log
534
- } else {
535
- fromBlock = filter.fromBlock;
536
- }
537
- } else {
538
- txHash = filter.txHash;
539
- if (filter.fromBlock !== undefined) {
540
- fromBlock = filter.fromBlock;
541
- }
542
- }
543
- if (filter.toBlock !== undefined) {
544
- toBlock = filter.toBlock;
545
- }
546
- // Ensure the indices are within block array bounds
547
- fromBlock = Math.max(fromBlock, INITIAL_L2_BLOCK_NUM);
548
- toBlock = Math.min(toBlock, this.l2Blocks.length + INITIAL_L2_BLOCK_NUM);
549
- if (fromBlock > this.l2Blocks.length || toBlock < fromBlock || toBlock <= 0) {
550
- return Promise.resolve({
551
- logs: [],
552
- maxLogsHit: false
553
- });
554
- }
555
- const contractAddress = filter.contractAddress;
556
- const logs = [];
557
- for(; fromBlock < toBlock; fromBlock++){
558
- const block = this.l2Blocks[fromBlock - INITIAL_L2_BLOCK_NUM];
559
- const blockLogs = this.contractClassLogsPerBlock.get(fromBlock);
560
- if (blockLogs) {
561
- for(let logIndex = 0; logIndex < blockLogs.length; logIndex++){
562
- const log = blockLogs[logIndex];
563
- const thisTxEffect = block.data.body.txEffects.filter((effect)=>effect.contractClassLogs.includes(log))[0];
564
- const thisTxIndexInBlock = block.data.body.txEffects.indexOf(thisTxEffect);
565
- const thisLogIndexInTx = thisTxEffect.contractClassLogs.indexOf(log);
566
- if ((!txHash || thisTxEffect.txHash.equals(txHash)) && (!contractAddress || log.contractAddress.equals(contractAddress)) && thisTxIndexInBlock >= txIndexInBlock && thisLogIndexInTx >= logIndexInTx) {
567
- logs.push(new ExtendedContractClassLog(new LogId(block.data.number, thisTxIndexInBlock, thisLogIndexInTx), log));
568
- if (logs.length === this.maxLogs) {
569
- return Promise.resolve({
570
- logs,
571
- maxLogsHit: true
572
- });
573
- }
574
- }
575
- }
576
- }
577
- }
578
- return Promise.resolve({
579
- logs,
580
- maxLogsHit: false
581
- });
582
- }
583
- getLastBlockNumber() {
584
- if (this.l2Blocks.length === 0) {
585
- return INITIAL_L2_BLOCK_NUM - 1;
586
- }
587
- return this.l2Blocks[this.l2Blocks.length - 1].data.number;
588
- }
589
- /**
590
- * Gets the number of the latest L2 block processed.
591
- * @returns The number of the latest L2 block processed.
592
- */ getSynchedL2BlockNumber() {
593
- return Promise.resolve(this.getLastBlockNumber());
594
- }
595
- getProvenL2BlockNumber() {
596
- return Promise.resolve(this.lastProvenL2BlockNumber);
597
- }
598
- setProvenL2BlockNumber(l2BlockNumber) {
599
- this.lastProvenL2BlockNumber = l2BlockNumber;
600
- return Promise.resolve();
601
- }
602
- setBlockSynchedL1BlockNumber(l1BlockNumber) {
603
- this.lastL1BlockNewBlocks = l1BlockNumber;
604
- return Promise.resolve();
605
- }
606
- setMessageSynchedL1BlockNumber(l1BlockNumber) {
607
- this.lastL1BlockNewMessages = l1BlockNumber;
608
- return Promise.resolve();
609
- }
610
- getSynchPoint() {
611
- return Promise.resolve({
612
- blocksSynchedTo: this.lastL1BlockNewBlocks,
613
- messagesSynchedTo: this.lastL1BlockNewMessages
614
- });
615
- }
616
- getContractFunctionName(_address, selector) {
617
- return Promise.resolve(this.functionNames.get(selector.toString()));
618
- }
619
- async registerContractFunctionSignatures(_address, signatures) {
620
- for (const sig of signatures){
621
- try {
622
- const selector = await FunctionSelector.fromSignature(sig);
623
- this.functionNames.set(selector.toString(), sig.slice(0, sig.indexOf('(')));
624
- } catch {
625
- this.#log.warn(`Failed to parse signature: ${sig}. Ignoring`);
626
- }
627
- }
628
- }
629
- estimateSize() {
630
- return Promise.resolve({
631
- mappingSize: 0,
632
- actualSize: 0,
633
- numItems: 0
634
- });
635
- }
636
- }