@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,12 +1,12 @@
1
1
  import {
2
2
  INITIAL_L2_BLOCK_NUM,
3
3
  L1_TO_L2_MSG_SUBTREE_HEIGHT,
4
- MAX_NULLIFIERS_PER_TX,
5
4
  PRIVATE_LOG_SIZE_IN_FIELDS,
6
5
  PUBLIC_LOG_DATA_SIZE_IN_FIELDS,
7
6
  } from '@aztec/constants';
8
7
  import { times, timesParallel } from '@aztec/foundation/collection';
9
8
  import { randomInt } from '@aztec/foundation/crypto';
9
+ import { Signature } from '@aztec/foundation/eth-signature';
10
10
  import { Fr } from '@aztec/foundation/fields';
11
11
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
12
12
  import { L2Block, wrapInBlock } from '@aztec/stdlib/block';
@@ -27,7 +27,7 @@ import '@aztec/stdlib/testing/jest';
27
27
  import { TxEffect, TxHash } from '@aztec/stdlib/tx';
28
28
 
29
29
  import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.js';
30
- import type { L1Published } from './structs/published.js';
30
+ import type { PublishedL2Block } from './structs/published.js';
31
31
 
32
32
  /**
33
33
  * @param testName - The name of the test suite.
@@ -39,8 +39,9 @@ export function describeArchiverDataStore(
39
39
  ) {
40
40
  describe(testName, () => {
41
41
  let store: ArchiverDataStore;
42
- let blocks: L1Published<L2Block>[];
43
- const blockTests: [number, number, () => L1Published<L2Block>[]][] = [
42
+ let blocks: PublishedL2Block[];
43
+
44
+ const blockTests: [number, number, () => PublishedL2Block[]][] = [
44
45
  [1, 1, () => blocks.slice(0, 1)],
45
46
  [10, 1, () => blocks.slice(9, 10)],
46
47
  [1, 10, () => blocks.slice(0, 10)],
@@ -48,18 +49,30 @@ export function describeArchiverDataStore(
48
49
  [5, 2, () => blocks.slice(4, 6)],
49
50
  ];
50
51
 
51
- const makeL1Published = (block: L2Block, l1BlockNumber: number): L1Published<L2Block> => ({
52
- data: block,
52
+ const makePublished = (block: L2Block, l1BlockNumber: number): PublishedL2Block => ({
53
+ block: block,
53
54
  l1: {
54
55
  blockNumber: BigInt(l1BlockNumber),
55
56
  blockHash: `0x${l1BlockNumber}`,
56
57
  timestamp: BigInt(l1BlockNumber * 1000),
57
58
  },
59
+ signatures: times(3, Signature.random),
58
60
  });
59
61
 
62
+ const expectBlocksEqual = (actual: PublishedL2Block[], expected: PublishedL2Block[]) => {
63
+ expect(actual.length).toEqual(expected.length);
64
+ for (let i = 0; i < expected.length; i++) {
65
+ const expectedBlock = expected[i];
66
+ const actualBlock = actual[i];
67
+ expect(actualBlock.l1).toEqual(expectedBlock.l1);
68
+ expect(actualBlock.block.equals(expectedBlock.block)).toBe(true);
69
+ expect(actualBlock.signatures.every((s, i) => s.equals(expectedBlock.signatures[i]))).toBe(true);
70
+ }
71
+ };
72
+
60
73
  beforeEach(async () => {
61
74
  store = await getStore();
62
- blocks = await timesParallel(10, async i => makeL1Published(await L2Block.random(i + 1), i + 10));
75
+ blocks = await timesParallel(10, async i => makePublished(await L2Block.random(i + 1), i + 10));
63
76
  });
64
77
 
65
78
  describe('addBlocks', () => {
@@ -78,7 +91,7 @@ export function describeArchiverDataStore(
78
91
  await store.addBlocks(blocks);
79
92
  const blockNumber = await store.getSynchedL2BlockNumber();
80
93
 
81
- expect(await store.getBlocks(blockNumber, 1)).toEqual([blocks[blocks.length - 1]]);
94
+ expectBlocksEqual(await store.getBlocks(blockNumber, 1), [blocks[blocks.length - 1]]);
82
95
 
83
96
  await store.unwindBlocks(blockNumber, 1);
84
97
 
@@ -87,13 +100,13 @@ export function describeArchiverDataStore(
87
100
  });
88
101
 
89
102
  it('can unwind multiple empty blocks', async () => {
90
- const emptyBlocks = await timesParallel(10, async i => makeL1Published(await L2Block.random(i + 1, 0), i + 10));
103
+ const emptyBlocks = await timesParallel(10, async i => makePublished(await L2Block.random(i + 1, 0), i + 10));
91
104
  await store.addBlocks(emptyBlocks);
92
105
  expect(await store.getSynchedL2BlockNumber()).toBe(10);
93
106
 
94
107
  await store.unwindBlocks(10, 3);
95
108
  expect(await store.getSynchedL2BlockNumber()).toBe(7);
96
- expect((await store.getBlocks(1, 10)).map(b => b.data.number)).toEqual([1, 2, 3, 4, 5, 6, 7]);
109
+ expect((await store.getBlocks(1, 10)).map(b => b.block.number)).toEqual([1, 2, 3, 4, 5, 6, 7]);
97
110
  });
98
111
 
99
112
  it('refuses to unwind blocks if the tip is not the last block', async () => {
@@ -108,7 +121,7 @@ export function describeArchiverDataStore(
108
121
  });
109
122
 
110
123
  it.each(blockTests)('retrieves previously stored blocks', async (start, limit, getExpectedBlocks) => {
111
- await expect(store.getBlocks(start, limit)).resolves.toEqual(getExpectedBlocks());
124
+ expectBlocksEqual(await store.getBlocks(start, limit), getExpectedBlocks());
112
125
  });
113
126
 
114
127
  it('returns an empty array if no blocks are found', async () => {
@@ -131,7 +144,7 @@ export function describeArchiverDataStore(
131
144
 
132
145
  it("returns the most recently added block's number", async () => {
133
146
  await store.addBlocks(blocks);
134
- await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1)!.data.number);
147
+ await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1)!.block.number);
135
148
  });
136
149
  });
137
150
 
@@ -165,14 +178,14 @@ export function describeArchiverDataStore(
165
178
 
166
179
  describe('addLogs', () => {
167
180
  it('adds private & public logs', async () => {
168
- const block = blocks[0].data;
181
+ const block = blocks[0].block;
169
182
  await expect(store.addLogs([block])).resolves.toEqual(true);
170
183
  });
171
184
  });
172
185
 
173
186
  describe('deleteLogs', () => {
174
187
  it('deletes private & public logs', async () => {
175
- const block = blocks[0].data;
188
+ const block = blocks[0].block;
176
189
  await store.addBlocks([blocks[0]]);
177
190
  await expect(store.addLogs([block])).resolves.toEqual(true);
178
191
 
@@ -193,7 +206,7 @@ export function describeArchiverDataStore(
193
206
 
194
207
  describe('getPrivateLogs', () => {
195
208
  it('gets added private logs', async () => {
196
- const block = blocks[0].data;
209
+ const block = blocks[0].block;
197
210
  await store.addBlocks([blocks[0]]);
198
211
  await store.addLogs([block]);
199
212
 
@@ -204,16 +217,16 @@ export function describeArchiverDataStore(
204
217
 
205
218
  describe('getTxEffect', () => {
206
219
  beforeEach(async () => {
207
- await store.addLogs(blocks.map(b => b.data));
220
+ await store.addLogs(blocks.map(b => b.block));
208
221
  await store.addBlocks(blocks);
209
222
  });
210
223
 
211
224
  it.each([
212
- () => wrapInBlock(blocks[0].data.body.txEffects[0], blocks[0].data),
213
- () => wrapInBlock(blocks[9].data.body.txEffects[3], blocks[9].data),
214
- () => wrapInBlock(blocks[3].data.body.txEffects[1], blocks[3].data),
215
- () => wrapInBlock(blocks[5].data.body.txEffects[2], blocks[5].data),
216
- () => wrapInBlock(blocks[1].data.body.txEffects[0], blocks[1].data),
225
+ () => wrapInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
226
+ () => wrapInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
227
+ () => wrapInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
228
+ () => wrapInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
229
+ () => wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block),
217
230
  ])('retrieves a previously stored transaction', async getExpectedTx => {
218
231
  const expectedTx = await getExpectedTx();
219
232
  const actualTx = await store.getTxEffect(expectedTx.data.txHash);
@@ -225,11 +238,11 @@ export function describeArchiverDataStore(
225
238
  });
226
239
 
227
240
  it.each([
228
- () => wrapInBlock(blocks[0].data.body.txEffects[0], blocks[0].data),
229
- () => wrapInBlock(blocks[9].data.body.txEffects[3], blocks[9].data),
230
- () => wrapInBlock(blocks[3].data.body.txEffects[1], blocks[3].data),
231
- () => wrapInBlock(blocks[5].data.body.txEffects[2], blocks[5].data),
232
- () => wrapInBlock(blocks[1].data.body.txEffects[0], blocks[1].data),
241
+ () => wrapInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
242
+ () => wrapInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
243
+ () => wrapInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
244
+ () => wrapInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
245
+ () => wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block),
233
246
  ])('tries to retrieves a previously stored transaction after deleted', async getExpectedTx => {
234
247
  await store.unwindBlocks(blocks.length, blocks.length);
235
248
 
@@ -292,16 +305,65 @@ export function describeArchiverDataStore(
292
305
  });
293
306
 
294
307
  it('returns previously stored contract instances', async () => {
295
- await expect(store.getContractInstance(contractInstance.address)).resolves.toMatchObject(contractInstance);
308
+ await expect(store.getContractInstance(contractInstance.address, blockNum)).resolves.toMatchObject(
309
+ contractInstance,
310
+ );
296
311
  });
297
312
 
298
313
  it('returns undefined if contract instance is not found', async () => {
299
- await expect(store.getContractInstance(await AztecAddress.random())).resolves.toBeUndefined();
314
+ await expect(store.getContractInstance(await AztecAddress.random(), blockNum)).resolves.toBeUndefined();
300
315
  });
301
316
 
302
317
  it('returns undefined if previously stored contract instances was deleted', async () => {
303
318
  await store.deleteContractInstances([contractInstance], blockNum);
304
- await expect(store.getContractInstance(contractInstance.address)).resolves.toBeUndefined();
319
+ await expect(store.getContractInstance(contractInstance.address, blockNum)).resolves.toBeUndefined();
320
+ });
321
+ });
322
+
323
+ describe('contractInstanceUpdates', () => {
324
+ let contractInstance: ContractInstanceWithAddress;
325
+ let classId: Fr;
326
+ let nextClassId: Fr;
327
+ const blockOfChange = 10;
328
+
329
+ beforeEach(async () => {
330
+ classId = Fr.random();
331
+ nextClassId = Fr.random();
332
+ const randomInstance = await SerializableContractInstance.random({
333
+ currentContractClassId: classId,
334
+ originalContractClassId: classId,
335
+ });
336
+ contractInstance = { ...randomInstance, address: await AztecAddress.random() };
337
+ await store.addContractInstances([contractInstance], 1);
338
+ await store.addContractInstanceUpdates(
339
+ [
340
+ {
341
+ prevContractClassId: classId,
342
+ newContractClassId: nextClassId,
343
+ blockOfChange,
344
+ address: contractInstance.address,
345
+ },
346
+ ],
347
+ blockOfChange - 1,
348
+ );
349
+ });
350
+
351
+ it('gets the correct current class id for a contract not updated yet', async () => {
352
+ const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange - 1);
353
+ expect(fetchedInstance?.originalContractClassId).toEqual(classId);
354
+ expect(fetchedInstance?.currentContractClassId).toEqual(classId);
355
+ });
356
+
357
+ it('gets the correct current class id for a contract that has just been updated', async () => {
358
+ const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange);
359
+ expect(fetchedInstance?.originalContractClassId).toEqual(classId);
360
+ expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
361
+ });
362
+
363
+ it('gets the correct current class id for a contract that was updated in the past', async () => {
364
+ const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange + 1);
365
+ expect(fetchedInstance?.originalContractClassId).toEqual(classId);
366
+ expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
305
367
  });
306
368
  });
307
369
 
@@ -378,31 +440,19 @@ export function describeArchiverDataStore(
378
440
  const numPrivateLogsPerTx = 3;
379
441
  const numPublicLogsPerTx = 2;
380
442
 
381
- let blocks: L1Published<L2Block>[];
443
+ let blocks: PublishedL2Block[];
382
444
 
383
445
  const makeTag = (blockNumber: number, txIndex: number, logIndex: number, isPublic = false) =>
384
446
  new Fr((blockNumber * 100 + txIndex * 10 + logIndex) * (isPublic ? 123 : 1));
385
447
 
386
- // See parseLogFromPublic
387
- // 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.
388
- const makeLengthsField = (publicValuesLen: number, privateValuesLen: number) => {
389
- const buf = Buffer.alloc(32);
390
- buf.writeUint16BE(publicValuesLen, 27);
391
- buf.writeUint16BE(privateValuesLen, 30);
392
- return Fr.fromBuffer(buf);
393
- };
394
-
395
448
  const makePrivateLog = (tag: Fr) =>
396
449
  PrivateLog.fromFields([tag, ...times(PRIVATE_LOG_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i))]);
397
450
 
398
- // The tag lives in field 1, not 0, of a public log
399
- // See extractTaggedLogsFromPublic and noir-projects/aztec-nr/aztec/src/macros/notes/mod.nr -> emit_log
400
451
  const makePublicLog = (tag: Fr) =>
401
452
  PublicLog.fromFields([
402
453
  AztecAddress.fromNumber(1).toField(), // log address
403
- makeLengthsField(2, PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 3), // field 0
404
- tag, // field 1
405
- ...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)), // fields 2 to end
454
+ tag, // field 0
455
+ ...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)), // fields 1 to end
406
456
  ]);
407
457
 
408
458
  const mockPrivateLogs = (blockNumber: number, txIndex: number) => {
@@ -419,7 +469,7 @@ export function describeArchiverDataStore(
419
469
  });
420
470
  };
421
471
 
422
- const mockBlockWithLogs = async (blockNumber: number): Promise<L1Published<L2Block>> => {
472
+ const mockBlockWithLogs = async (blockNumber: number): Promise<PublishedL2Block> => {
423
473
  const block = await L2Block.random(blockNumber);
424
474
  block.header.globalVariables.blockNumber = new Fr(blockNumber);
425
475
 
@@ -431,7 +481,8 @@ export function describeArchiverDataStore(
431
481
  });
432
482
 
433
483
  return {
434
- data: block,
484
+ block: block,
485
+ signatures: times(3, Signature.random),
435
486
  l1: { blockNumber: BigInt(blockNumber), blockHash: `0x${blockNumber}`, timestamp: BigInt(blockNumber) },
436
487
  };
437
488
  };
@@ -440,7 +491,7 @@ export function describeArchiverDataStore(
440
491
  blocks = await timesParallel(numBlocks, (index: number) => mockBlockWithLogs(index));
441
492
 
442
493
  await store.addBlocks(blocks);
443
- await store.addLogs(blocks.map(b => b.data));
494
+ await store.addLogs(blocks.map(b => b.block));
444
495
  });
445
496
 
446
497
  it('is possible to batch request private logs via tags', async () => {
@@ -452,14 +503,14 @@ export function describeArchiverDataStore(
452
503
  [
453
504
  expect.objectContaining({
454
505
  blockNumber: 1,
455
- logData: makePrivateLog(tags[0]).toBuffer(),
506
+ log: makePrivateLog(tags[0]),
456
507
  isFromPublic: false,
457
508
  }),
458
509
  ],
459
510
  [
460
511
  expect.objectContaining({
461
512
  blockNumber: 0,
462
- logData: makePrivateLog(tags[1]).toBuffer(),
513
+ log: makePrivateLog(tags[1]),
463
514
  isFromPublic: false,
464
515
  }),
465
516
  ],
@@ -476,12 +527,12 @@ export function describeArchiverDataStore(
476
527
  [
477
528
  expect.objectContaining({
478
529
  blockNumber: 0,
479
- logData: makePrivateLog(tags[0]).toBuffer(),
530
+ log: makePrivateLog(tags[0]),
480
531
  isFromPublic: false,
481
532
  }),
482
533
  expect.objectContaining({
483
534
  blockNumber: 0,
484
- logData: makePublicLog(tags[0]).toBuffer(),
535
+ log: makePublicLog(tags[0]),
485
536
  isFromPublic: true,
486
537
  }),
487
538
  ],
@@ -494,11 +545,11 @@ export function describeArchiverDataStore(
494
545
  // Create a block containing logs that have the same tag as the blocks before.
495
546
  const newBlockNumber = numBlocks;
496
547
  const newBlock = await mockBlockWithLogs(newBlockNumber);
497
- const newLog = newBlock.data.body.txEffects[1].privateLogs[1];
548
+ const newLog = newBlock.block.body.txEffects[1].privateLogs[1];
498
549
  newLog.fields[0] = tags[0];
499
- newBlock.data.body.txEffects[1].privateLogs[1] = newLog;
550
+ newBlock.block.body.txEffects[1].privateLogs[1] = newLog;
500
551
  await store.addBlocks([newBlock]);
501
- await store.addLogs([newBlock.data]);
552
+ await store.addLogs([newBlock.block]);
502
553
 
503
554
  const logsByTags = await store.getLogsByTags(tags);
504
555
 
@@ -506,12 +557,12 @@ export function describeArchiverDataStore(
506
557
  [
507
558
  expect.objectContaining({
508
559
  blockNumber: 1,
509
- logData: makePrivateLog(tags[0]).toBuffer(),
560
+ log: makePrivateLog(tags[0]),
510
561
  isFromPublic: false,
511
562
  }),
512
563
  expect.objectContaining({
513
564
  blockNumber: newBlockNumber,
514
- logData: newLog.toBuffer(),
565
+ log: newLog,
515
566
  isFromPublic: false,
516
567
  }),
517
568
  ],
@@ -530,42 +581,12 @@ export function describeArchiverDataStore(
530
581
  [
531
582
  expect.objectContaining({
532
583
  blockNumber: 1,
533
- logData: makePrivateLog(tags[1]).toBuffer(),
584
+ log: makePrivateLog(tags[1]),
534
585
  isFromPublic: false,
535
586
  }),
536
587
  ],
537
588
  ]);
538
589
  });
539
-
540
- it('is not possible to add public logs by tag if they are invalid', async () => {
541
- const tag = makeTag(99, 88, 77);
542
- const invalidLogs = [
543
- PublicLog.fromFields([
544
- AztecAddress.fromNumber(1).toField(),
545
- makeLengthsField(2, 3), // This field claims we have 5 items, but we actually have more
546
- tag,
547
- ...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)),
548
- ]),
549
- PublicLog.fromFields([
550
- AztecAddress.fromNumber(1).toField(),
551
- makeLengthsField(2, PUBLIC_LOG_DATA_SIZE_IN_FIELDS), // This field claims we have more than the max items
552
- tag,
553
- ...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)),
554
- ]),
555
- ];
556
-
557
- // Create a block containing these invalid logs
558
- const newBlockNumber = numBlocks;
559
- const newBlock = await mockBlockWithLogs(newBlockNumber);
560
- newBlock.data.body.txEffects[0].publicLogs = invalidLogs;
561
- await store.addBlocks([newBlock]);
562
- await store.addLogs([newBlock.data]);
563
-
564
- const logsByTags = await store.getLogsByTags([tag]);
565
-
566
- // Neither of the logs should have been added:
567
- expect(logsByTags).toEqual([[]]);
568
- });
569
590
  });
570
591
 
571
592
  describe('getPublicLogs', () => {
@@ -573,27 +594,28 @@ export function describeArchiverDataStore(
573
594
  const numPublicFunctionCalls = 3;
574
595
  const numPublicLogs = 2;
575
596
  const numBlocks = 10;
576
- let blocks: L1Published<L2Block>[];
597
+ let blocks: PublishedL2Block[];
577
598
 
578
599
  beforeEach(async () => {
579
600
  blocks = await timesParallel(numBlocks, async (index: number) => ({
580
- data: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs),
601
+ block: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs),
581
602
  l1: { blockNumber: BigInt(index), blockHash: `0x${index}`, timestamp: BigInt(index) },
603
+ signatures: times(3, Signature.random),
582
604
  }));
583
605
 
584
606
  await store.addBlocks(blocks);
585
- await store.addLogs(blocks.map(b => b.data));
607
+ await store.addLogs(blocks.map(b => b.block));
586
608
  });
587
609
 
588
610
  it('no logs returned if deleted ("txHash" filter param is respected variant)', async () => {
589
611
  // get random tx
590
612
  const targetBlockIndex = randomInt(numBlocks);
591
613
  const targetTxIndex = randomInt(txsPerBlock);
592
- const targetTxHash = blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash;
614
+ const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
593
615
 
594
616
  await Promise.all([
595
617
  store.unwindBlocks(blocks.length, blocks.length),
596
- store.deleteLogs(blocks.map(b => b.data)),
618
+ store.deleteLogs(blocks.map(b => b.block)),
597
619
  ]);
598
620
 
599
621
  const response = await store.getPublicLogs({ txHash: targetTxHash });
@@ -607,7 +629,7 @@ export function describeArchiverDataStore(
607
629
  // get random tx
608
630
  const targetBlockIndex = randomInt(numBlocks);
609
631
  const targetTxIndex = randomInt(txsPerBlock);
610
- const targetTxHash = blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash;
632
+ const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
611
633
 
612
634
  const response = await store.getPublicLogs({ txHash: targetTxHash });
613
635
  const logs = response.logs;
@@ -650,7 +672,7 @@ export function describeArchiverDataStore(
650
672
  const targetTxIndex = randomInt(txsPerBlock);
651
673
  const targetLogIndex = randomInt(numPublicLogs * numPublicFunctionCalls);
652
674
  const targetContractAddress =
653
- blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].publicLogs[targetLogIndex].contractAddress;
675
+ blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].publicLogs[targetLogIndex].contractAddress;
654
676
 
655
677
  const response = await store.getPublicLogs({ contractAddress: targetContractAddress });
656
678
 
@@ -753,58 +775,5 @@ export function describeArchiverDataStore(
753
775
  }
754
776
  });
755
777
  });
756
-
757
- describe('findNullifiersIndexesWithBlock', () => {
758
- let blocks: L2Block[];
759
- const numBlocks = 10;
760
- const nullifiersPerBlock = new Map<number, Fr[]>();
761
-
762
- beforeEach(async () => {
763
- blocks = await timesParallel(numBlocks, (index: number) => L2Block.random(index + 1, 1));
764
-
765
- blocks.forEach((block, blockIndex) => {
766
- nullifiersPerBlock.set(
767
- blockIndex,
768
- block.body.txEffects.flatMap(txEffect => txEffect.nullifiers),
769
- );
770
- });
771
- });
772
-
773
- it('returns wrapped nullifiers with blocks if they exist', async () => {
774
- await store.addNullifiers(blocks);
775
- const nullifiersToRetrieve = [...nullifiersPerBlock.get(0)!, ...nullifiersPerBlock.get(5)!, Fr.random()];
776
- const blockScopedNullifiers = await store.findNullifiersIndexesWithBlock(10, nullifiersToRetrieve);
777
-
778
- expect(blockScopedNullifiers).toHaveLength(nullifiersToRetrieve.length);
779
- const [undefinedNullifier] = blockScopedNullifiers.slice(-1);
780
- const realNullifiers = blockScopedNullifiers.slice(0, -1);
781
- realNullifiers.forEach((blockScopedNullifier, index) => {
782
- expect(blockScopedNullifier).not.toBeUndefined();
783
- const { data, l2BlockNumber } = blockScopedNullifier!;
784
- expect(data).toEqual(expect.any(BigInt));
785
- expect(l2BlockNumber).toEqual(index < MAX_NULLIFIERS_PER_TX ? 1 : 6);
786
- });
787
- expect(undefinedNullifier).toBeUndefined();
788
- });
789
-
790
- it('returns wrapped nullifiers filtering by blockNumber', async () => {
791
- await store.addNullifiers(blocks);
792
- const nullifiersToRetrieve = [...nullifiersPerBlock.get(0)!, ...nullifiersPerBlock.get(5)!];
793
- const blockScopedNullifiers = await store.findNullifiersIndexesWithBlock(5, nullifiersToRetrieve);
794
-
795
- expect(blockScopedNullifiers).toHaveLength(nullifiersToRetrieve.length);
796
- const undefinedNullifiers = blockScopedNullifiers.slice(-MAX_NULLIFIERS_PER_TX);
797
- const realNullifiers = blockScopedNullifiers.slice(0, -MAX_NULLIFIERS_PER_TX);
798
- realNullifiers.forEach(blockScopedNullifier => {
799
- expect(blockScopedNullifier).not.toBeUndefined();
800
- const { data, l2BlockNumber } = blockScopedNullifier!;
801
- expect(data).toEqual(expect.any(BigInt));
802
- expect(l2BlockNumber).toEqual(1);
803
- });
804
- undefinedNullifiers.forEach(undefinedNullifier => {
805
- expect(undefinedNullifier).toBeUndefined();
806
- });
807
- });
808
- });
809
778
  });
810
779
  }
@@ -40,6 +40,9 @@ export type ArchiverConfig = {
40
40
 
41
41
  /** The max number of logs that can be obtained in 1 "getPublicLogs" call. */
