@aztec/archiver 0.80.0 → 0.81.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 (41) hide show
  1. package/dest/archiver/archiver.d.ts +5 -9
  2. package/dest/archiver/archiver.d.ts.map +1 -1
  3. package/dest/archiver/archiver.js +36 -49
  4. package/dest/archiver/archiver_store.d.ts +5 -4
  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 +104 -91
  8. package/dest/archiver/data_retrieval.d.ts +3 -4
  9. package/dest/archiver/data_retrieval.d.ts.map +1 -1
  10. package/dest/archiver/data_retrieval.js +8 -3
  11. package/dest/archiver/index.d.ts +1 -1
  12. package/dest/archiver/index.d.ts.map +1 -1
  13. package/dest/archiver/kv_archiver_store/block_store.d.ts +6 -6
  14. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  15. package/dest/archiver/kv_archiver_store/block_store.js +24 -21
  16. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +4 -4
  17. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  18. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +2 -3
  19. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  20. package/dest/archiver/kv_archiver_store/log_store.js +9 -41
  21. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +4 -4
  22. package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
  23. package/dest/archiver/memory_archiver_store/memory_archiver_store.js +25 -54
  24. package/dest/archiver/structs/published.d.ts +1 -10
  25. package/dest/archiver/structs/published.d.ts.map +1 -1
  26. package/dest/archiver/structs/published.js +1 -1
  27. package/dest/test/mock_l2_block_source.d.ts +9 -0
  28. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  29. package/dest/test/mock_l2_block_source.js +13 -0
  30. package/package.json +13 -13
  31. package/src/archiver/archiver.ts +44 -60
  32. package/src/archiver/archiver_store.ts +5 -4
  33. package/src/archiver/archiver_store_test_suite.ts +116 -93
  34. package/src/archiver/data_retrieval.ts +11 -10
  35. package/src/archiver/index.ts +1 -1
  36. package/src/archiver/kv_archiver_store/block_store.ts +28 -27
  37. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +5 -6
  38. package/src/archiver/kv_archiver_store/log_store.ts +11 -59
  39. package/src/archiver/memory_archiver_store/memory_archiver_store.ts +35 -66
  40. package/src/archiver/structs/published.ts +1 -11
  41. package/src/test/mock_l2_block_source.ts +14 -0
@@ -7,6 +7,7 @@ import {
7
7
  } from '@aztec/constants';
8
8
  import { times, timesParallel } from '@aztec/foundation/collection';
9
9
  import { randomInt } from '@aztec/foundation/crypto';
10
+ import { Signature } from '@aztec/foundation/eth-signature';
10
11
  import { Fr } from '@aztec/foundation/fields';
11
12
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
12
13
  import { L2Block, wrapInBlock } from '@aztec/stdlib/block';
@@ -27,7 +28,7 @@ import '@aztec/stdlib/testing/jest';
27
28
  import { TxEffect, TxHash } from '@aztec/stdlib/tx';
28
29
 
29
30
  import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.js';
30
- import type { L1Published } from './structs/published.js';
31
+ import type { PublishedL2Block } from './structs/published.js';
31
32
 
