@aztec/archiver 0.55.1 → 0.57.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 (78) hide show
  1. package/README.md +1 -1
  2. package/dest/archiver/archiver.d.ts +27 -25
  3. package/dest/archiver/archiver.d.ts.map +1 -1
  4. package/dest/archiver/archiver.js +391 -169
  5. package/dest/archiver/archiver_store.d.ts +47 -23
  6. package/dest/archiver/archiver_store.d.ts.map +1 -1
  7. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  8. package/dest/archiver/archiver_store_test_suite.js +75 -42
  9. package/dest/archiver/config.js +6 -6
  10. package/dest/archiver/data_retrieval.d.ts +32 -5
  11. package/dest/archiver/data_retrieval.d.ts.map +1 -1
  12. package/dest/archiver/data_retrieval.js +126 -16
  13. package/dest/archiver/epoch_helpers.d.ts +15 -0
  14. package/dest/archiver/epoch_helpers.d.ts.map +1 -0
  15. package/dest/archiver/epoch_helpers.js +23 -0
  16. package/dest/archiver/kv_archiver_store/block_store.d.ts +22 -3
  17. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  18. package/dest/archiver/kv_archiver_store/block_store.js +75 -12
  19. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +2 -1
  20. package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -1
  21. package/dest/archiver/kv_archiver_store/contract_class_store.js +11 -4
  22. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +1 -0
  23. package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -1
  24. package/dest/archiver/kv_archiver_store/contract_instance_store.js +4 -1
  25. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +31 -23
  26. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  27. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +65 -38
  28. package/dest/archiver/kv_archiver_store/log_store.d.ts +4 -5
  29. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  30. package/dest/archiver/kv_archiver_store/log_store.js +18 -14
  31. package/dest/archiver/kv_archiver_store/message_store.d.ts +2 -0
  32. package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
  33. package/dest/archiver/kv_archiver_store/message_store.js +18 -8
  34. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts +1 -0
  35. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts.map +1 -1
  36. package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.js +4 -1
  37. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +23 -39
  38. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
  39. package/dest/archiver/memory_archiver_store/memory_archiver_store.js +132 -91
  40. package/dest/index.d.ts +0 -1
  41. package/dest/index.d.ts.map +1 -1
  42. package/dest/index.js +2 -2
  43. package/dest/test/index.d.ts +2 -0
  44. package/dest/test/index.d.ts.map +1 -0
  45. package/dest/test/index.js +2 -0
  46. package/dest/test/mock_l2_block_source.d.ts +73 -0
  47. package/dest/test/mock_l2_block_source.d.ts.map +1 -0
  48. package/dest/test/mock_l2_block_source.js +134 -0
  49. package/package.json +15 -11
  50. package/src/archiver/archiver.ts +531 -248
  51. package/src/archiver/archiver_store.ts +53 -31
  52. package/src/archiver/archiver_store_test_suite.ts +93 -81
  53. package/src/archiver/config.ts +5 -5
  54. package/src/archiver/data_retrieval.ts +189 -30
  55. package/src/archiver/epoch_helpers.ts +26 -0
  56. package/src/archiver/kv_archiver_store/block_store.ts +87 -12
  57. package/src/archiver/kv_archiver_store/contract_class_store.ts +18 -5
  58. package/src/archiver/kv_archiver_store/contract_instance_store.ts +4 -0
  59. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +74 -47
  60. package/src/archiver/kv_archiver_store/log_store.ts +18 -18
  61. package/src/archiver/kv_archiver_store/message_store.ts +18 -5
  62. package/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +4 -0
  63. package/src/archiver/memory_archiver_store/memory_archiver_store.ts +155 -108
  64. package/src/index.ts +1 -2
  65. package/src/test/index.ts +1 -0
  66. package/src/test/mock_l2_block_source.ts +165 -0
  67. package/dest/archiver/eth_log_handlers.d.ts +0 -59
  68. package/dest/archiver/eth_log_handlers.d.ts.map +0 -1
  69. package/dest/archiver/eth_log_handlers.js +0 -155
  70. package/dest/archiver/kv_archiver_store/block_body_store.d.ts +0 -34
  71. package/dest/archiver/kv_archiver_store/block_body_store.d.ts.map +0 -1
  72. package/dest/archiver/kv_archiver_store/block_body_store.js +0 -65
  73. package/dest/archiver/kv_archiver_store/proven_store.d.ts +0 -14
  74. package/dest/archiver/kv_archiver_store/proven_store.d.ts.map +0 -1
  75. package/dest/archiver/kv_archiver_store/proven_store.js +0 -30
  76. package/src/archiver/eth_log_handlers.ts +0 -213
  77. package/src/archiver/kv_archiver_store/block_body_store.ts +0 -74
  78. package/src/archiver/kv_archiver_store/proven_store.ts +0 -34
