@aztec/archiver 4.0.0-nightly.20260111 → 4.0.0-nightly.20260113

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/README.md +14 -14
  2. package/dest/archiver/archiver.d.ts +13 -10
  3. package/dest/archiver/archiver.d.ts.map +1 -1
  4. package/dest/archiver/archiver.js +97 -32
  5. package/dest/archiver/archiver_store.d.ts +11 -4
  6. package/dest/archiver/archiver_store.d.ts.map +1 -1
  7. package/dest/archiver/archiver_store_test_suite.d.ts +1 -1
  8. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  9. package/dest/archiver/archiver_store_test_suite.js +6 -6
  10. package/dest/archiver/config.js +2 -2
  11. package/dest/archiver/kv_archiver_store/block_store.d.ts +11 -4
  12. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  13. package/dest/archiver/kv_archiver_store/block_store.js +22 -3
  14. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +5 -4
  15. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
  16. package/dest/archiver/kv_archiver_store/kv_archiver_store.js +3 -0
  17. package/dest/archiver/l1/calldata_retriever.d.ts +2 -2
  18. package/dest/archiver/l1/calldata_retriever.d.ts.map +1 -1
  19. package/dest/archiver/l1/calldata_retriever.js +2 -2
  20. package/dest/archiver/l1/validate_trace.js +1 -1
  21. package/dest/archiver/validation.d.ts +4 -4
  22. package/dest/archiver/validation.d.ts.map +1 -1
  23. package/dest/archiver/validation.js +1 -1
  24. package/dest/test/mock_l1_to_l2_message_source.d.ts +2 -2
  25. package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
  26. package/dest/test/mock_l1_to_l2_message_source.js +12 -3
  27. package/dest/test/mock_l2_block_source.d.ts +8 -4
  28. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  29. package/dest/test/mock_l2_block_source.js +65 -19
  30. package/package.json +13 -13
  31. package/src/archiver/archiver.ts +137 -40
  32. package/src/archiver/archiver_store.ts +11 -3
  33. package/src/archiver/archiver_store_test_suite.ts +12 -13
  34. package/src/archiver/config.ts +2 -2
  35. package/src/archiver/kv_archiver_store/block_store.ts +35 -7
  36. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +7 -3
  37. package/src/archiver/l1/calldata_retriever.ts +2 -2
  38. package/src/archiver/l1/validate_trace.ts +1 -1
  39. package/src/archiver/validation.ts +6 -6
  40. package/src/test/mock_l1_to_l2_message_source.ts +10 -4
  41. package/src/test/mock_l2_block_source.ts +76 -18
@@ -14,9 +14,9 @@ import {
14
14
  CommitteeAttestation,
15
15
  L2BlockHash,
16
16
  L2BlockNew,
17
- type ValidateBlockResult,
18
- deserializeValidateBlockResult,
19
- serializeValidateBlockResult,
17
+ type ValidateCheckpointResult,
18
+ deserializeValidateCheckpointResult,
19
+ serializeValidateCheckpointResult,
20
20
  } from '@aztec/stdlib/block';
21
21
  import { L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
22
22
  import { CheckpointHeader } from '@aztec/stdlib/rollup';
@@ -503,6 +503,34 @@ export class BlockStore {
503
503
  );
504
504
  }
505
505
 