32
33
  /**
33
34
  * @param testName - The name of the test suite.
@@ -39,8 +40,9 @@ export function describeArchiverDataStore(
39
40
  ) {
40
41
  describe(testName, () => {
41
42
  let store: ArchiverDataStore;
42
- let blocks: L1Published<L2Block>[];
43
- const blockTests: [number, number, () => L1Published<L2Block>[]][] = [
43
+ let blocks: PublishedL2Block[];
44
+
45
+ const blockTests: [number, number, () => PublishedL2Block[]][] = [
44
46
  [1, 1, () => blocks.slice(0, 1)],
45
47
  [10, 1, () => blocks.slice(9, 10)],
46
48
  [1, 10, () => blocks.slice(0, 10)],
@@ -48,18 +50,30 @@ export function describeArchiverDataStore(
48
50
  [5, 2, () => blocks.slice(4, 6)],
49
51
  ];
50
52
 
51
- const makeL1Published = (block: L2Block, l1BlockNumber: number): L1Published<L2Block> => ({
52
- data: block,
53
+ const makePublished = (block: L2Block, l1BlockNumber: number): PublishedL2Block => ({
54
+ block: block,
53
55
  l1: {
54
56
  blockNumber: BigInt(l1BlockNumber),
55
57
  blockHash: `0x${l1BlockNumber}`,
56
58
  timestamp: BigInt(l1BlockNumber * 1000),
57
59
  },
60
+ signatures: times(3, Signature.random),
58
61
  });
59
62
 
63
+ const expectBlocksEqual = (actual: PublishedL2Block[], expected: PublishedL2Block[]) => {
64
+ expect(actual.length).toEqual(expected.length);
65
+ for (let i = 0; i < expected.length; i++) {
66
+ const expectedBlock = expected[i];
67
+ const actualBlock = actual[i];
68
+ expect(actualBlock.l1).toEqual(expectedBlock.l1);
69
+ expect(actualBlock.block.equals(expectedBlock.block)).toBe(true);
70
+ expect(actualBlock.signatures.every((s, i) => s.equals(expectedBlock.signatures[i]))).toBe(true);
71
+ }
72
+ };
73
+
60
74
  beforeEach(async () => {
61
75
  store = await getStore();
62
- blocks = await timesParallel(10, async i => makeL1Published(await L2Block.random(i + 1), i + 10));
76
+ blocks = await timesParallel(10, async i => makePublished(await L2Block.random(i + 1), i + 10));
63
77
  });
64
78
 
65
79
  describe('addBlocks', () => {
@@ -78,7 +92,7 @@ export function describeArchiverDataStore(
78
92
  await store.addBlocks(blocks);
79
93
  const blockNumber = await store.getSynchedL2BlockNumber();
80
94
 
81
- expect(await store.getBlocks(blockNumber, 1)).toEqual([blocks[blocks.length - 1]]);
95
+ expectBlocksEqual(await store.getBlocks(blockNumber, 1), [blocks[blocks.length - 1]]);
82
96
 
83
97
  await store.unwindBlocks(blockNumber, 1);
84
98
 
@@ -87,13 +101,13 @@ export function describeArchiverDataStore(
87
101
  });
88
102
 
89
103
  it('can unwind multiple empty blocks', async () => {
90
- const emptyBlocks = await timesParallel(10, async i => makeL1Published(await L2Block.random(i + 1, 0), i + 10));
104
+ const emptyBlocks = await timesParallel(10, async i => makePublished(await L2Block.random(i + 1, 0), i + 10));
91
105
  await store.addBlocks(emptyBlocks);
92
106
  expect(await store.getSynchedL2BlockNumber()).toBe(10);
93
107
 
94
108
  await store.unwindBlocks(10, 3);
95
109
  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]);
110
+ expect((await store.getBlocks(1, 10)).map(b => b.block.number)).toEqual([1, 2, 3, 4, 5, 6, 7]);
97
111
  });
98
112
 
99
113
  it('refuses to unwind blocks if the tip is not the last block', async () => {
@@ -108,7 +122,7 @@ export function describeArchiverDataStore(
108
122
  });
109
123
 
110
124
  it.each(blockTests)('retrieves previously stored blocks', async (start, limit, getExpectedBlocks) => {
111
- await expect(store.getBlocks(start, limit)).resolves.toEqual(getExpectedBlocks());
125
+ expectBlocksEqual(await store.getBlocks(start, limit), getExpectedBlocks());
112
126
  });
113
127
 
114
128
  it('returns an empty array if no blocks are found', async () => {
@@ -131,7 +145,7 @@ export function describeArchiverDataStore(
131
145
 
132
146
  it("returns the most recently added block's number", async () => {
133
147
  await store.addBlocks(blocks);
134
- await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1)!.data.number);
148
+ await expect(store.getSynchedL2BlockNumber()).resolves.toEqual(blocks.at(-1)!.block.number);
135
149
  });
136
150
  });
137
151
 
@@ -165,14 +179,14 @@ export function describeArchiverDataStore(
165
179
 
166
180
  describe('addLogs', () => {
167
181
  it('adds private & public logs', async () => {
168
- const block = blocks[0].data;
182
+ const block = blocks[0].block;
169
183
  await expect(store.addLogs([block])).resolves.toEqual(true);
170
184
  });
171
185
  });
172
186
 
173
187
  describe('deleteLogs', () => {
174
188
  it('deletes private & public logs', async () => {
175
- const block = blocks[0].data;
189
+ const block = blocks[0].block;
176
190
  await store.addBlocks([blocks[0]]);
177
191
  await expect(store.addLogs([block])).resolves.toEqual(true);
178
192
 
@@ -193,7 +207,7 @@ export function describeArchiverDataStore(
193
207
 
194
208
  describe('getPrivateLogs', () => {
195
209
  it('gets added private logs', async () => {
196
- const block = blocks[0].data;
210
+ const block = blocks[0].block;
197
211
  await store.addBlocks([blocks[0]]);
198
212
  await store.addLogs([block]);
199
213
 
@@ -204,16 +218,16 @@ export function describeArchiverDataStore(
204
218
 
205
219
  describe('getTxEffect', () => {
206
220
  beforeEach(async () => {
207
- await store.addLogs(blocks.map(b => b.data));
221
+ await store.addLogs(blocks.map(b => b.block));
208
222
  await store.addBlocks(blocks);
209
223
  });
210
224
 
211
225
  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),
226
+ () => wrapInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
227
+ () => wrapInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
228
+ () => wrapInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
229
+ () => wrapInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
230
+ () => wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block),
217
231
  ])('retrieves a previously stored transaction', async getExpectedTx => {
218
232
  const expectedTx = await getExpectedTx();
219
233
  const actualTx = await store.getTxEffect(expectedTx.data.txHash);
@@ -225,11 +239,11 @@ export function describeArchiverDataStore(
225
239
  });
226
240
 
227
241
  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),
242
+ () => wrapInBlock(blocks[0].block.body.txEffects[0], blocks[0].block),
243
+ () => wrapInBlock(blocks[9].block.body.txEffects[3], blocks[9].block),
244
+ () => wrapInBlock(blocks[3].block.body.txEffects[1], blocks[3].block),
245
+ () => wrapInBlock(blocks[5].block.body.txEffects[2], blocks[5].block),
246
+ () => wrapInBlock(blocks[1].block.body.txEffects[0], blocks[1].block),
233
247
  ])('tries to retrieves a previously stored transaction after deleted', async getExpectedTx => {
234
248
  await store.unwindBlocks(blocks.length, blocks.length);
235
249
 
@@ -292,16 +306,65 @@ export function describeArchiverDataStore(
292
306
  });
293
307
 
294
308
  it('returns previously stored contract instances', async () => {
295
- await expect(store.getContractInstance(contractInstance.address)).resolves.toMatchObject(contractInstance);
309
+ await expect(store.getContractInstance(contractInstance.address, blockNum)).resolves.toMatchObject(
310
+ contractInstance,
311
+ );
296
312
  });
297
313
 
298
314
  it('returns undefined if contract instance is not found', async () => {
299
- await expect(store.getContractInstance(await AztecAddress.random())).resolves.toBeUndefined();
315
+ await expect(store.getContractInstance(await AztecAddress.random(), blockNum)).resolves.toBeUndefined();
300
316
  });
301
317
 
302
318
  it('returns undefined if previously stored contract instances was deleted', async () => {
303
319
  await store.deleteContractInstances([contractInstance], blockNum);
304
- await expect(store.getContractInstance(contractInstance.address)).resolves.toBeUndefined();
320
+ await expect(store.getContractInstance(contractInstance.address, blockNum)).resolves.toBeUndefined();
321
+ });
322
+ });
323
+
324
+ describe('contractInstanceUpdates', () => {
325
+ let contractInstance: ContractInstanceWithAddress;
326
+ let classId: Fr;
327
+ let nextClassId: Fr;
328
+ const blockOfChange = 10;
329
+
330
+ beforeEach(async () => {
331
+ classId = Fr.random();
332
+ nextClassId = Fr.random();
333
+ const randomInstance = await SerializableContractInstance.random({
334
+ currentContractClassId: classId,
335
+ originalContractClassId: classId,
336
+ });
337
+ contractInstance = { ...randomInstance, address: await AztecAddress.random() };
338
+ await store.addContractInstances([contractInstance], 1);
339
+ await store.addContractInstanceUpdates(
340
+ [
341
+ {
342
+ prevContractClassId: classId,
343
+ newContractClassId: nextClassId,
344
+ blockOfChange,
345
+ address: contractInstance.address,
346
+ },
347
+ ],
348
+ blockOfChange - 1,
349
+ );
350
+ });
351
+
352
+ it('gets the correct current class id for a contract not updated yet', async () => {
353
+ const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange - 1);
354
+ expect(fetchedInstance?.originalContractClassId).toEqual(classId);
355
+ expect(fetchedInstance?.currentContractClassId).toEqual(classId);
356
+ });
357
+
358
+ it('gets the correct current class id for a contract that has just been updated', async () => {
359
+ const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange);
360
+ expect(fetchedInstance?.originalContractClassId).toEqual(classId);
361
+ expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
362
+ });
363
+
364
+ it('gets the correct current class id for a contract that was updated in the past', async () => {
365
+ const fetchedInstance = await store.getContractInstance(contractInstance.address, blockOfChange + 1);
366
+ expect(fetchedInstance?.originalContractClassId).toEqual(classId);
367
+ expect(fetchedInstance?.currentContractClassId).toEqual(nextClassId);
305
368
  });
306
369
  });
307
370
 
@@ -378,31 +441,19 @@ export function describeArchiverDataStore(
378
441
  const numPrivateLogsPerTx = 3;
379
442
  const numPublicLogsPerTx = 2;
380
443
 
381
- let blocks: L1Published<L2Block>[];
444
+ let blocks: PublishedL2Block[];
382
445
 
383
446
  const makeTag = (blockNumber: number, txIndex: number, logIndex: number, isPublic = false) =>
384
447
  new Fr((blockNumber * 100 + txIndex * 10 + logIndex) * (isPublic ? 123 : 1));
385
448
 
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
449
  const makePrivateLog = (tag: Fr) =>
396
450
  PrivateLog.fromFields([tag, ...times(PRIVATE_LOG_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i))]);
397
451
 
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
452
  const makePublicLog = (tag: Fr) =>
401
453
  PublicLog.fromFields([
402
454
  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
455
+ tag, // field 0
456
+ ...times(PUBLIC_LOG_DATA_SIZE_IN_FIELDS - 1, i => new Fr(tag.toNumber() + i)), // fields 1 to end
406
457
  ]);
407
458
 
408
459
  const mockPrivateLogs = (blockNumber: number, txIndex: number) => {
@@ -419,7 +470,7 @@ export function describeArchiverDataStore(
419
470
  });
420
471
  };
421
472
 
422
- const mockBlockWithLogs = async (blockNumber: number): Promise<L1Published<L2Block>> => {
473
+ const mockBlockWithLogs = async (blockNumber: number): Promise<PublishedL2Block> => {
423
474
  const block = await L2Block.random(blockNumber);
424
475
  block.header.globalVariables.blockNumber = new Fr(blockNumber);
425
476
 
@@ -431,7 +482,8 @@ export function describeArchiverDataStore(
431
482
  });
432
483
 
433
484
  return {
434
- data: block,
485
+ block: block,
486
+ signatures: times(3, Signature.random),
435
487
  l1: { blockNumber: BigInt(blockNumber), blockHash: `0x${blockNumber}`, timestamp: BigInt(blockNumber) },
436
488
  };
437
489
  };
@@ -440,7 +492,7 @@ export function describeArchiverDataStore(
440
492
  blocks = await timesParallel(numBlocks, (index: number) => mockBlockWithLogs(index));
441
493
 
442
494
  await store.addBlocks(blocks);
443
- await store.addLogs(blocks.map(b => b.data));
495
+ await store.addLogs(blocks.map(b => b.block));
444
496
  });
445
497
 
446
498
  it('is possible to batch request private logs via tags', async () => {
@@ -452,14 +504,14 @@ export function describeArchiverDataStore(
452
504
  [
453
505
  expect.objectContaining({
454
506
  blockNumber: 1,
455
- logData: makePrivateLog(tags[0]).toBuffer(),
507
+ log: makePrivateLog(tags[0]),
456
508
  isFromPublic: false,
457
509
  }),
458
510
  ],
459
511
  [
460
512
  expect.objectContaining({
461
513
  blockNumber: 0,
462
- logData: makePrivateLog(tags[1]).toBuffer(),
514
+ log: makePrivateLog(tags[1]),
463
515
  isFromPublic: false,
464
516
  }),
465
517
  ],
@@ -476,12 +528,12 @@ export function describeArchiverDataStore(
476
528
  [
477
529
  expect.objectContaining({
478
530
  blockNumber: 0,
479
- logData: makePrivateLog(tags[0]).toBuffer(),
531
+ log: makePrivateLog(tags[0]),
480
532
  isFromPublic: false,
481
533
  }),
482
534
  expect.objectContaining({
483
535
  blockNumber: 0,
484
- logData: makePublicLog(tags[0]).toBuffer(),
536
+ log: makePublicLog(tags[0]),
485
537
  isFromPublic: true,
486
538
  }),
487
539
  ],
@@ -494,11 +546,11 @@ export function describeArchiverDataStore(
494
546
  // Create a block containing logs that have the same tag as the blocks before.
495
547
  const newBlockNumber = numBlocks;
496
548
  const newBlock = await mockBlockWithLogs(newBlockNumber);
497
- const newLog = newBlock.data.body.txEffects[1].privateLogs[1];
549
+ const newLog = newBlock.block.body.txEffects[1].privateLogs[1];
498
550
  newLog.fields[0] = tags[0];
499
- newBlock.data.body.txEffects[1].privateLogs[1] = newLog;
551
+ newBlock.block.body.txEffects[1].privateLogs[1] = newLog;
500
552
  await store.addBlocks([newBlock]);
501
- await store.addLogs([newBlock.data]);
553
+ await store.addLogs([newBlock.block]);
502
554
 
503
555
  const logsByTags = await store.getLogsByTags(tags);
504
556
 
@@ -506,12 +558,12 @@ export function describeArchiverDataStore(
506
558
  [
507
559
  expect.objectContaining({
508
560
  blockNumber: 1,
509
- logData: makePrivateLog(tags[0]).toBuffer(),
561
+ log: makePrivateLog(tags[0]),
510
562
  isFromPublic: false,
511
563
  }),
512
564
  expect.objectContaining({
513
565
  blockNumber: newBlockNumber,
514
- logData: newLog.toBuffer(),
566
+ log: newLog,
515
567
  isFromPublic: false,
516
568
  }),
517
569
  ],
@@ -530,42 +582,12 @@ export function describeArchiverDataStore(
530
582
  [
531
583
  expect.objectContaining({
532
584
  blockNumber: 1,
533
- logData: makePrivateLog(tags[1]).toBuffer(),
585
+ log: makePrivateLog(tags[1]),
534
586
  isFromPublic: false,
535
587
  }),
536
588
  ],
537
589
  ]);
538
590
  });
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
591
  });
570
592
 
571
593
  describe('getPublicLogs', () => {
@@ -573,27 +595,28 @@ export function describeArchiverDataStore(
573
595
  const numPublicFunctionCalls = 3;
574
596
  const numPublicLogs = 2;
575
597
  const numBlocks = 10;
576
- let blocks: L1Published<L2Block>[];
598
+ let blocks: PublishedL2Block[];
577
599
 
578
600
  beforeEach(async () => {
579
601
  blocks = await timesParallel(numBlocks, async (index: number) => ({
580
- data: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs),
602
+ block: await L2Block.random(index + 1, txsPerBlock, numPublicFunctionCalls, numPublicLogs),
581
603
  l1: { blockNumber: BigInt(index), blockHash: `0x${index}`, timestamp: BigInt(index) },
604
+ signatures: times(3, Signature.random),
582
605
  }));
583
606
 
584
607
  await store.addBlocks(blocks);
585
- await store.addLogs(blocks.map(b => b.data));
608
+ await store.addLogs(blocks.map(b => b.block));
586
609
  });
587
610
 
588
611
  it('no logs returned if deleted ("txHash" filter param is respected variant)', async () => {
589
612
  // get random tx
590
613
  const targetBlockIndex = randomInt(numBlocks);
591
614
  const targetTxIndex = randomInt(txsPerBlock);
592
- const targetTxHash = blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash;
615
+ const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
593
616
 
594
617
  await Promise.all([
595
618
  store.unwindBlocks(blocks.length, blocks.length),
596
- store.deleteLogs(blocks.map(b => b.data)),
619
+ store.deleteLogs(blocks.map(b => b.block)),
597
620
  ]);
598
621
 
599
622
  const response = await store.getPublicLogs({ txHash: targetTxHash });
@@ -607,7 +630,7 @@ export function describeArchiverDataStore(
607
630
  // get random tx
608
631
  const targetBlockIndex = randomInt(numBlocks);
609
632
  const targetTxIndex = randomInt(txsPerBlock);
610
- const targetTxHash = blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].txHash;
633
+ const targetTxHash = blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].txHash;
611
634
 
612
635
  const response = await store.getPublicLogs({ txHash: targetTxHash });
613
636
  const logs = response.logs;
@@ -650,7 +673,7 @@ export function describeArchiverDataStore(
650
673
  const targetTxIndex = randomInt(txsPerBlock);
651
674
  const targetLogIndex = randomInt(numPublicLogs * numPublicFunctionCalls);
652
675
  const targetContractAddress =
653
- blocks[targetBlockIndex].data.body.txEffects[targetTxIndex].publicLogs[targetLogIndex].contractAddress;
676
+ blocks[targetBlockIndex].block.body.txEffects[targetTxIndex].publicLogs[targetLogIndex].contractAddress;
654
677
 
655
678
  const response = await store.getPublicLogs({ contractAddress: targetContractAddress });
656
679
 
@@ -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,
@@ -207,7 +207,7 @@ async function getBlockFromRollupTx(
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,6 +1,6 @@
1
1
  export * from './archiver.js';
2
2
  export * from './config.js';
3
- export { type L1Published, type L1PublishedData } from './structs/published.js';
3
+ export { type PublishedL2Block, type L1PublishedData } from './structs/published.js';
4
4
  export { MemoryArchiverStore } from './memory_archiver_store/memory_archiver_store.js';
5
5
  export type { ArchiverDataStore } from './archiver_store.js';
6
6
  export { KVArchiverDataStore } from './kv_archiver_store/kv_archiver_store.js';