42
42
  maxLogs?: number;
43
+
44
+ /** The maximum possible size of the archiver DB in KB. Overwrites the general dataStoreMapSizeKB. */
45
+ archiverStoreMapSizeKb?: number;
43
46
  } & L1ReaderConfig &
44
47
  L1ContractsConfig &
45
48
  BlobSinkConfig &
@@ -72,6 +75,11 @@ export const archiverConfigMappings: ConfigMappingsType<ArchiverConfig> = {
72
75
  description: 'The max number of logs that can be obtained in 1 "getPublicLogs" call.',
73
76
  ...numberConfigHelper(1_000),
74
77
  },
78
+ archiverStoreMapSizeKb: {
79
+ env: 'ARCHIVER_STORE_MAP_SIZE_KB',
80
+ parseEnv: (val: string | undefined) => (val ? +val : undefined),
81
+ description: 'The maximum possible size of the archiver DB in KB. Overwrites the general dataStoreMapSizeKB.',
82
+ },
75
83
  ...chainConfigMappings,
76
84
  ...l1ReaderConfigMappings,
77
85
  viemPollingIntervalMS: {
@@ -3,7 +3,7 @@ import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
3
3
  import type { EpochProofPublicInputArgs, ViemPublicClient } from '@aztec/ethereum';
4
4
  import { asyncPool } from '@aztec/foundation/async-pool';
5
5
  import type { EthAddress } from '@aztec/foundation/eth-address';
6
- import type { ViemSignature } from '@aztec/foundation/eth-signature';
6
+ import { Signature, type ViemSignature } from '@aztec/foundation/eth-signature';
7
7
  import { Fr } from '@aztec/foundation/fields';
8
8
  import { type Logger, createLogger } from '@aztec/foundation/log';
9
9
  import { numToUInt32BE } from '@aztec/foundation/serialize';
@@ -25,7 +25,7 @@ import {
25
25
 
26
26
  import { NoBlobBodiesFoundError } from './errors.js';
27
27
  import type { DataRetrieval } from './structs/data_retrieval.js';
28
- import type { L1Published, L1PublishedData } from './structs/published.js';
28
+ import type { L1PublishedData, PublishedL2Block } from './structs/published.js';
29
29
 
30
30
  /**
31
31
  * Fetches new L2 blocks.
@@ -43,8 +43,8 @@ export async function retrieveBlocksFromRollup(
43
43
  searchStartBlock: bigint,
44
44
  searchEndBlock: bigint,
45
45
  logger: Logger = createLogger('archiver'),
46
- ): Promise<L1Published<L2Block>[]> {
47
- const retrievedBlocks: L1Published<L2Block>[] = [];
46
+ ): Promise<PublishedL2Block[]> {
47
+ const retrievedBlocks: PublishedL2Block[] = [];
48
48
  do {
49
49
  if (searchStartBlock > searchEndBlock) {
50
50
  break;
@@ -96,8 +96,8 @@ export async function processL2BlockProposedLogs(
96
96
  blobSinkClient: BlobSinkClientInterface,
97
97
  logs: GetContractEventsReturnType<typeof RollupAbi, 'L2BlockProposed'>,
98
98
  logger: Logger,
99
- ): Promise<L1Published<L2Block>[]> {
100
- const retrievedBlocks: L1Published<L2Block>[] = [];
99
+ ): Promise<PublishedL2Block[]> {
100
+ const retrievedBlocks: PublishedL2Block[] = [];
101
101
  await asyncPool(10, logs, async log => {
102
102
  const l2BlockNumber = log.args.blockNumber!;
103
103
  const archive = log.args.archive!;
@@ -122,7 +122,7 @@ export async function processL2BlockProposedLogs(
122
122
  timestamp: await getL1BlockTime(publicClient, log.blockNumber),
123
123
  };
124
124
 
125
- retrievedBlocks.push({ data: block, l1 });
125
+ retrievedBlocks.push({ ...block, l1 });
126
126
  } else {
127
127
  logger.warn(`Ignoring L2 block ${l2BlockNumber} due to archive root mismatch`, {
128
128
  actual: archive,
@@ -203,11 +203,11 @@ async function getBlockFromRollupTx(
203
203
  publicClient: ViemPublicClient,
204
204
  blobSinkClient: BlobSinkClientInterface,
205
205
  txHash: `0x${string}`,
206
- blobHashes: Buffer[], // WORKTODO(md): buffer32?
206
+ blobHashes: Buffer[], // TODO(md): buffer32?
207
207
  l2BlockNum: bigint,
208
208
  rollupAddress: Hex,
209
209
  logger: Logger,
210
- ): Promise<L2Block> {
210
+ ): Promise<Omit<PublishedL2Block, 'l1'>> {
211
211
  const { input: forwarderData, blockHash } = await publicClient.getTransaction({ hash: txHash });
212
212
 
213
213
  const rollupData = extractRollupProposeCalldata(forwarderData, rollupAddress);
@@ -220,7 +220,7 @@ async function getBlockFromRollupTx(
220
220
  throw new Error(`Unexpected rollup method called ${rollupFunctionName}`);
221
221
  }
222
222
 
223
- const [decodedArgs, ,] = rollupArgs! as readonly [
223
+ const [decodedArgs, signatures] = rollupArgs! as readonly [
224
224
  {
225
225
  header: Hex;
226
226
  archive: Hex;
@@ -268,7 +268,8 @@ async function getBlockFromRollupTx(
268
268
  ]),
269
269
  );
270
270
 
271
- return new L2Block(archive, header, blockBody);
271
+ const block = new L2Block(archive, header, blockBody);
272
+ return { block, signatures: signatures.map(Signature.fromViemSignature) };
272
273
  }
273
274
 
274
275
  /**
@@ -1,7 +1,6 @@
1
1
  export * from './archiver.js';
2
2
  export * from './config.js';
3
- export { type L1Published, type L1PublishedData } from './structs/published.js';
4
- export { MemoryArchiverStore } from './memory_archiver_store/memory_archiver_store.js';
3
+ export { type PublishedL2Block, type L1PublishedData } from './structs/published.js';
5
4
  export type { ArchiverDataStore } from './archiver_store.js';
6
5
  export { KVArchiverDataStore } from './kv_archiver_store/kv_archiver_store.js';
7
6
  export { ContractInstanceStore } from './kv_archiver_store/contract_instance_store.js';