@aztec/archiver 0.0.1-commit.3469e52 → 0.0.1-commit.381b1a9

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 (97) hide show
  1. package/README.md +9 -0
  2. package/dest/archiver.d.ts +12 -8
  3. package/dest/archiver.d.ts.map +1 -1
  4. package/dest/archiver.js +81 -120
  5. package/dest/errors.d.ts +6 -1
  6. package/dest/errors.d.ts.map +1 -1
  7. package/dest/errors.js +8 -0
  8. package/dest/factory.d.ts +3 -1
  9. package/dest/factory.d.ts.map +1 -1
  10. package/dest/factory.js +14 -11
  11. package/dest/index.d.ts +2 -1
  12. package/dest/index.d.ts.map +1 -1
  13. package/dest/index.js +1 -0
  14. package/dest/l1/bin/retrieve-calldata.js +35 -32
  15. package/dest/l1/calldata_retriever.d.ts +73 -50
  16. package/dest/l1/calldata_retriever.d.ts.map +1 -1
  17. package/dest/l1/calldata_retriever.js +190 -259
  18. package/dest/l1/data_retrieval.d.ts +4 -7
  19. package/dest/l1/data_retrieval.d.ts.map +1 -1
  20. package/dest/l1/data_retrieval.js +12 -16
  21. package/dest/l1/spire_proposer.d.ts +5 -5
  22. package/dest/l1/spire_proposer.d.ts.map +1 -1
  23. package/dest/l1/spire_proposer.js +9 -17
  24. package/dest/l1/validate_trace.d.ts +6 -3
  25. package/dest/l1/validate_trace.d.ts.map +1 -1
  26. package/dest/l1/validate_trace.js +13 -9
  27. package/dest/modules/data_source_base.d.ts +25 -21
  28. package/dest/modules/data_source_base.d.ts.map +1 -1
  29. package/dest/modules/data_source_base.js +45 -120
  30. package/dest/modules/data_store_updater.d.ts +40 -21
  31. package/dest/modules/data_store_updater.d.ts.map +1 -1
  32. package/dest/modules/data_store_updater.js +114 -64
  33. package/dest/modules/instrumentation.d.ts +6 -4
  34. package/dest/modules/instrumentation.d.ts.map +1 -1
  35. package/dest/modules/instrumentation.js +26 -12
  36. package/dest/modules/l1_synchronizer.d.ts +5 -8
  37. package/dest/modules/l1_synchronizer.d.ts.map +1 -1
  38. package/dest/modules/l1_synchronizer.js +46 -20
  39. package/dest/store/block_store.d.ts +49 -32
  40. package/dest/store/block_store.d.ts.map +1 -1
  41. package/dest/store/block_store.js +165 -54
  42. package/dest/store/contract_class_store.d.ts +1 -1
  43. package/dest/store/contract_class_store.d.ts.map +1 -1
  44. package/dest/store/contract_class_store.js +11 -7
  45. package/dest/store/kv_archiver_store.d.ts +53 -25
  46. package/dest/store/kv_archiver_store.d.ts.map +1 -1
  47. package/dest/store/kv_archiver_store.js +50 -17
  48. package/dest/store/l2_tips_cache.d.ts +19 -0
  49. package/dest/store/l2_tips_cache.d.ts.map +1 -0
  50. package/dest/store/l2_tips_cache.js +89 -0
  51. package/dest/store/log_store.d.ts +4 -4
  52. package/dest/store/log_store.d.ts.map +1 -1
  53. package/dest/store/log_store.js +105 -47
  54. package/dest/store/message_store.js +1 -1
  55. package/dest/test/fake_l1_state.d.ts +16 -4
  56. package/dest/test/fake_l1_state.d.ts.map +1 -1
  57. package/dest/test/fake_l1_state.js +84 -20
  58. package/dest/test/index.js +3 -1
  59. package/dest/test/mock_archiver.d.ts +1 -1
  60. package/dest/test/mock_archiver.d.ts.map +1 -1
  61. package/dest/test/mock_archiver.js +3 -2
  62. package/dest/test/mock_l2_block_source.d.ts +39 -23
  63. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  64. package/dest/test/mock_l2_block_source.js +157 -112
  65. package/dest/test/mock_structs.d.ts +6 -2
  66. package/dest/test/mock_structs.d.ts.map +1 -1
  67. package/dest/test/mock_structs.js +24 -10
  68. package/dest/test/noop_l1_archiver.d.ts +26 -0
  69. package/dest/test/noop_l1_archiver.d.ts.map +1 -0
  70. package/dest/test/noop_l1_archiver.js +72 -0
  71. package/package.json +14 -13
  72. package/src/archiver.ts +106 -149
  73. package/src/errors.ts +12 -0
  74. package/src/factory.ts +29 -12
  75. package/src/index.ts +1 -0
  76. package/src/l1/README.md +25 -68
  77. package/src/l1/bin/retrieve-calldata.ts +45 -33
  78. package/src/l1/calldata_retriever.ts +249 -379
  79. package/src/l1/data_retrieval.ts +10 -20
  80. package/src/l1/spire_proposer.ts +7 -15
  81. package/src/l1/validate_trace.ts +24 -6
  82. package/src/modules/data_source_base.ts +76 -166
  83. package/src/modules/data_store_updater.ts +130 -66
  84. package/src/modules/instrumentation.ts +26 -14
  85. package/src/modules/l1_synchronizer.ts +55 -26
  86. package/src/store/block_store.ts +216 -92
  87. package/src/store/contract_class_store.ts +11 -7
  88. package/src/store/kv_archiver_store.ts +88 -30
  89. package/src/store/l2_tips_cache.ts +89 -0
  90. package/src/store/log_store.ts +171 -55
  91. package/src/store/message_store.ts +1 -1
  92. package/src/test/fake_l1_state.ts +112 -23
  93. package/src/test/index.ts +3 -0
  94. package/src/test/mock_archiver.ts +3 -2
  95. package/src/test/mock_l2_block_source.ts +211 -129
  96. package/src/test/mock_structs.ts +45 -15
  97. package/src/test/noop_l1_archiver.ts +115 -0