@@ -1,5 +1,4 @@
1
1
  import {
2
- type Body,
3
2
  type EncryptedL2BlockL2Logs,
4
3
  type EncryptedNoteL2BlockL2Logs,
5
4
  ExtendedUnencryptedL2Log,
@@ -16,18 +15,19 @@ import {
16
15
  TxReceipt,
17
16
  type UnencryptedL2BlockL2Logs,
18
17
  } from '@aztec/circuit-types';
19
- import { Fr, INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js';
18
+ import { Fr, type Header, INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js';
20
19
  import { type ContractArtifact } from '@aztec/foundation/abi';
21
20
  import { type AztecAddress } from '@aztec/foundation/aztec-address';
22
21
  import {
23
22
  type ContractClassPublic,
23
+ type ContractClassPublicWithBlockNumber,
24
24
  type ContractInstanceWithAddress,
25
25
  type ExecutablePrivateFunctionWithMembershipProof,
26
26
  type UnconstrainedFunctionWithMembershipProof,
27
27
  } from '@aztec/types/contracts';
28
28
 
29
29
  import { type ArchiverDataStore, type ArchiverL1SynchPoint } from '../archiver_store.js';
30
- import { type DataRetrieval, type SingletonDataRetrieval } from '../structs/data_retrieval.js';
30
+ import { type DataRetrieval } from '../structs/data_retrieval.js';
31
31
  import { type L1Published } from '../structs/published.js';
32
32
  import { L1ToL2MessageStore } from './l1_to_l2_message_store.js';
33
33
 
@@ -40,33 +40,16 @@ export class MemoryArchiverStore implements ArchiverDataStore {
40
40
  */
41
41
  private l2Blocks: L1Published<L2Block>[] = [];
42
42
 
43
- /**
44
- * A mapping of body hash to body
45
- */
46
- private l2BlockBodies: Map<string, Body> = new Map();
47
-
48
43
  /**
49
44
  * An array containing all the tx effects in the L2 blocks that have been fetched so far.
50
45
  */
51
46
  private txEffects: TxEffect[] = [];
52
47
 
53
- /**
54
- * An array containing all the encrypted logs that have been fetched so far.
55
- * Note: Index in the "outer" array equals to (corresponding L2 block's number - INITIAL_L2_BLOCK_NUM).
56
- */
57
- private noteEncryptedLogsPerBlock: EncryptedNoteL2BlockL2Logs[] = [];
48
+ private noteEncryptedLogsPerBlock: Map<number, EncryptedNoteL2BlockL2Logs> = new Map();
58
49
 
59
- /**
60
- * An array containing all the encrypted logs that have been fetched so far.
61
- * Note: Index in the "outer" array equals to (corresponding L2 block's number - INITIAL_L2_BLOCK_NUM).
62
- */
63
- private encryptedLogsPerBlock: EncryptedL2BlockL2Logs[] = [];
50
+ private encryptedLogsPerBlock: Map<number, EncryptedL2BlockL2Logs> = new Map();
64
51
 
65
- /**
66
- * An array containing all the unencrypted logs that have been fetched so far.
67
- * Note: Index in the "outer" array equals to (corresponding L2 block's number - INITIAL_L2_BLOCK_NUM).
68
- */
69
- private unencryptedLogsPerBlock: UnencryptedL2BlockL2Logs[] = [];
52
+ private unencryptedLogsPerBlock: Map<number, UnencryptedL2BlockL2Logs> = new Map();
70
53
 
71
54
  /**
72
55
  * Contains all L1 to L2 messages.
@@ -75,7 +58,7 @@ export class MemoryArchiverStore implements ArchiverDataStore {
75
58
 
76
59
  private contractArtifacts: Map<string, ContractArtifact> = new Map();
77
60
 
78
- private contractClasses: Map<string, ContractClassPublic> = new Map();
61
+ private contractClasses: Map<string, ContractClassPublicWithBlockNumber> = new Map();
79
62
 
80
63
  private privateFunctions: Map<string, ExecutablePrivateFunctionWithMembershipProof[]> = new Map();
81
64
 
@@ -84,11 +67,10 @@ export class MemoryArchiverStore implements ArchiverDataStore {
84
67
  private contractInstances: Map<string, ContractInstanceWithAddress> = new Map();
85
68
 
86
69
  private lastL1BlockNewBlocks: bigint | undefined = undefined;
87
- private lastL1BlockNewBlockBodies: bigint | undefined = undefined;
88
70
  private lastL1BlockNewMessages: bigint | undefined = undefined;
89
- private lastL1BlockNewProvenLogs: bigint | undefined = undefined;
90
71
 
91
72
  private lastProvenL2BlockNumber: number = 0;
73
+ private lastProvenL2EpochNumber: number = 0;
92
74
 
93
75
  constructor(
94
76
  /** The max number of logs that can be obtained in 1 "getUnencryptedLogs" call. */
@@ -136,9 +118,24 @@ export class MemoryArchiverStore implements ArchiverDataStore {
136
118
  return Promise.resolve(true);
137
119
  }
138
120
 
139
- public addContractClasses(data: ContractClassPublic[], _blockNumber: number): Promise<boolean> {
121
+ public addContractClasses(data: ContractClassPublic[], blockNumber: number): Promise<boolean> {
140
122
  for (const contractClass of data) {
141
- this.contractClasses.set(contractClass.id.toString(), contractClass);
123
+ if (!this.contractClasses.has(contractClass.id.toString())) {
124
+ this.contractClasses.set(contractClass.id.toString(), {
125
+ ...contractClass,
126
+ l2BlockNumber: blockNumber,
127
+ });
128
+ }
129
+ }
130
+ return Promise.resolve(true);
131
+ }
132
+
133
+ public deleteContractClasses(data: ContractClassPublic[], blockNumber: number): Promise<boolean> {
134
+ for (const contractClass of data) {
135
+ const restored = this.contractClasses.get(contractClass.id.toString());
136
+ if (restored && restored.l2BlockNumber >= blockNumber) {
137
+ this.contractClasses.delete(contractClass.id.toString());
138
+ }
142
139
  }
143
140
  return Promise.resolve(true);
144
141
  }
@@ -150,6 +147,13 @@ export class MemoryArchiverStore implements ArchiverDataStore {
150
147
  return Promise.resolve(true);
151
148
  }
152
149
 
150
+ public deleteContractInstances(data: ContractInstanceWithAddress[], _blockNumber: number): Promise<boolean> {
151
+ for (const contractInstance of data) {
152
+ this.contractInstances.delete(contractInstance.address.toString());
153
+ }
154
+ return Promise.resolve(true);
155
+ }
156
+
153
157
  /**
154
158
  * Append new blocks to the store's list.
155
159
  * @param blocks - The L2 blocks to be added to the store and the last processed L1 block.
@@ -163,62 +167,63 @@ export class MemoryArchiverStore implements ArchiverDataStore {
163
167
  this.lastL1BlockNewBlocks = blocks[blocks.length - 1].l1.blockNumber;
164
168
  this.l2Blocks.push(...blocks);
165
169
  this.txEffects.push(...blocks.flatMap(b => b.data.body.txEffects));
170
+
166
171
  return Promise.resolve(true);
167
172
  }
168
173
 
169
174
  /**
170
- * Append new block bodies to the store's list.
171
- * @param blockBodies - The L2 block bodies to be added to the store.
172
- * @returns True if the operation is successful.
175
+ * Unwinds blocks from the database
176
+ * @param from - The tip of the chain, passed for verification purposes,
177
+ * ensuring that we don't end up deleting something we did not intend
178
+ * @param blocksToUnwind - The number of blocks we are to unwind
179
+ * @returns True if the operation is successful
173
180
  */
174
- addBlockBodies(blockBodies: DataRetrieval<Body>): Promise<boolean> {
175
- for (const body of blockBodies.retrievedData) {
176
- void this.l2BlockBodies.set(body.getTxsEffectsHash().toString('hex'), body);
181
+ public async unwindBlocks(from: number, blocksToUnwind: number): Promise<boolean> {
182
+ const last = await this.getSynchedL2BlockNumber();
183
+ if (from != last) {
184
+ throw new Error(`Can only remove the tip`);
177
185
  }
178
- this.lastL1BlockNewBlockBodies = blockBodies.lastProcessedL1BlockNumber;
179
- return Promise.resolve(true);
180
- }
181
186
 
182
- /**
183
- * Gets block bodies that have the same txHashes as we supply.
184
- *
185
- * @param txsEffectsHashes - A list of txsEffectsHashes (body hashes).
186
- * @returns The requested L2 block bodies
187
- */
188
- getBlockBodies(txsEffectsHashes: Buffer[]): Promise<(Body | undefined)[]> {
189
- return Promise.resolve(
190
- txsEffectsHashes.map(txsEffectsHash => this.l2BlockBodies.get(txsEffectsHash.toString('hex'))),
191
- );
187
+ const stopAt = from - blocksToUnwind;
188
+ while ((await this.getSynchedL2BlockNumber()) > stopAt) {
189
+ const block = this.l2Blocks.pop();
190
+ if (block == undefined) {
191
+ break;
192
+ }
193
+ block.data.body.txEffects.forEach(() => this.txEffects.pop());
194
+ }
195
+
196
+ return Promise.resolve(true);
192
197
  }
193
198
 
194
199
  /**
195
200
  * Append new logs to the store's list.
196
- * @param encryptedLogs - The encrypted logs to be added to the store.
197
- * @param unencryptedLogs - The unencrypted logs to be added to the store.
198
- * @param blockNumber - The block for which to add the logs.
201
+ * @param block - The block for which to add the logs.
199
202
  * @returns True if the operation is successful.
200
203
  */
201
- addLogs(
202
- noteEncryptedLogs: EncryptedNoteL2BlockL2Logs,
203
- encryptedLogs: EncryptedL2BlockL2Logs,
204
- unencryptedLogs: UnencryptedL2BlockL2Logs,
205
- blockNumber: number,
206
- ): Promise<boolean> {
207
- if (noteEncryptedLogs) {
208
- this.noteEncryptedLogsPerBlock[blockNumber - INITIAL_L2_BLOCK_NUM] = noteEncryptedLogs;
209
- }
210
-
211
- if (encryptedLogs) {
212
- this.encryptedLogsPerBlock[blockNumber - INITIAL_L2_BLOCK_NUM] = encryptedLogs;
213
- }
204
+ addLogs(blocks: L2Block[]): Promise<boolean> {
205
+ blocks.forEach(block => {
206
+ this.noteEncryptedLogsPerBlock.set(block.number, block.body.noteEncryptedLogs);
207
+ this.encryptedLogsPerBlock.set(block.number, block.body.encryptedLogs);
208
+ this.unencryptedLogsPerBlock.set(block.number, block.body.unencryptedLogs);
209
+ });
210
+ return Promise.resolve(true);
211
+ }
214
212
 
215
- if (unencryptedLogs) {
216
- this.unencryptedLogsPerBlock[blockNumber - INITIAL_L2_BLOCK_NUM] = unencryptedLogs;
217
- }
213
+ deleteLogs(blocks: L2Block[]): Promise<boolean> {
214
+ blocks.forEach(block => {
215
+ this.encryptedLogsPerBlock.delete(block.number);
216
+ this.noteEncryptedLogsPerBlock.delete(block.number);
217
+ this.unencryptedLogsPerBlock.delete(block.number);
218
+ });
218
219
 
219
220
  return Promise.resolve(true);
220
221
  }
221
222
 
223
+ getTotalL1ToL2MessageCount(): Promise<bigint> {
224
+ return Promise.resolve(this.l1ToL2Messages.getTotalL1ToL2MessageCount());
225
+ }
226
+
222
227
  /**
223
228
  * Append L1 to L2 messages to the store.
224
229
  * @param messages - The L1 to L2 messages to be added to the store and the last processed L1 block.
@@ -257,12 +262,15 @@ export class MemoryArchiverStore implements ArchiverDataStore {
257
262
  * @remarks When "from" is smaller than genesis block number, blocks from the beginning are returned.
258
263
  */
259
264
  public getBlocks(from: number, limit: number): Promise<L1Published<L2Block>[]> {
260
- // Return an empty array if we are outside of range
261
265
  if (limit < 1) {
262
266
  return Promise.reject(new Error(`Invalid limit: ${limit}`));
263
267
  }
264
268
 
265
- const fromIndex = Math.max(from - INITIAL_L2_BLOCK_NUM, 0);
269
+ if (from < INITIAL_L2_BLOCK_NUM) {
270
+ return Promise.reject(new Error(`Invalid start: ${from}`));
271
+ }
272
+
273
+ const fromIndex = from - INITIAL_L2_BLOCK_NUM;
266
274
  if (fromIndex >= this.l2Blocks.length) {
267
275
  return Promise.resolve([]);
268
276
  }
@@ -271,6 +279,11 @@ export class MemoryArchiverStore implements ArchiverDataStore {
271
279
  return Promise.resolve(this.l2Blocks.slice(fromIndex, toIndex));
272
280
  }
273
281
 
282
+ public async getBlockHeaders(from: number, limit: number): Promise<Header[]> {
283
+ const blocks = await this.getBlocks(from, limit);
284
+ return blocks.map(block => block.data.header);
285
+ }
286
+
274
287
  /**
275
288
  * Gets a tx effect.
276
289
  * @param txHash - The txHash of the tx effect.
@@ -328,9 +341,14 @@ export class MemoryArchiverStore implements ArchiverDataStore {
328
341
  logType: TLogType,
329
342
  ): Promise<L2BlockL2Logs<FromLogType<TLogType>>[]> {
330
343
  if (from < INITIAL_L2_BLOCK_NUM || limit < 1) {
331
- throw new Error(`Invalid limit: ${limit}`);
344
+ return Promise.resolve([]);
332
345
  }
333
- const logs = (() => {
346
+
347
+ if (from > this.l2Blocks.length) {
348
+ return Promise.resolve([]);
349
+ }
350
+
351
+ const logMap = (() => {
334
352
  switch (logType) {
335
353
  case LogType.ENCRYPTED:
336
354
  return this.encryptedLogsPerBlock;
@@ -340,14 +358,24 @@ export class MemoryArchiverStore implements ArchiverDataStore {
340
358
  default:
341
359
  return this.unencryptedLogsPerBlock;
342
360
  }
343
- })() as L2BlockL2Logs<FromLogType<TLogType>>[];
361
+ })() as Map<number, L2BlockL2Logs<FromLogType<TLogType>>>;
344
362
 
345
- if (from > logs.length) {
346
- return Promise.resolve([]);
347
- }
348
- const startIndex = from - INITIAL_L2_BLOCK_NUM;
363
+ const startIndex = from;
349
364
  const endIndex = startIndex + limit;
350
- return Promise.resolve(logs.slice(startIndex, endIndex));
365
+ const upper = Math.min(endIndex, this.l2Blocks.length + INITIAL_L2_BLOCK_NUM);
366
+
367
+ const l = [];
368
+ for (let i = startIndex; i < upper; i++) {
369
+ const log = logMap.get(i);
370
+ if (log) {
371
+ l.push(log);
372
+ } else {
373
+ // I hate typescript sometimes
374
+ l.push(undefined as unknown as L2BlockL2Logs<FromLogType<TLogType>>);
375
+ }
376
+ }
377
+
378
+ return Promise.resolve(l);
351
379
  }
352
380
 
353
381
  /**
@@ -358,37 +386,37 @@ export class MemoryArchiverStore implements ArchiverDataStore {
358
386
  */
359
387
  getUnencryptedLogs(filter: LogFilter): Promise<GetUnencryptedLogsResponse> {
360
388
  let txHash: TxHash | undefined;
361
- let fromBlockIndex = 0;
362
- let toBlockIndex = this.unencryptedLogsPerBlock.length;
389
+ let fromBlock = 0;
390
+ let toBlock = this.l2Blocks.length + INITIAL_L2_BLOCK_NUM;
363
391
  let txIndexInBlock = 0;
364
392
  let logIndexInTx = 0;
365
393
 
366
394
  if (filter.afterLog) {
367
395
  // Continuation parameter is set --> tx hash is ignored
368
396
  if (filter.fromBlock == undefined || filter.fromBlock <= filter.afterLog.blockNumber) {
369
- fromBlockIndex = filter.afterLog.blockNumber - INITIAL_L2_BLOCK_NUM;
397
+ fromBlock = filter.afterLog.blockNumber;
370
398
  txIndexInBlock = filter.afterLog.txIndex;
371
399
  logIndexInTx = filter.afterLog.logIndex + 1; // We want to start from the next log
372
400
  } else {
373
- fromBlockIndex = filter.fromBlock - INITIAL_L2_BLOCK_NUM;
401
+ fromBlock = filter.fromBlock;
374
402
  }
375
403
  } else {
376
404
  txHash = filter.txHash;
377
405
 
378
406
  if (filter.fromBlock !== undefined) {
379
- fromBlockIndex = filter.fromBlock - INITIAL_L2_BLOCK_NUM;
407
+ fromBlock = filter.fromBlock;
380
408
  }
381
409
  }
382
410
 
383
411
  if (filter.toBlock !== undefined) {
384
- toBlockIndex = filter.toBlock - INITIAL_L2_BLOCK_NUM;
412
+ toBlock = filter.toBlock;
385
413
  }
386
414
 
387
415
  // Ensure the indices are within block array bounds
388
- fromBlockIndex = Math.max(fromBlockIndex, 0);
389
- toBlockIndex = Math.min(toBlockIndex, this.unencryptedLogsPerBlock.length);
416
+ fromBlock = Math.max(fromBlock, INITIAL_L2_BLOCK_NUM);
417
+ toBlock = Math.min(toBlock, this.l2Blocks.length + INITIAL_L2_BLOCK_NUM);
390
418
 
391
- if (fromBlockIndex > this.unencryptedLogsPerBlock.length || toBlockIndex < fromBlockIndex || toBlockIndex <= 0) {
419
+ if (fromBlock > this.l2Blocks.length || toBlock < fromBlock || toBlock <= 0) {
392
420
  return Promise.resolve({
393
421
  logs: [],
394
422
  maxLogsHit: false,
@@ -399,27 +427,30 @@ export class MemoryArchiverStore implements ArchiverDataStore {
399
427
 
400
428
  const logs: ExtendedUnencryptedL2Log[] = [];
401
429
 
402
- for (; fromBlockIndex < toBlockIndex; fromBlockIndex++) {
403
- const block = this.l2Blocks[fromBlockIndex];
404
- const blockLogs = this.unencryptedLogsPerBlock[fromBlockIndex];
405
- for (; txIndexInBlock < blockLogs.txLogs.length; txIndexInBlock++) {
406
- const txLogs = blockLogs.txLogs[txIndexInBlock].unrollLogs();
407
- for (; logIndexInTx < txLogs.length; logIndexInTx++) {
408
- const log = txLogs[logIndexInTx];
409
- if (
410
- (!txHash || block.data.body.txEffects[txIndexInBlock].txHash.equals(txHash)) &&
411
- (!contractAddress || log.contractAddress.equals(contractAddress))
412
- ) {
413
- logs.push(new ExtendedUnencryptedL2Log(new LogId(block.data.number, txIndexInBlock, logIndexInTx), log));
414
- if (logs.length === this.maxLogs) {
415
- return Promise.resolve({
416
- logs,
417
- maxLogsHit: true,
418
- });
430
+ for (; fromBlock < toBlock; fromBlock++) {
431
+ const block = this.l2Blocks[fromBlock - INITIAL_L2_BLOCK_NUM];
432
+ const blockLogs = this.unencryptedLogsPerBlock.get(fromBlock);
433
+
434
+ if (blockLogs) {
435
+ for (; txIndexInBlock < blockLogs.txLogs.length; txIndexInBlock++) {
436
+ const txLogs = blockLogs.txLogs[txIndexInBlock].unrollLogs();
437
+ for (; logIndexInTx < txLogs.length; logIndexInTx++) {
438
+ const log = txLogs[logIndexInTx];
439
+ if (
440
+ (!txHash || block.data.body.txEffects[txIndexInBlock].txHash.equals(txHash)) &&
441
+ (!contractAddress || log.contractAddress.equals(contractAddress))
442
+ ) {
443
+ logs.push(new ExtendedUnencryptedL2Log(new LogId(block.data.number, txIndexInBlock, logIndexInTx), log));
444
+ if (logs.length === this.maxLogs) {
445
+ return Promise.resolve({
446
+ logs,
447
+ maxLogsHit: true,
448
+ });
449
+ }
419
450
  }
420
451
  }
452
+ logIndexInTx = 0;
421
453
  }
422
- logIndexInTx = 0;
423
454
  }
424
455
  txIndexInBlock = 0;
425
456
  }
@@ -445,9 +476,27 @@ export class MemoryArchiverStore implements ArchiverDataStore {
445
476
  return Promise.resolve(this.lastProvenL2BlockNumber);
446
477
  }
447
478
 
448
- public setProvenL2BlockNumber(l2BlockNumber: SingletonDataRetrieval<number>): Promise<void> {
449
- this.lastProvenL2BlockNumber = l2BlockNumber.retrievedData;
450
- this.lastL1BlockNewProvenLogs = l2BlockNumber.lastProcessedL1BlockNumber;
479
+ public getProvenL2EpochNumber(): Promise<number | undefined> {
480
+ return Promise.resolve(this.lastProvenL2EpochNumber);
481
+ }
482
+
483
+ public setProvenL2BlockNumber(l2BlockNumber: number): Promise<void> {
484
+ this.lastProvenL2BlockNumber = l2BlockNumber;
485
+ return Promise.resolve();
486
+ }
487
+
488
+ public setProvenL2EpochNumber(l2EpochNumber: number): Promise<void> {
489
+ this.lastProvenL2EpochNumber = l2EpochNumber;
490
+ return Promise.resolve();
491
+ }
492
+
493
+ setBlockSynchedL1BlockNumber(l1BlockNumber: bigint) {
494
+ this.lastL1BlockNewBlocks = l1BlockNumber;
495
+ return Promise.resolve();
496
+ }
497
+
498
+ setMessageSynchedL1BlockNumber(l1BlockNumber: bigint) {
499
+ this.lastL1BlockNewMessages = l1BlockNumber;
451
500
  return Promise.resolve();
452
501
  }
453
502
 
@@ -455,8 +504,6 @@ export class MemoryArchiverStore implements ArchiverDataStore {
455
504
  return Promise.resolve({
456
505
  blocksSynchedTo: this.lastL1BlockNewBlocks,
457
506
  messagesSynchedTo: this.lastL1BlockNewMessages,
458
- blockBodiesSynchedTo: this.lastL1BlockNewBlockBodies,
459
- provenLogsSynchedTo: this.lastL1BlockNewProvenLogs,
460
507
  });
461
508
  }
462
509
 
package/src/index.ts CHANGED
@@ -15,8 +15,6 @@ export * from './factory.js';
15
15
 
16
16
  export { retrieveL2ProofVerifiedEvents, retrieveBlockFromRollup } from './archiver/data_retrieval.js';
17
17
 
18
- export { getL2BlockProposedLogs } from './archiver/eth_log_handlers.js';
19
-
20
18
  const log = createDebugLogger('aztec:archiver');
21
19
 
22
20
  /**
@@ -27,6 +25,7 @@ async function main() {
27
25
  const config = getArchiverConfigFromEnv();
28
26
  const { l1RpcUrl: rpcUrl, l1Contracts } = config;
29
27
 
28
+ log.info(`Starting archiver in main(): ${JSON.stringify(config)}`);
30
29
  const publicClient = createPublicClient({
31
30
  chain: localhost,
32
31
  transport: http(rpcUrl),
@@ -0,0 +1 @@
1
+ export * from './mock_l2_block_source.js';
@@ -0,0 +1,165 @@
1
+ import { L2Block, type L2BlockSource, type TxEffect, type TxHash, TxReceipt, TxStatus } from '@aztec/circuit-types';
2
+ import { EthAddress, type Header } from '@aztec/circuits.js';
3
+
4
+ import { getSlotRangeForEpoch } from '../archiver/epoch_helpers.js';
5
+
6
+ /**
7
+ * A mocked implementation of L2BlockSource to be used in p2p tests.
8
+ */
9
+ export class MockBlockSource implements L2BlockSource {
10
+ private l2Blocks: L2Block[] = [];
11
+ private txEffects: TxEffect[] = [];
12
+ private provenEpochNumber: number = 0;
13
+
14
+ constructor(numBlocks = 100, private provenBlockNumber?: number) {
15
+ this.addBlocks(numBlocks);
16
+ }
17
+
18
+ public addBlocks(numBlocks: number) {
19
+ for (let i = 0; i < numBlocks; i++) {
20
+ const blockNum = this.l2Blocks.length;
21
+ const block = L2Block.random(blockNum, blockNum);
22
+ this.l2Blocks.push(block);
23
+ this.txEffects.push(...block.body.txEffects);
24
+ }
25
+ }
26
+
27
+ public setProvenBlockNumber(provenBlockNumber: number) {
28
+ this.provenBlockNumber = provenBlockNumber;
29
+ }
30
+
31
+ public setProvenEpochNumber(provenEpochNumber: number) {
32
+ this.provenEpochNumber = provenEpochNumber;
33
+ }
34
+
35
+ /**
36
+ * Method to fetch the rollup contract address at the base-layer.
37
+ * @returns The rollup address.
38
+ */
39
+ getRollupAddress(): Promise<EthAddress> {
40
+ return Promise.resolve(EthAddress.random());
41
+ }
42
+
43
+ /**
44
+ * Method to fetch the registry contract address at the base-layer.
45
+ * @returns The registry address.
46
+ */
47
+ getRegistryAddress(): Promise<EthAddress> {
48
+ return Promise.resolve(EthAddress.random());
49
+ }
50
+
51
+ /**
52
+ * Gets the number of the latest L2 block processed by the block source implementation.
53
+ * @returns In this mock instance, returns the number of L2 blocks that we've mocked.
54
+ */
55
+ public getBlockNumber() {
56
+ return Promise.resolve(this.l2Blocks.length - 1);
57
+ }
58
+
59
+ public async getProvenBlockNumber(): Promise<number> {
60
+ return this.provenBlockNumber ?? (await this.getBlockNumber());
61
+ }
62
+
63
+ public getProvenL2EpochNumber(): Promise<number | undefined> {
64
+ return Promise.resolve(this.provenEpochNumber);
65
+ }
66
+
67
+ /**
68
+ * Gets an l2 block.
69
+ * @param number - The block number to return (inclusive).
70
+ * @returns The requested L2 block.
71
+ */
72
+ public getBlock(number: number) {
73
+ return Promise.resolve(this.l2Blocks[number]);
74
+ }
75
+
76
+ /**
77
+ * Gets up to `limit` amount of L2 blocks starting from `from`.
78
+ * @param from - Number of the first block to return (inclusive).
79
+ * @param limit - The maximum number of blocks to return.
80
+ * @returns The requested mocked L2 blocks.
81
+ */
82
+ public getBlocks(from: number, limit: number, proven?: boolean) {
83
+ return Promise.resolve(
84
+ this.l2Blocks
85
+ .slice(from, from + limit)
86
+ .filter(b => !proven || this.provenBlockNumber === undefined || b.number <= this.provenBlockNumber),
87
+ );
88
+ }
89
+
90
+ getBlockHeader(number: number | 'latest'): Promise<Header | undefined> {
91
+ return Promise.resolve(this.l2Blocks.at(typeof number === 'number' ? number : -1)?.header);
92
+ }
93
+
94
+ getBlocksForEpoch(epochNumber: bigint): Promise<L2Block[]> {
95
+ const [start, end] = getSlotRangeForEpoch(epochNumber);
96
+ const blocks = this.l2Blocks.filter(b => {
97
+ const slot = b.header.globalVariables.slotNumber.toBigInt();
98
+ return slot >= start && slot <= end;
99
+ });
100
+ return Promise.resolve(blocks);
101
+ }
102
+
103
+ /**
104
+ * Gets a tx effect.
105
+ * @param txHash - The hash of a transaction which resulted in the returned tx effect.
106
+ * @returns The requested tx effect.
107
+ */
108
+ public getTxEffect(txHash: TxHash) {
109
+ const txEffect = this.txEffects.find(tx => tx.txHash.equals(txHash));
110
+ return Promise.resolve(txEffect);
111
+ }
112
+
113
+ /**
114
+ * Gets a receipt of a settled tx.
115
+ * @param txHash - The hash of a tx we try to get the receipt for.
116
+ * @returns The requested tx receipt (or undefined if not found).
117
+ */
118
+ public getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
119
+ for (const block of this.l2Blocks) {
120
+ for (const txEffect of block.body.txEffects) {
121
+ if (txEffect.txHash.equals(txHash)) {
122
+ return Promise.resolve(
123
+ new TxReceipt(
124
+ txHash,
125
+ TxStatus.SUCCESS,
126
+ '',
127
+ txEffect.transactionFee.toBigInt(),
128
+ block.hash().toBuffer(),
129
+ block.number,
130
+ ),
131
+ );
132
+ }
133
+ }
134
+ }
135
+ return Promise.resolve(undefined);
136
+ }
137
+
138
+ getL2EpochNumber(): Promise<bigint> {
139
+ throw new Error('Method not implemented.');
140
+ }
141
+
142
+ getL2SlotNumber(): Promise<bigint> {
143
+ throw new Error('Method not implemented.');
144
+ }
145
+
146
+ isEpochComplete(_epochNumber: bigint): Promise<boolean> {
147
+ throw new Error('Method not implemented.');
148
+ }
149
+
150
+ /**
151
+ * Starts the block source. In this mock implementation, this is a noop.
152
+ * @returns A promise that signals the initialization of the l2 block source on completion.
153
+ */
154
+ public start(): Promise<void> {
155
+ return Promise.resolve();
156
+ }
157
+
158
+ /**
159
+ * Stops the block source. In this mock implementation, this is a noop.
160
+ * @returns A promise that signals the l2 block source is now stopped.
161
+ */
162
+ public stop(): Promise<void> {
163
+ return Promise.resolve();
164
+ }
165
+ }