506
+ /**
507
+ * Gets up to `limit` amount of Checkpointed L2 blocks starting from `from`.
508
+ * @param start - Number of the first block to return (inclusive).
509
+ * @param limit - The number of blocks to return.
510
+ * @returns The requested L2 blocks
511
+ */
512
+ async *getCheckpointedBlocks(start: BlockNumber, limit: number): AsyncIterableIterator<CheckpointedL2Block> {
513
+ const checkpointCache = new Map<CheckpointNumber, CheckpointStorage>();
514
+ for await (const [blockNumber, blockStorage] of this.getBlockStorages(start, limit)) {
515
+ const block = await this.getBlockFromBlockStorage(blockNumber, blockStorage);
516
+ if (block) {
517
+ const checkpoint =
518
+ checkpointCache.get(CheckpointNumber(blockStorage.checkpointNumber)) ??
519
+ (await this.#checkpoints.getAsync(blockStorage.checkpointNumber));
520
+ if (checkpoint) {
521
+ checkpointCache.set(CheckpointNumber(blockStorage.checkpointNumber), checkpoint);
522
+ const checkpointedBlock = new CheckpointedL2Block(
523
+ CheckpointNumber(checkpoint.checkpointNumber),
524
+ block,
525
+ L1PublishedData.fromBuffer(checkpoint.l1),
526
+ checkpoint.attestations.map(buf => CommitteeAttestation.fromBuffer(buf)),
527
+ );
528
+ yield checkpointedBlock;
529
+ }
530
+ }
531
+ }
532
+ }
533
+
506
534
  async getCheckpointedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
507
535
  const blockNumber = await this.#blockHashIndex.getAsync(blockHash.toString());
508
536
  if (blockNumber === undefined) {
@@ -799,21 +827,21 @@ export class BlockStore {
799
827
  * Gets the pending chain validation status.
800
828
  * @returns The validation status or undefined if not set.
801
829
  */
802
- async getPendingChainValidationStatus(): Promise<ValidateBlockResult | undefined> {
830
+ async getPendingChainValidationStatus(): Promise<ValidateCheckpointResult | undefined> {
803
831
  const buffer = await this.#pendingChainValidationStatus.getAsync();
804
832
  if (!buffer) {
805
833
  return undefined;
806
834
  }
807
- return deserializeValidateBlockResult(buffer);
835
+ return deserializeValidateCheckpointResult(buffer);
808
836
  }
809
837
 
810
838
  /**
811
839
  * Sets the pending chain validation status.
812
840
  * @param status - The validation status to store.
813
841
  */
814
- async setPendingChainValidationStatus(status: ValidateBlockResult | undefined): Promise<void> {
842
+ async setPendingChainValidationStatus(status: ValidateCheckpointResult | undefined): Promise<void> {
815
843
  if (status) {
816
- const buffer = serializeValidateBlockResult(status);
844
+ const buffer = serializeValidateCheckpointResult(status);
817
845
  await this.#pendingChainValidationStatus.set(buffer);
818
846
  } else {
819
847
  await this.#pendingChainValidationStatus.delete();
@@ -6,7 +6,7 @@ import { createLogger } from '@aztec/foundation/log';
6
6
  import type { AztecAsyncKVStore, CustomRange, StoreSize } from '@aztec/kv-store';
7
7
  import { FunctionSelector } from '@aztec/stdlib/abi';
8
8
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
9
- import { CheckpointedL2Block, L2BlockHash, L2BlockNew, type ValidateBlockResult } from '@aztec/stdlib/block';
9
+ import { CheckpointedL2Block, L2BlockHash, L2BlockNew, type ValidateCheckpointResult } from '@aztec/stdlib/block';
10
10
  import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
11
11
  import type {
12
12
  ContractClassPublic,
@@ -234,6 +234,10 @@ export class KVArchiverDataStore implements ArchiverDataStore, ContractDataSourc
234
234
  return toArray(this.#blockStore.getBlocks(from, limit));
235
235
  }
236
236
 
237
+ getCheckpointedBlocks(from: BlockNumber, limit: number): Promise<CheckpointedL2Block[]> {
238
+ return toArray(this.#blockStore.getCheckpointedBlocks(from, limit));
239
+ }
240
+
237
241
  /**
238
242
  * Gets up to `limit` amount of L2 blocks headers starting from `from`.
239
243
  *
@@ -410,11 +414,11 @@ export class KVArchiverDataStore implements ArchiverDataStore, ContractDataSourc
410
414
  return this.#messageStore.removeL1ToL2Messages(startIndex);
411
415
  }
412
416
 
413
- public getPendingChainValidationStatus(): Promise<ValidateBlockResult | undefined> {
417
+ public getPendingChainValidationStatus(): Promise<ValidateCheckpointResult | undefined> {
414
418
  return this.#blockStore.getPendingChainValidationStatus();
415
419
  }
416
420
 
417
- public setPendingChainValidationStatus(status: ValidateBlockResult | undefined): Promise<void> {
421
+ public setPendingChainValidationStatus(status: ValidateCheckpointResult | undefined): Promise<void> {
418
422
  return this.#blockStore.setPendingChainValidationStatus(status);
419
423
  }
420
424
 
@@ -72,7 +72,7 @@ export class CalldataRetriever {
72
72
  */
73
73
  async getCheckpointFromRollupTx(
74
74
  txHash: `0x${string}`,
75
- blobHashes: Buffer[],
75
+ _blobHashes: Buffer[],
76
76
  checkpointNumber: CheckpointNumber,
77
77
  expectedHashes: {
78
78
  attestationsHash?: Hex;
@@ -459,7 +459,7 @@ export class CalldataRetriever {
459
459
  // Use ConsensusPayload to compute the digest - this ensures we match the exact logic
460
460
  // used by the network for signing and verification
461
461
  const consensusPayload = new ConsensusPayload(header, archiveRoot);
462
- const payloadToSign = consensusPayload.getPayloadToSign(SignatureDomainSeparator.blockAttestation);
462
+ const payloadToSign = consensusPayload.getPayloadToSign(SignatureDomainSeparator.checkpointAttestation);
463
463
  const computedPayloadDigest = keccak256(payloadToSign);
464
464
 
465
465
  // Compare as buffers to avoid case-sensitivity and string comparison issues
@@ -165,7 +165,7 @@ export async function validateAndLogTraceAvailability(
165
165
  client: ViemPublicDebugClient,
166
166
  ethereumAllowNoDebugHosts: boolean,
167
167
  ): Promise<void> {
168
- logger.info('Validating trace/debug method availability...');
168
+ logger.debug('Validating trace/debug method availability...');
169
169
 
170
170
  const availability = await validateTraceAvailability(client);
171
171
 
@@ -4,15 +4,15 @@ import { compactArray } from '@aztec/foundation/collection';
4
4
  import type { Logger } from '@aztec/foundation/log';
5
5
  import {
6
6
  type AttestationInfo,
7
- type ValidateBlockNegativeResult,
8
- type ValidateBlockResult,
7
+ type ValidateCheckpointNegativeResult,
8
+ type ValidateCheckpointResult,
9
9
  getAttestationInfoFromPayload,
10
10
  } from '@aztec/stdlib/block';
11
11
  import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
12
12
  import { type L1RollupConstants, getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
13
13
  import { ConsensusPayload } from '@aztec/stdlib/p2p';
14
14
 
15
- export type { ValidateBlockResult };
15
+ export type { ValidateCheckpointResult };
16
16
 
17
17
  /**
18
18
  * Extracts attestation information from a published checkpoint.
@@ -35,7 +35,7 @@ export async function validateCheckpointAttestations(
35
35
  epochCache: EpochCache,
36
36
  constants: Pick<L1RollupConstants, 'epochDuration'>,
37
37
  logger?: Logger,
38
- ): Promise<ValidateBlockResult> {
38
+ ): Promise<ValidateCheckpointResult> {
39
39
  const attestorInfos = getAttestationInfoFromPublishedCheckpoint(publishedCheckpoint);
40
40
  const attestors = compactArray(attestorInfos.map(info => ('address' in info ? info.address : undefined)));
41
41
  const { checkpoint, attestations } = publishedCheckpoint;
@@ -63,10 +63,10 @@ export async function validateCheckpointAttestations(
63
63
 
64
64
  const requiredAttestationCount = Math.floor((committee.length * 2) / 3) + 1;
65
65
 
66
- const failedValidationResult = <TReason extends ValidateBlockNegativeResult['reason']>(reason: TReason) => ({
66
+ const failedValidationResult = <TReason extends ValidateCheckpointNegativeResult['reason']>(reason: TReason) => ({
67
67
  valid: false as const,
68
68
  reason,
69
- block: checkpoint.blocks[0].toBlockInfo(),
69
+ checkpoint: checkpoint.toCheckpointInfo(),
70
70
  committee,
71
71
  seed,
72
72
  epoch,
@@ -1,6 +1,6 @@
1
- import { BlockNumber, type CheckpointNumber } from '@aztec/foundation/branded-types';
1
+ import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
2
2
  import { Fr } from '@aztec/foundation/curves/bn254';
3
- import type { L2Tips } from '@aztec/stdlib/block';
3
+ import type { CheckpointId, L2BlockId, L2TipId, L2Tips } from '@aztec/stdlib/block';
4
4
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
5
5
 
6
6
  /**
@@ -33,9 +33,15 @@ export class MockL1ToL2MessageSource implements L1ToL2MessageSource {
33
33
 
34
34
  getL2Tips(): Promise<L2Tips> {
35
35
  const number = this.blockNumber;
36
- const tip = { number: BlockNumber(number), hash: new Fr(number).toString() };
36
+ const blockId: L2BlockId = { number: BlockNumber(number), hash: new Fr(number).toString() };
37
+ const checkpointId: CheckpointId = {
38
+ number: CheckpointNumber(number),
39
+ hash: new Fr(number + 1).toString(),
40
+ };
41
+ const tip: L2TipId = { block: blockId, checkpoint: checkpointId };
37
42
  return Promise.resolve({
38
- latest: tip,
43
+ proposed: blockId,
44
+ checkpointed: tip,
39
45
  proven: tip,
40
46
  finalized: tip,
41
47
  });
@@ -8,13 +8,14 @@ import { createLogger } from '@aztec/foundation/log';
8
8
  import type { FunctionSelector } from '@aztec/stdlib/abi';
9
9
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
10
10
  import {
11
+ CheckpointedL2Block,
11
12
  L2Block,
12
13
  L2BlockHash,
13
14
  L2BlockNew,
14
15
  type L2BlockSource,
15
16
  type L2Tips,
16
17
  PublishedL2Block,
17
- type ValidateBlockResult,
18
+ type ValidateCheckpointResult,
18
19
  } from '@aztec/stdlib/block';
19
20
  import { type Checkpoint, L1PublishedData } from '@aztec/stdlib/checkpoint';
20
21
  import type { ContractClassPublic, ContractDataSource, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
@@ -30,6 +31,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
30
31
 
31
32
  private provenBlockNumber: number = 0;
32
33
  private finalizedBlockNumber: number = 0;
34
+ private checkpointedBlockNumber: number = 0;
33
35
 
34
36
  private log = createLogger('archiver:mock_l2_block_source');
35
37
 
@@ -64,6 +66,10 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
64
66
  this.finalizedBlockNumber = finalizedBlockNumber;
65
67
  }
66
68
 
69
+ public setCheckpointedBlockNumber(checkpointedBlockNumber: number) {
70
+ this.checkpointedBlockNumber = checkpointedBlockNumber;
71
+ }
72
+
67
73
  /**
68
74
  * Method to fetch the rollup contract address at the base-layer.
69
75
  * @returns The rollup address.
@@ -92,9 +98,40 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
92
98
  return Promise.resolve(BlockNumber(this.provenBlockNumber));
93
99
  }
94
100
 
95
- public getCheckpointedBlock(_number: BlockNumber) {
96
- // In this mock, we don't track checkpointed blocks separately
97
- return Promise.resolve(undefined);
101
+ public getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
102
+ if (number > this.checkpointedBlockNumber) {
103
+ return Promise.resolve(undefined);
104
+ }
105
+ const block = this.l2Blocks[number - 1];
106
+ if (!block) {
107
+ return Promise.resolve(undefined);
108
+ }
109
+ const checkpointedBlock = new CheckpointedL2Block(
110
+ CheckpointNumber(number),
111
+ block.toL2Block(),
112
+ new L1PublishedData(BigInt(number), BigInt(number), `0x${number.toString(16).padStart(64, '0')}`),
113
+ [],
114
+ );
115
+ return Promise.resolve(checkpointedBlock);
116
+ }
117
+
118
+ public async getCheckpointedBlocks(
119
+ from: BlockNumber,
120
+ limit: number,
121
+ _proven?: boolean,
122
+ ): Promise<CheckpointedL2Block[]> {
123
+ const result: CheckpointedL2Block[] = [];
124
+ for (let i = 0; i < limit; i++) {
125
+ const blockNum = from + i;
126
+ if (blockNum > this.checkpointedBlockNumber) {
127
+ break;
128
+ }
129
+ const block = await this.getCheckpointedBlock(BlockNumber(blockNum));
130
+ if (block) {
131
+ result.push(block);
132
+ }
133
+ }
134
+ return result;
98
135
  }
99
136
 
100
137
  /**
@@ -151,6 +188,11 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
151
188
  );
152
189
  }
153
190
 
191
+ async getL2BlocksNew(from: BlockNumber, limit: number, proven?: boolean): Promise<L2BlockNew[]> {
192
+ const blocks = await this.getBlocks(from, limit, proven);
193
+ return blocks.map(x => x.toL2Block());
194
+ }
195
+
154
196
  public async getPublishedBlockByHash(blockHash: Fr): Promise<PublishedL2Block | undefined> {
155
197
  for (const block of this.l2Blocks) {
156
198
  const hash = await block.hash();
@@ -263,29 +305,45 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
263
305
  }
264
306
 
265
307
  async getL2Tips(): Promise<L2Tips> {
266
- const [latest, proven, finalized] = [
308
+ const [latest, proven, finalized, checkpointed] = [
267
309
  await this.getBlockNumber(),
268
310
  await this.getProvenBlockNumber(),
269
311
  this.finalizedBlockNumber,
312
+ this.checkpointedBlockNumber,
270
313
  ] as const;
271
314
 
272
315
  const latestBlock = this.l2Blocks[latest - 1];
273
316
  const provenBlock = this.l2Blocks[proven - 1];
274
317
  const finalizedBlock = this.l2Blocks[finalized - 1];
318
+ const checkpointedBlock = this.l2Blocks[checkpointed - 1];
319
+
320
+ const latestBlockId = {
321
+ number: BlockNumber(latest),
322
+ hash: (await latestBlock?.hash())?.toString(),
323
+ };
324
+ const provenBlockId = {
325
+ number: BlockNumber(proven),
326
+ hash: (await provenBlock?.hash())?.toString(),
327
+ };
328
+ const finalizedBlockId = {
329
+ number: BlockNumber(finalized),
330
+ hash: (await finalizedBlock?.hash())?.toString(),
331
+ };
332
+ const checkpointedBlockId = {
333
+ number: BlockNumber(checkpointed),
334
+ hash: (await checkpointedBlock?.hash())?.toString(),
335
+ };
336
+
337
+ const makeTipId = (blockId: typeof latestBlockId) => ({
338
+ block: blockId,
339
+ checkpoint: { number: CheckpointNumber(blockId.number), hash: blockId.hash },
340
+ });
275
341
 
276
342
  return {
277
- latest: {
278
- number: BlockNumber(latest),
279
- hash: (await latestBlock?.hash())?.toString(),
280
- },
281
- proven: {
282
- number: BlockNumber(proven),
283
- hash: (await provenBlock?.hash())?.toString(),
284
- },
285
- finalized: {
286
- number: BlockNumber(finalized),
287
- hash: (await finalizedBlock?.hash())?.toString(),
288
- },
343
+ proposed: latestBlockId,
344
+ checkpointed: makeTipId(checkpointedBlockId),
345
+ proven: makeTipId(provenBlockId),
346
+ finalized: makeTipId(finalizedBlockId),
289
347
  };
290
348
  }
291
349
 
@@ -363,7 +421,7 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
363
421
  return Promise.resolve(false);
364
422
  }
365
423
 
366
- getPendingChainValidationStatus(): Promise<ValidateBlockResult> {
424
+ getPendingChainValidationStatus(): Promise<ValidateCheckpointResult> {
367
425
  return Promise.resolve({ valid: true });
368
426
  }
369
427
  }