@@ -6,8 +6,14 @@ 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 ValidateCheckpointResult } from '@aztec/stdlib/block';
10
- import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
9
+ import {
10
+ type BlockData,
11
+ BlockHash,
12
+ CheckpointedL2Block,
13
+ L2Block,
14
+ type ValidateCheckpointResult,
15
+ } from '@aztec/stdlib/block';
16
+ import type { CheckpointData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
11
17
  import type {
12
18
  ContractClassPublic,
13
19
  ContractDataSource,
@@ -16,6 +22,7 @@ import type {
16
22
  ExecutablePrivateFunctionWithMembershipProof,
17
23
  UtilityFunctionWithMembershipProof,
18
24
  } from '@aztec/stdlib/contract';
25
+ import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
19
26
  import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
20
27
  import type { LogFilter, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
21
28
  import type { BlockHeader, TxHash, TxReceipt } from '@aztec/stdlib/tx';
@@ -24,7 +31,7 @@ import type { UInt64 } from '@aztec/stdlib/types';
24
31
  import { join } from 'path';
25
32
 
26
33
  import type { InboxMessage } from '../structs/inbox_message.js';
27
- import { BlockStore, type CheckpointData } from './block_store.js';
34
+ import { BlockStore, type RemoveCheckpointsResult } from './block_store.js';
28
35
  import { ContractClassStore } from './contract_class_store.js';
29
36
  import { ContractInstanceStore } from './contract_instance_store.js';
30
37
  import { LogStore } from './log_store.js';
@@ -72,6 +79,11 @@ export class KVArchiverDataStore implements ContractDataSource {
72
79
  this.#contractInstanceStore = new ContractInstanceStore(db);
73
80
  }
74
81
 
82
+ /** Returns the underlying block store. Used by L2TipsCache. */
83
+ get blockStore(): BlockStore {
84
+ return this.#blockStore;
85
+ }
86
+
75
87
  /** Opens a new transaction to the underlying store and runs all operations within it. */
76
88
  public transactionAsync<T>(callback: () => Promise<T>): Promise<T> {
77
89
  return this.db.transactionAsync(callback);
@@ -101,6 +113,11 @@ export class KVArchiverDataStore implements ContractDataSource {
101
113
  return this.db.close();
102
114
  }
103
115
 
116
+ /** Computes the finalized block number based on the proven block number. */
117
+ getFinalizedL2BlockNumber(): Promise<BlockNumber> {
118
+ return this.#blockStore.getFinalizedL2BlockNumber();
119
+ }
120
+
104
121
  /** Looks up a public function name given a selector. */
105
122
  getDebugFunctionName(_address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
106
123
  return Promise.resolve(this.functionNames.get(selector.toString()));
@@ -228,12 +245,14 @@ export class KVArchiverDataStore implements ContractDataSource {
228
245
  }
229
246
 
230
247
  /**
231
- * Append new blocks to the store's list.
232
- * @param blocks - The L2 blocks to be added to the store and the last processed L1 block.
248
+ * Append new proposed blocks to the store's list.
249
+ * These are uncheckpointed blocks that have been proposed by the sequencer but not yet included in a checkpoint on L1.
250
+ * For checkpointed blocks (already published to L1), use addCheckpoints() instead.
251
+ * @param blocks - The proposed L2 blocks to be added to the store.
233
252
  * @returns True if the operation is successful.
234
253
  */
235
- addBlocks(blocks: L2BlockNew[], opts: { force?: boolean; checkpointNumber?: number } = {}): Promise<boolean> {
236
- return this.#blockStore.addBlocks(blocks, opts);
254
+ addProposedBlocks(blocks: L2Block[], opts: { force?: boolean; checkpointNumber?: number } = {}): Promise<boolean> {
255
+ return this.#blockStore.addProposedBlocks(blocks, opts);
237
256
  }
238
257
 
239
258
  /**
@@ -254,14 +273,12 @@ export class KVArchiverDataStore implements ContractDataSource {
254
273
  }
255
274
 
256
275
  /**
257
- * Unwinds checkpoints from the database
258
- * @param from - The tip of the chain, passed for verification purposes,
259
- * ensuring that we don't end up deleting something we did not intend
260
- * @param checkpointsToUnwind - The number of checkpoints we are to unwind
261
- * @returns True if the operation is successful
276
+ * Removes all checkpoints with checkpoint number > checkpointNumber.
277
+ * Also removes ALL blocks (both checkpointed and uncheckpointed) after the last block of the given checkpoint.
278
+ * @param checkpointNumber - Remove all checkpoints strictly after this one.
262
279
  */
263
- unwindCheckpoints(from: CheckpointNumber, checkpointsToUnwind: number): Promise<boolean> {
264
- return this.#blockStore.unwindCheckpoints(from, checkpointsToUnwind);
280
+ removeCheckpointsAfter(checkpointNumber: CheckpointNumber): Promise<RemoveCheckpointsResult> {
281
+ return this.#blockStore.removeCheckpointsAfter(checkpointNumber);
265
282
  }
266
283
 
267
284
  /**
@@ -284,7 +301,7 @@ export class KVArchiverDataStore implements ContractDataSource {
284
301
  * Returns the block for the given hash, or undefined if not exists.
285
302
  * @param blockHash - The block hash to return.
286
303
  */
287
- getCheckpointedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
304
+ getCheckpointedBlockByHash(blockHash: BlockHash): Promise<CheckpointedL2Block | undefined> {
288
305
  return this.#blockStore.getCheckpointedBlockByHash(blockHash);
289
306
  }
290
307
  /**
@@ -298,21 +315,21 @@ export class KVArchiverDataStore implements ContractDataSource {
298
315
  * Returns the block for the given number, or undefined if not exists.
299
316
  * @param number - The block number to return.
300
317
  */
301
- getBlock(number: BlockNumber): Promise<L2BlockNew | undefined> {
318
+ getBlock(number: BlockNumber): Promise<L2Block | undefined> {
302
319
  return this.#blockStore.getBlock(number);
303
320
  }
304
321
  /**
305
322
  * Returns the block for the given hash, or undefined if not exists.
306
323
  * @param blockHash - The block hash to return.
307
324
  */
308
- getBlockByHash(blockHash: Fr): Promise<L2BlockNew | undefined> {
309
- return this.#blockStore.getBlockByHash(L2BlockHash.fromField(blockHash));
325
+ getBlockByHash(blockHash: BlockHash): Promise<L2Block | undefined> {
326
+ return this.#blockStore.getBlockByHash(blockHash);
310
327
  }
311
328
  /**
312
329
  * Returns the block for the given archive root, or undefined if not exists.
313
330
  * @param archive - The archive root to return.
314
331
  */
315
- getBlockByArchive(archive: Fr): Promise<L2BlockNew | undefined> {
332
+ getBlockByArchive(archive: Fr): Promise<L2Block | undefined> {
316
333
  return this.#blockStore.getBlockByArchive(archive);
317
334
  }
318
335
 
@@ -322,7 +339,7 @@ export class KVArchiverDataStore implements ContractDataSource {
322
339
  * @param limit - The number of blocks to return.
323
340
  * @returns The requested L2 blocks.
324
341
  */
325
- getBlocks(from: BlockNumber, limit: number): Promise<L2BlockNew[]> {
342
+ getBlocks(from: BlockNumber, limit: number): Promise<L2Block[]> {
326
343
  return toArray(this.#blockStore.getBlocks(from, limit));
327
344
  }
328
345
 
@@ -350,8 +367,8 @@ export class KVArchiverDataStore implements ContractDataSource {
350
367
  * Returns the block header for the given hash, or undefined if not exists.
351
368
  * @param blockHash - The block hash to return.
352
369
  */
353
- getBlockHeaderByHash(blockHash: Fr): Promise<BlockHeader | undefined> {
354
- return this.#blockStore.getBlockHeaderByHash(L2BlockHash.fromField(blockHash));
370
+ getBlockHeaderByHash(blockHash: BlockHash): Promise<BlockHeader | undefined> {
371
+ return this.#blockStore.getBlockHeaderByHash(blockHash);
355
372
  }
356
373
 
357
374
  /**
@@ -362,6 +379,22 @@ export class KVArchiverDataStore implements ContractDataSource {
362
379
  return this.#blockStore.getBlockHeaderByArchive(archive);
363
380
  }
364
381
 
382
+ /**
383
+ * Gets block metadata (without tx data) by block number.
384
+ * @param blockNumber - The block number to return.
385
+ */
386
+ getBlockData(blockNumber: BlockNumber): Promise<BlockData | undefined> {
387
+ return this.#blockStore.getBlockData(blockNumber);
388
+ }
389
+
390
+ /**
391
+ * Gets block metadata (without tx data) by archive root.
392
+ * @param archive - The archive root to return.
393
+ */
394
+ getBlockDataByArchive(archive: Fr): Promise<BlockData | undefined> {
395
+ return this.#blockStore.getBlockDataByArchive(archive);
396
+ }
397
+
365
398
  /**
366
399
  * Gets a tx effect.
367
400
  * @param txHash - The hash of the tx corresponding to the tx effect.
@@ -376,8 +409,11 @@ export class KVArchiverDataStore implements ContractDataSource {
376
409
  * @param txHash - The hash of a tx we try to get the receipt for.
377
410
  * @returns The requested tx receipt (or undefined if not found).
378
411
  */
379
- getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
380
- return this.#blockStore.getSettledTxReceipt(txHash);
412
+ getSettledTxReceipt(
413
+ txHash: TxHash,
414
+ l1Constants?: Pick<L1RollupConstants, 'epochDuration'>,
415
+ ): Promise<TxReceipt | undefined> {
416
+ return this.#blockStore.getSettledTxReceipt(txHash, l1Constants);
381
417
  }
382
418
 
383
419
  /**
@@ -385,11 +421,11 @@ export class KVArchiverDataStore implements ContractDataSource {
385
421
  * @param blocks - The blocks for which to add the logs.
386
422
  * @returns True if the operation is successful.
387
423
  */
388
- addLogs(blocks: L2BlockNew[]): Promise<boolean> {
424
+ addLogs(blocks: L2Block[]): Promise<boolean> {
389
425
  return this.#logStore.addLogs(blocks);
390
426
  }
391
427
 
392
- deleteLogs(blocks: L2BlockNew[]): Promise<boolean> {
428
+ deleteLogs(blocks: L2Block[]): Promise<boolean> {
393
429
  return this.#logStore.deleteLogs(blocks);
394
430
  }
395
431
 
@@ -508,6 +544,22 @@ export class KVArchiverDataStore implements ContractDataSource {
508
544
  await this.#blockStore.setProvenCheckpointNumber(checkpointNumber);
509
545
  }
510
546
 
547
+ /**
548
+ * Gets the number of the latest finalized checkpoint processed.
549
+ * @returns The number of the latest finalized checkpoint processed.
550
+ */
551
+ getFinalizedCheckpointNumber(): Promise<CheckpointNumber> {
552
+ return this.#blockStore.getFinalizedCheckpointNumber();
553
+ }
554
+
555
+ /**
556
+ * Stores the number of the latest finalized checkpoint processed.
557
+ * @param checkpointNumber - The number of the latest finalized checkpoint processed.
558
+ */
559
+ async setFinalizedCheckpointNumber(checkpointNumber: CheckpointNumber) {
560
+ await this.#blockStore.setFinalizedCheckpointNumber(checkpointNumber);
561
+ }
562
+
511
563
  async setBlockSynchedL1BlockNumber(l1BlockNumber: bigint) {
512
564
  await this.#blockStore.setSynchedL1BlockNumber(l1BlockNumber);
513
565
  }
@@ -598,7 +650,7 @@ export class KVArchiverDataStore implements ContractDataSource {
598
650
  * @param checkpointNumber Retrieves all blocks for the given checkpoint
599
651
  * @returns The collection of blocks for the requested checkpoint if available (undefined otherwise)
600
652
  */
601
- getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<L2BlockNew[] | undefined> {
653
+ getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<L2Block[] | undefined> {
602
654
  return this.#blockStore.getBlocksForCheckpoint(checkpointNumber);
603
655
  }
604
656
 
@@ -611,21 +663,27 @@ export class KVArchiverDataStore implements ContractDataSource {
611
663
  return this.#blockStore.getCheckpointData(checkpointNumber);
612
664
  }
613
665
 
666
+ /** Returns checkpoint data for all checkpoints whose slot falls within the given range (inclusive). */
667
+ getCheckpointDataForSlotRange(startSlot: SlotNumber, endSlot: SlotNumber): Promise<CheckpointData[]> {
668
+ return this.#blockStore.getCheckpointDataForSlotRange(startSlot, endSlot);
669
+ }
670
+
614
671
  /**
615
672
  * Gets all blocks that have the given slot number.
616
673
  * @param slotNumber - The slot number to search for.
617
674
  * @returns All blocks with the given slot number.
618
675
  */
619
- getBlocksForSlot(slotNumber: SlotNumber): Promise<L2BlockNew[]> {
676
+ getBlocksForSlot(slotNumber: SlotNumber): Promise<L2Block[]> {
620
677
  return this.#blockStore.getBlocksForSlot(slotNumber);
621
678
  }
622
679
 
623
680
  /**
624
681
  * Removes all blocks with block number > blockNumber.
682
+ * Does not remove any associated checkpoints.
625
683
  * @param blockNumber - The block number to remove after.
626
684
  * @returns The removed blocks (for event emission).
627
685
  */
628
- removeBlocksAfter(blockNumber: BlockNumber): Promise<L2BlockNew[]> {
629
- return this.#blockStore.unwindBlocksAfter(blockNumber);
686
+ removeBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]> {
687
+ return this.#blockStore.removeBlocksAfter(blockNumber);
630
688
  }
631
689
  }
@@ -0,0 +1,89 @@
1
+ import { GENESIS_BLOCK_HEADER_HASH, INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
2
+ import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
3
+ import { type BlockData, type CheckpointId, GENESIS_CHECKPOINT_HEADER_HASH, type L2Tips } from '@aztec/stdlib/block';
4
+
5
+ import type { BlockStore } from './block_store.js';
6
+
7
+ /**
8
+ * In-memory cache for L2 chain tips (proposed, checkpointed, proven, finalized).
9
+ * Populated from the BlockStore on first access, then kept up-to-date by the ArchiverDataStoreUpdater.
10
+ * Refresh calls should happen within the store transaction that mutates block data to ensure consistency.
11
+ */
12
+ export class L2TipsCache {
13
+ #tipsPromise: Promise<L2Tips> | undefined;
14
+
15
+ constructor(private blockStore: BlockStore) {}
16
+
17
+ /** Returns the cached L2 tips. Loads from the block store on first call. */
18
+ public getL2Tips(): Promise<L2Tips> {
19
+ return (this.#tipsPromise ??= this.loadFromStore());
20
+ }
21
+
22
+ /** Reloads the L2 tips from the block store. Should be called within the store transaction that mutates data. */
23
+ public async refresh(): Promise<void> {
24
+ this.#tipsPromise = this.loadFromStore();
25
+ await this.#tipsPromise;
26
+ }
27
+
28
+ private async loadFromStore(): Promise<L2Tips> {
29
+ const [latestBlockNumber, provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber] = await Promise.all([
30
+ this.blockStore.getLatestBlockNumber(),
31
+ this.blockStore.getProvenBlockNumber(),
32
+ this.blockStore.getCheckpointedL2BlockNumber(),
33
+ this.blockStore.getFinalizedL2BlockNumber(),
34
+ ]);
35
+
36
+ const genesisBlockHeader = {
37
+ blockHash: GENESIS_BLOCK_HEADER_HASH,
38
+ checkpointNumber: CheckpointNumber.ZERO,
39
+ } as const;
40
+ const beforeInitialBlockNumber = BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
41
+
42
+ const getBlockData = (blockNumber: BlockNumber) =>
43
+ blockNumber > beforeInitialBlockNumber ? this.blockStore.getBlockData(blockNumber) : genesisBlockHeader;
44
+
45
+ const [latestBlockData, provenBlockData, checkpointedBlockData, finalizedBlockData] = await Promise.all(
46
+ [latestBlockNumber, provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber].map(getBlockData),
47
+ );
48
+
49
+ if (!latestBlockData || !provenBlockData || !finalizedBlockData || !checkpointedBlockData) {
50
+ throw new Error('Failed to load block data for L2 tips');
51
+ }
52
+
53
+ const [provenCheckpointId, finalizedCheckpointId, checkpointedCheckpointId] = await Promise.all([
54
+ this.getCheckpointIdForBlock(provenBlockData),
55
+ this.getCheckpointIdForBlock(finalizedBlockData),
56
+ this.getCheckpointIdForBlock(checkpointedBlockData),
57
+ ]);
58
+
59
+ return {
60
+ proposed: { number: latestBlockNumber, hash: latestBlockData.blockHash.toString() },
61
+ proven: {
62
+ block: { number: provenBlockNumber, hash: provenBlockData.blockHash.toString() },
63
+ checkpoint: provenCheckpointId,
64
+ },
65
+ finalized: {
66
+ block: { number: finalizedBlockNumber, hash: finalizedBlockData.blockHash.toString() },
67
+ checkpoint: finalizedCheckpointId,
68
+ },
69
+ checkpointed: {
70
+ block: { number: checkpointedBlockNumber, hash: checkpointedBlockData.blockHash.toString() },
71
+ checkpoint: checkpointedCheckpointId,
72
+ },
73
+ };
74
+ }
75
+
76
+ private async getCheckpointIdForBlock(blockData: Pick<BlockData, 'checkpointNumber'>): Promise<CheckpointId> {
77
+ const checkpointData = await this.blockStore.getCheckpointData(blockData.checkpointNumber);
78
+ if (!checkpointData) {
79
+ return {
80
+ number: CheckpointNumber.ZERO,
81
+ hash: GENESIS_CHECKPOINT_HEADER_HASH.toString(),
82
+ };
83
+ }
84
+ return {
85
+ number: checkpointData.checkpointNumber,
86
+ hash: checkpointData.header.hash().toString(),
87
+ };
88
+ }
89
+ }