@aztec/archiver 3.0.0-rc.5 → 4.0.0-nightly.20260107

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 (55) hide show
  1. package/dest/archiver/archiver.d.ts +69 -49
  2. package/dest/archiver/archiver.d.ts.map +1 -1
  3. package/dest/archiver/archiver.js +777 -214
  4. package/dest/archiver/archiver_store.d.ts +89 -30
  5. package/dest/archiver/archiver_store.d.ts.map +1 -1
  6. package/dest/archiver/archiver_store_test_suite.d.ts +1 -1
  7. package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
  8. package/dest/archiver/archiver_store_test_suite.js +1785 -288
  9. package/dest/archiver/config.d.ts +3 -3
  10. package/dest/archiver/config.d.ts.map +1 -1
  11. package/dest/archiver/config.js +2 -2
  12. package/dest/archiver/errors.d.ts +25 -1
  13. package/dest/archiver/errors.d.ts.map +1 -1
  14. package/dest/archiver/errors.js +37 -0
  15. package/dest/archiver/index.d.ts +2 -2
  16. package/dest/archiver/index.d.ts.map +1 -1
  17. package/dest/archiver/kv_archiver_store/block_store.d.ts +49 -17
  18. package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
  19. package/dest/archiver/kv_archiver_store/block_store.js +320 -84
  20. package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +33 -37
  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 +60 -35
  23. package/dest/archiver/kv_archiver_store/log_store.d.ts +14 -11
  24. package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
  25. package/dest/archiver/kv_archiver_store/log_store.js +149 -62
  26. package/dest/archiver/l1/bin/retrieve-calldata.js +5 -3
  27. package/dest/archiver/l1/calldata_retriever.d.ts +17 -3
  28. package/dest/archiver/l1/calldata_retriever.d.ts.map +1 -1
  29. package/dest/archiver/l1/calldata_retriever.js +75 -7
  30. package/dest/archiver/l1/data_retrieval.d.ts +13 -10
  31. package/dest/archiver/l1/data_retrieval.d.ts.map +1 -1
  32. package/dest/archiver/l1/data_retrieval.js +31 -18
  33. package/dest/archiver/structs/published.d.ts +1 -2
  34. package/dest/archiver/structs/published.d.ts.map +1 -1
  35. package/dest/factory.d.ts +1 -1
  36. package/dest/factory.js +1 -1
  37. package/dest/test/mock_l2_block_source.d.ts +10 -3
  38. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  39. package/dest/test/mock_l2_block_source.js +16 -15
  40. package/package.json +13 -13
  41. package/src/archiver/archiver.ts +509 -260
  42. package/src/archiver/archiver_store.ts +99 -29
  43. package/src/archiver/archiver_store_test_suite.ts +1831 -274
  44. package/src/archiver/config.ts +7 -3
  45. package/src/archiver/errors.ts +64 -0
  46. package/src/archiver/index.ts +1 -1
  47. package/src/archiver/kv_archiver_store/block_store.ts +434 -94
  48. package/src/archiver/kv_archiver_store/kv_archiver_store.ts +74 -49
  49. package/src/archiver/kv_archiver_store/log_store.ts +213 -77
  50. package/src/archiver/l1/bin/retrieve-calldata.ts +3 -3
  51. package/src/archiver/l1/calldata_retriever.ts +116 -6
  52. package/src/archiver/l1/data_retrieval.ts +41 -20
  53. package/src/archiver/structs/published.ts +0 -1
  54. package/src/factory.ts +1 -1
  55. package/src/test/mock_l2_block_source.ts +20 -16
@@ -1,4 +1,4 @@
1
- import type { BlobSinkClientInterface } from '@aztec/blob-sink/client';
1
+ import type { BlobClientInterface } from '@aztec/blob-client/client';
2
2
  import { GENESIS_BLOCK_HEADER_HASH } from '@aztec/constants';
3
3
  import { EpochCache } from '@aztec/epoch-cache';
4
4
  import { createEthereumChain } from '@aztec/ethereum/chain';
@@ -17,6 +17,7 @@ import { type PromiseWithResolvers, promiseWithResolvers } from '@aztec/foundati
17
17
  import { RunningPromise, makeLoggingErrorHandler } from '@aztec/foundation/running-promise';
18
18
  import { count } from '@aztec/foundation/string';
19
19
  import { DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
20
+ import { isDefined } from '@aztec/foundation/types';
20
21
  import type { CustomRange } from '@aztec/kv-store';
21
22
  import { RollupAbi } from '@aztec/l1-artifacts';
22
23
  import {
@@ -32,13 +33,17 @@ import type { FunctionSelector } from '@aztec/stdlib/abi';
32
33
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
33
34
  import {
34
35
  type ArchiverEmitter,
36
+ CheckpointedL2Block,
37
+ CommitteeAttestation,
35
38
  L2Block,
39
+ L2BlockNew,
40
+ type L2BlockSink,
36
41
  type L2BlockSource,
37
42
  L2BlockSourceEvents,
38
43
  type L2Tips,
39
44
  PublishedL2Block,
40
45
  } from '@aztec/stdlib/block';
41
- import type { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
46
+ import { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
42
47
  import {
43
48
  type ContractClassPublic,
44
49
  type ContractDataSource,
@@ -59,7 +64,15 @@ import {
59
64
  } from '@aztec/stdlib/epoch-helpers';
60
65
  import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
61
66
  import type { L2LogsSource } from '@aztec/stdlib/interfaces/server';
62
- import { ContractClassLog, type LogFilter, type PrivateLog, type PublicLog, TxScopedL2Log } from '@aztec/stdlib/logs';
67
+ import {
68
+ ContractClassLog,
69
+ type LogFilter,
70
+ type PrivateLog,
71
+ type PublicLog,
72
+ type SiloedTag,
73
+ Tag,
74
+ TxScopedL2Log,
75
+ } from '@aztec/stdlib/logs';
63
76
  import { type L1ToL2MessageSource, computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
64
77
  import type { CheckpointHeader } from '@aztec/stdlib/rollup';
65
78
  import { type BlockHeader, type IndexedTxEffect, TxHash, TxReceipt } from '@aztec/stdlib/tx';
@@ -78,8 +91,9 @@ import { type GetContractReturnType, type Hex, createPublicClient, fallback, htt
78
91
 
79
92
  import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.js';
80
93
  import type { ArchiverConfig } from './config.js';
81
- import { InitialBlockNumberNotSequentialError, NoBlobBodiesFoundError } from './errors.js';
94
+ import { InitialCheckpointNumberNotSequentialError, NoBlobBodiesFoundError } from './errors.js';
82
95
  import { ArchiverInstrumentation } from './instrumentation.js';
96
+ import type { CheckpointData } from './kv_archiver_store/block_store.js';
83
97
  import {
84
98
  retrieveCheckpointsFromRollup,
85
99
  retrieveL1ToL2Message,
@@ -95,9 +109,16 @@ import { type ValidateBlockResult, validateCheckpointAttestations } from './vali
95
109
  */
96
110
  export type ArchiveSource = L2BlockSource & L2LogsSource & ContractDataSource & L1ToL2MessageSource;
97
111
 
112
+ /** Request to add a block to the archiver, queued for processing by the sync loop. */
113
+ type AddBlockRequest = {
114
+ block: L2BlockNew;
115
+ resolve: () => void;
116
+ reject: (err: Error) => void;
117
+ };
118
+
98
119
  export type ArchiverDeps = {
99
120
  telemetry?: TelemetryClient;
100
- blobSinkClient: BlobSinkClientInterface;
121
+ blobClient: BlobClientInterface;
101
122
  epochCache?: EpochCache;
102
123
  dateProvider?: DateProvider;
103
124
  };
@@ -127,7 +148,10 @@ type RollupStatus = {
127
148
  * Responsible for handling robust L1 polling so that other components do not need to
128
149
  * concern themselves with it.
129
150
  */
130
- export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implements ArchiveSource, Traceable {
151
+ export class Archiver
152
+ extends (EventEmitter as new () => ArchiverEmitter)
153
+ implements ArchiveSource, L2BlockSink, Traceable
154
+ {
131
155
  /** A loop in which we will be continually fetching new checkpoints. */
132
156
  private runningPromise: RunningPromise;
133
157
 
@@ -141,6 +165,9 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
141
165
  private initialSyncComplete: boolean = false;
142
166
  private initialSyncPromise: PromiseWithResolvers<void>;
143
167
 
168
+ /** Queue of blocks to be added to the store, processed by the sync loop. */
169
+ private blockQueue: AddBlockRequest[] = [];
170
+
144
171
  public readonly tracer: Tracer;
145
172
 
146
173
  /**
@@ -169,7 +196,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
169
196
  maxAllowedEthClientDriftSeconds: number;
170
197
  ethereumAllowNoDebugHosts?: boolean;
171
198
  },
172
- private readonly blobSinkClient: BlobSinkClientInterface,
199
+ private readonly blobClient: BlobClientInterface,
173
200
  private readonly epochCache: EpochCache,
174
201
  private readonly dateProvider: DateProvider,
175
202
  private readonly instrumentation: ArchiverInstrumentation,
@@ -211,7 +238,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
211
238
  const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
212
239
  const publicClient = createPublicClient({
213
240
  chain: chain.chainInfo,
214
- transport: fallback(config.l1RpcUrls.map(url => http(url))),
241
+ transport: fallback(config.l1RpcUrls.map(url => http(url, { batch: false }))),
215
242
  pollingInterval: config.viemPollingIntervalMS,
216
243
  });
217
244
 
@@ -219,7 +246,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
219
246
  const debugRpcUrls = config.l1DebugRpcUrls.length > 0 ? config.l1DebugRpcUrls : config.l1RpcUrls;
220
247
  const debugClient = createPublicClient({
221
248
  chain: chain.chainInfo,
222
- transport: fallback(debugRpcUrls.map(url => http(url))),
249
+ transport: fallback(debugRpcUrls.map(url => http(url, { batch: false }))),
223
250
  pollingInterval: config.viemPollingIntervalMS,
224
251
  }) as ViemPublicDebugClient;
225
252
 
@@ -248,7 +275,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
248
275
  slotDuration,
249
276
  ethereumSlotDuration,
250
277
  proofSubmissionEpochs: Number(proofSubmissionEpochs),
251
- genesisArchiveRoot: Fr.fromHexString(genesisArchiveRoot),
278
+ genesisArchiveRoot: Fr.fromString(genesisArchiveRoot.toString()),
252
279
  };
253
280
 
254
281
  const opts = merge(
@@ -270,7 +297,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
270
297
  { ...config.l1Contracts, slashingProposerAddress },
271
298
  archiverStore,
272
299
  opts,
273
- deps.blobSinkClient,
300
+ deps.blobClient,
274
301
  epochCache,
275
302
  deps.dateProvider ?? new DateProvider(),
276
303
  await ArchiverInstrumentation.new(telemetry, () => archiverStore.estimateSize()),
@@ -294,17 +321,17 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
294
321
  throw new Error('Archiver is already running');
295
322
  }
296
323
 
297
- await this.blobSinkClient.testSources();
324
+ await this.blobClient.testSources();
298
325
  await this.testEthereumNodeSynced();
299
326
  await validateAndLogTraceAvailability(this.debugClient, this.config.ethereumAllowNoDebugHosts ?? false);
300
327
 
301
328
  // Log initial state for the archiver
302
329
  const { l1StartBlock } = this.l1constants;
303
330
  const { blocksSynchedTo = l1StartBlock, messagesSynchedTo = l1StartBlock } = await this.store.getSynchPoint();
304
- const currentL2Block = await this.getBlockNumber();
331
+ const currentL2Checkpoint = await this.getSynchedCheckpointNumber();
305
332
  this.log.info(
306
- `Starting archiver sync to rollup contract ${this.l1Addresses.rollupAddress.toString()} from L1 block ${blocksSynchedTo} and L2 block ${currentL2Block}`,
307
- { blocksSynchedTo, messagesSynchedTo, currentL2Block },
333
+ `Starting archiver sync to rollup contract ${this.l1Addresses.rollupAddress.toString()} from L1 block ${blocksSynchedTo} and L2 checkpoint ${currentL2Checkpoint}`,
334
+ { blocksSynchedTo, messagesSynchedTo, currentL2Checkpoint },
308
335
  );
309
336
 
310
337
  // Start sync loop, and return the wait for initial sync if we are asked to block until synced
@@ -318,6 +345,51 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
318
345
  return this.runningPromise.trigger();
319
346
  }
320
347
 
348
+ /**
349
+ * Queues a block to be added to the archiver store and triggers processing.
350
+ * The block will be processed by the sync loop.
351
+ * Implements the L2BlockSink interface.
352
+ * @param block - The L2 block to add.
353
+ * @returns A promise that resolves when the block has been added to the store, or rejects on error.
354
+ */
355
+ public addBlock(block: L2BlockNew): Promise<void> {
356
+ return new Promise<void>((resolve, reject) => {
357
+ this.blockQueue.push({ block, resolve, reject });
358
+ this.log.debug(`Queued block ${block.number} for processing`);
359
+ // Trigger an immediate sync, but don't wait for it - the promise resolves when the block is processed
360
+ this.syncImmediate().catch(err => {
361
+ this.log.error(`Sync immediate call failed: ${err}`);
362
+ });
363
+ });
364
+ }
365
+
366
+ /**
367
+ * Processes all queued blocks, adding them to the store.
368
+ * Called at the beginning of each sync iteration.
369
+ * Blocks are processed in the order they were queued.
370
+ */
371
+ private async processQueuedBlocks(): Promise<void> {
372
+ if (this.blockQueue.length === 0) {
373
+ return;
374
+ }
375
+
376
+ // Take all blocks from the queue
377
+ const queuedItems = this.blockQueue.splice(0, this.blockQueue.length);
378
+ this.log.debug(`Processing ${queuedItems.length} queued block(s)`);
379
+
380
+ // Process each block individually to properly resolve/reject each promise
381
+ for (const { block, resolve, reject } of queuedItems) {
382
+ try {
383
+ await this.store.addBlocks([block]);
384
+ this.log.debug(`Added block ${block.number} to store`);
385
+ resolve();
386
+ } catch (err: any) {
387
+ this.log.error(`Failed to add block ${block.number} to store: ${err.message}`);
388
+ reject(err);
389
+ }
390
+ }
391
+ }
392
+
321
393
  public waitForInitialSync() {
322
394
  return this.initialSyncPromise.promise;
323
395
  }
@@ -337,11 +409,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
337
409
  }
338
410
  }
339
411
 
340
- /**
341
- * Fetches logs from L1 contracts and processes them.
342
- */
343
- @trackSpan('Archiver.sync')
344
- private async sync() {
412
+ private async syncFromL1() {
345
413
  /**
346
414
  * We keep track of three "pointers" to L1 blocks:
347
415
  * 1. the last L1 block that published an L2 block
@@ -427,7 +495,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
427
495
  // past it, since otherwise we'll keep downloading it and reprocessing it on every iteration until
428
496
  // we get a valid checkpoint to advance the syncpoint.
429
497
  if (!rollupStatus.validationResult?.valid && rollupStatus.lastL1BlockWithCheckpoint !== undefined) {
430
- await this.store.setBlockSynchedL1BlockNumber(rollupStatus.lastL1BlockWithCheckpoint);
498
+ await this.store.setCheckpointSynchedL1BlockNumber(rollupStatus.lastL1BlockWithCheckpoint);
431
499
  }
432
500
 
433
501
  // And lastly we check if we are missing any checkpoints behind us due to a possible L1 reorg.
@@ -461,6 +529,17 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
461
529
  }
462
530
  }
463
531
 
532
+ /**
533
+ * Fetches logs from L1 contracts and processes them.
534
+ */
535
+ @trackSpan('Archiver.sync')
536
+ private async sync() {
537
+ // Process any queued blocks first, before doing L1 sync
538
+ await this.processQueuedBlocks();
539
+ // Now perform L1 sync
540
+ await this.syncFromL1();
541
+ }
542
+
464
543
  /** Queries the rollup contract on whether a prune can be executed on the immediate next L1 block. */
465
544
  private async canPrune(currentL1BlockNumber: bigint, currentL1Timestamp: bigint) {
466
545
  const time = (currentL1Timestamp ?? 0n) + BigInt(this.l1constants.ethereumSlotDuration);
@@ -499,13 +578,26 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
499
578
 
500
579
  const checkpointsToUnwind = localPendingCheckpointNumber - provenCheckpointNumber;
501
580
 
502
- const checkpoints = await this.getCheckpoints(pruneFrom, checkpointsToUnwind);
581
+ const checkpointPromises = Array.from({ length: checkpointsToUnwind })
582
+ .fill(0)
583
+ .map((_, i) => this.store.getCheckpointData(CheckpointNumber(i + pruneFrom)));
584
+ const checkpoints = await Promise.all(checkpointPromises);
585
+
586
+ const blockPromises = await Promise.all(
587
+ checkpoints
588
+ .filter(isDefined)
589
+ .map(cp => this.store.getBlocksForCheckpoint(CheckpointNumber(cp.checkpointNumber))),
590
+ );
591
+ const newBlocks = blockPromises.filter(isDefined).flat();
592
+
593
+ // TODO(pw/mbps): Don't convert to legacy blocks here
594
+ const blocks: L2Block[] = (await Promise.all(newBlocks.map(x => this.getBlock(x.number)))).filter(isDefined);
503
595
 
504
596
  // Emit an event for listening services to react to the chain prune
505
597
  this.emit(L2BlockSourceEvents.L2PruneDetected, {
506
598
  type: L2BlockSourceEvents.L2PruneDetected,
507
599
  epochNumber: pruneFromEpochNumber,
508
- blocks: checkpoints.flatMap(c => L2Block.fromCheckpoint(c)),
600
+ blocks,
509
601
  });
510
602
 
511
603
  this.log.debug(
@@ -697,20 +789,18 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
697
789
  private async handleCheckpoints(blocksSynchedTo: bigint, currentL1BlockNumber: bigint): Promise<RollupStatus> {
698
790
  const localPendingCheckpointNumber = await this.getSynchedCheckpointNumber();
699
791
  const initialValidationResult: ValidateBlockResult | undefined = await this.store.getPendingChainValidationStatus();
700
- const [
701
- rollupProvenCheckpointNumber,
702
- provenArchive,
703
- rollupPendingCheckpointNumber,
704
- pendingArchive,
705
- archiveForLocalPendingCheckpointNumber,
706
- ] = await this.rollup.status(localPendingCheckpointNumber, { blockNumber: currentL1BlockNumber });
707
- const provenCheckpointNumber = CheckpointNumber.fromBigInt(rollupProvenCheckpointNumber);
708
- const pendingCheckpointNumber = CheckpointNumber.fromBigInt(rollupPendingCheckpointNumber);
709
- const rollupStatus = {
792
+ const {
710
793
  provenCheckpointNumber,
711
794
  provenArchive,
712
795
  pendingCheckpointNumber,
713
796
  pendingArchive,
797
+ archiveOfMyCheckpoint: archiveForLocalPendingCheckpointNumber,
798
+ } = await this.rollup.status(localPendingCheckpointNumber, { blockNumber: currentL1BlockNumber });
799
+ const rollupStatus: RollupStatus = {
800
+ provenCheckpointNumber,
801
+ provenArchive: provenArchive.toString(),
802
+ pendingCheckpointNumber,
803
+ pendingArchive: pendingArchive.toString(),
714
804
  validationResult: initialValidationResult,
715
805
  };
716
806
  this.log.trace(`Retrieved rollup status at current L1 block ${currentL1BlockNumber}.`, {
@@ -733,17 +823,18 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
733
823
  }
734
824
  }
735
825
 
736
- const localCheckpointForDestinationProvenCheckpointNumber = await this.getCheckpoint(provenCheckpointNumber);
826
+ const localCheckpointForDestinationProvenCheckpointNumber =
827
+ await this.store.getCheckpointData(provenCheckpointNumber);
737
828
 
738
829
  // Sanity check. I've hit what seems to be a state where the proven checkpoint is set to a value greater than the latest
739
830
  // synched checkpoint when requesting L2Tips from the archiver. This is the only place where the proven checkpoint is set.
740
831
  const synched = await this.getSynchedCheckpointNumber();
741
832
  if (
742
833
  localCheckpointForDestinationProvenCheckpointNumber &&
743
- synched < localCheckpointForDestinationProvenCheckpointNumber.number
834
+ synched < localCheckpointForDestinationProvenCheckpointNumber.checkpointNumber
744
835
  ) {
745
836
  this.log.error(
746
- `Hit local checkpoint greater than last synched checkpoint: ${localCheckpointForDestinationProvenCheckpointNumber.number} > ${synched}`,
837
+ `Hit local checkpoint greater than last synched checkpoint: ${localCheckpointForDestinationProvenCheckpointNumber.checkpointNumber} > ${synched}`,
747
838
  );
748
839
  }
749
840
 
@@ -753,38 +844,39 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
753
844
  }`,
754
845
  );
755
846
 
756
- const lastProvenBlockNumber = await this.getLastBlockNumberInCheckpoint(provenCheckpointNumber);
757
847
  if (
758
848
  localCheckpointForDestinationProvenCheckpointNumber &&
759
- provenArchive === localCheckpointForDestinationProvenCheckpointNumber.archive.root.toString()
849
+ provenArchive.equals(localCheckpointForDestinationProvenCheckpointNumber.archive.root)
760
850
  ) {
761
851
  const localProvenCheckpointNumber = await this.getProvenCheckpointNumber();
762
852
  if (localProvenCheckpointNumber !== provenCheckpointNumber) {
763
853
  await this.setProvenCheckpointNumber(provenCheckpointNumber);
764
- this.log.info(`Updated proven chain to checkpoint ${provenCheckpointNumber}`, {
765
- provenCheckpointNumber,
766
- });
854
+ this.log.info(`Updated proven chain to checkpoint ${provenCheckpointNumber}`, { provenCheckpointNumber });
767
855
  const provenSlotNumber = localCheckpointForDestinationProvenCheckpointNumber.header.slotNumber;
768
856
  const provenEpochNumber: EpochNumber = getEpochAtSlot(provenSlotNumber, this.l1constants);
857
+ const lastBlockNumberInCheckpoint =
858
+ localCheckpointForDestinationProvenCheckpointNumber.startBlock +
859
+ localCheckpointForDestinationProvenCheckpointNumber.numBlocks -
860
+ 1;
769
861
 
770
862
  this.emit(L2BlockSourceEvents.L2BlockProven, {
771
863
  type: L2BlockSourceEvents.L2BlockProven,
772
- blockNumber: lastProvenBlockNumber,
864
+ blockNumber: BlockNumber(lastBlockNumberInCheckpoint),
773
865
  slotNumber: provenSlotNumber,
774
866
  epochNumber: provenEpochNumber,
775
867
  });
868
+ this.instrumentation.updateLastProvenBlock(lastBlockNumberInCheckpoint);
776
869
  } else {
777
870
  this.log.trace(`Proven checkpoint ${provenCheckpointNumber} already stored.`);
778
871
  }
779
872
  }
780
- this.instrumentation.updateLastProvenBlock(lastProvenBlockNumber);
781
873
  };
782
874
 
783
875
  // This is an edge case that we only hit if there are no proposed checkpoints.
784
876
  // If we have 0 checkpoints locally and there are no checkpoints onchain there is nothing to do.
785
877
  const noCheckpoints = localPendingCheckpointNumber === 0 && pendingCheckpointNumber === 0;
786
878
  if (noCheckpoints) {
787
- await this.store.setBlockSynchedL1BlockNumber(currentL1BlockNumber);
879
+ await this.store.setCheckpointSynchedL1BlockNumber(currentL1BlockNumber);
788
880
  this.log.debug(
789
881
  `No checkpoints to retrieve from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}, no checkpoints on chain`,
790
882
  );
@@ -796,13 +888,13 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
796
888
  // Related to the L2 reorgs of the pending chain. We are only interested in actually addressing a reorg if there
797
889
  // are any state that could be impacted by it. If we have no checkpoints, there is no impact.
798
890
  if (localPendingCheckpointNumber > 0) {
799
- const localPendingCheckpoint = await this.getCheckpoint(localPendingCheckpointNumber);
891
+ const localPendingCheckpoint = await this.store.getCheckpointData(localPendingCheckpointNumber);
800
892
  if (localPendingCheckpoint === undefined) {
801
893
  throw new Error(`Missing checkpoint ${localPendingCheckpointNumber}`);
802
894
  }
803
895
 
804
896
  const localPendingArchiveRoot = localPendingCheckpoint.archive.root.toString();
805
- const noCheckpointSinceLast = localPendingCheckpoint && pendingArchive === localPendingArchiveRoot;
897
+ const noCheckpointSinceLast = localPendingCheckpoint && pendingArchive.toString() === localPendingArchiveRoot;
806
898
  if (noCheckpointSinceLast) {
807
899
  // We believe the following line causes a problem when we encounter L1 re-orgs.
808
900
  // Basically, by setting the synched L1 block number here, we are saying that we have
@@ -816,7 +908,9 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
816
908
  return rollupStatus;
817
909
  }
818
910
 
819
- const localPendingCheckpointInChain = archiveForLocalPendingCheckpointNumber === localPendingArchiveRoot;
911
+ const localPendingCheckpointInChain = archiveForLocalPendingCheckpointNumber.equals(
912
+ localPendingCheckpoint.archive.root,
913
+ );
820
914
  if (!localPendingCheckpointInChain) {
821
915
  // If our local pending checkpoint tip is not in the chain on L1 a "prune" must have happened
822
916
  // or the L1 have reorged.
@@ -829,20 +923,20 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
829
923
 
830
924
  let tipAfterUnwind = localPendingCheckpointNumber;
831
925
  while (true) {
832
- const candidateCheckpoint = await this.getCheckpoint(tipAfterUnwind);
926
+ const candidateCheckpoint = await this.store.getCheckpointData(tipAfterUnwind);
833
927
  if (candidateCheckpoint === undefined) {
834
928
  break;
835
929
  }
836
930
 
837
- const archiveAtContract = await this.rollup.archiveAt(candidateCheckpoint.number);
931
+ const archiveAtContract = await this.rollup.archiveAt(candidateCheckpoint.checkpointNumber);
838
932
  this.log.trace(
839
- `Checking local checkpoint ${candidateCheckpoint.number} with archive ${candidateCheckpoint.archive.root}`,
933
+ `Checking local checkpoint ${candidateCheckpoint.checkpointNumber} with archive ${candidateCheckpoint.archive.root}`,
840
934
  {
841
935
  archiveAtContract,
842
936
  archiveLocal: candidateCheckpoint.archive.root.toString(),
843
937
  },
844
938
  );
845
- if (archiveAtContract === candidateCheckpoint.archive.root.toString()) {
939
+ if (archiveAtContract.equals(candidateCheckpoint.archive.root)) {
846
940
  break;
847
941
  }
848
942
  tipAfterUnwind--;
@@ -871,17 +965,18 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
871
965
 
872
966
  this.log.trace(`Retrieving checkpoints from L1 block ${searchStartBlock} to ${searchEndBlock}`);
873
967
 
874
- // TODO(md): Retrieve from blob sink then from consensus client, then from peers
968
+ // TODO(md): Retrieve from blob client then from consensus client, then from peers
875
969
  const retrievedCheckpoints = await retrieveCheckpointsFromRollup(
876
970
  this.rollup.getContract() as GetContractReturnType<typeof RollupAbi, ViemPublicClient>,
877
971
  this.publicClient,
878
972
  this.debugClient,
879
- this.blobSinkClient,
973
+ this.blobClient,
880
974
  searchStartBlock, // TODO(palla/reorg): If the L2 reorg was due to an L1 reorg, we need to start search earlier
881
975
  searchEndBlock,
882
976
  this.l1Addresses,
883
977
  this.instrumentation,
884
978
  this.log,
979
+ !this.initialSyncComplete, // isHistoricalSync
885
980
  );
886
981
 
887
982
  if (retrievedCheckpoints.length === 0) {
@@ -981,19 +1076,18 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
981
1076
  validCheckpoints.flatMap(c => c.checkpoint.blocks),
982
1077
  );
983
1078
  } catch (err) {
984
- if (err instanceof InitialBlockNumberNotSequentialError) {
985
- const { previousBlockNumber, newBlockNumber } = err;
986
- const previousBlock = previousBlockNumber
987
- ? await this.store.getPublishedBlock(BlockNumber(previousBlockNumber))
1079
+ if (err instanceof InitialCheckpointNumberNotSequentialError) {
1080
+ const { previousCheckpointNumber, newCheckpointNumber } = err;
1081
+ const previousCheckpoint = previousCheckpointNumber
1082
+ ? await this.store.getCheckpointData(CheckpointNumber(previousCheckpointNumber))
988
1083
  : undefined;
989
- const updatedL1SyncPoint = previousBlock?.l1.blockNumber ?? this.l1constants.l1StartBlock;
1084
+ const updatedL1SyncPoint = previousCheckpoint?.l1.blockNumber ?? this.l1constants.l1StartBlock;
990
1085
  await this.store.setBlockSynchedL1BlockNumber(updatedL1SyncPoint);
991
1086
  this.log.warn(
992
- `Attempting to insert block ${newBlockNumber} with previous block ${previousBlockNumber}. Rolling back L1 sync point to ${updatedL1SyncPoint} to try and fetch the missing blocks.`,
1087
+ `Attempting to insert checkpoint ${newCheckpointNumber} with previous block ${previousCheckpointNumber}. Rolling back L1 sync point to ${updatedL1SyncPoint} to try and fetch the missing blocks.`,
993
1088
  {
994
- previousBlockNumber,
995
- previousBlockHash: await previousBlock?.block.hash(),
996
- newBlockNumber,
1089
+ previousCheckpointNumber,
1090
+ newCheckpointNumber,
997
1091
  updatedL1SyncPoint,
998
1092
  },
999
1093
  );
@@ -1038,13 +1132,16 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1038
1132
  // We suspect an L1 reorg that added checkpoints *behind* us. If that is the case, it must have happened between
1039
1133
  // the last checkpoint we saw and the current one, so we reset the last synched L1 block number. In the edge case
1040
1134
  // we don't have one, we go back 2 L1 epochs, which is the deepest possible reorg (assuming Casper is working).
1041
- const latestLocalCheckpoint =
1042
- lastRetrievedCheckpoint ??
1043
- (latestLocalCheckpointNumber > 0
1044
- ? await this.getPublishedCheckpoints(latestLocalCheckpointNumber, 1).then(([c]) => c)
1045
- : undefined);
1046
- const targetL1BlockNumber = latestLocalCheckpoint?.l1.blockNumber ?? maxBigint(currentL1BlockNumber - 64n, 0n);
1047
- const latestLocalCheckpointArchive = latestLocalCheckpoint?.checkpoint.archive.root.toString();
1135
+ let latestLocalCheckpointArchive: string | undefined = undefined;
1136
+ let targetL1BlockNumber = maxBigint(currentL1BlockNumber - 64n, 0n);
1137
+ if (lastRetrievedCheckpoint) {
1138
+ latestLocalCheckpointArchive = lastRetrievedCheckpoint.checkpoint.archive.root.toString();
1139
+ targetL1BlockNumber = lastRetrievedCheckpoint.l1.blockNumber;
1140
+ } else if (latestLocalCheckpointNumber > 0) {
1141
+ const checkpoint = await this.store.getRangeOfCheckpoints(latestLocalCheckpointNumber, 1).then(([c]) => c);
1142
+ latestLocalCheckpointArchive = checkpoint.archive.root.toString();
1143
+ targetL1BlockNumber = checkpoint.l1.blockNumber;
1144
+ }
1048
1145
  this.log.warn(
1049
1146
  `Failed to reach checkpoint ${pendingCheckpointNumber} at ${currentL1BlockNumber} (latest is ${latestLocalCheckpointNumber}). ` +
1050
1147
  `Rolling back last synched L1 block number to ${targetL1BlockNumber}.`,
@@ -1130,15 +1227,22 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1130
1227
  const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1constants);
1131
1228
  const blocks: L2Block[] = [];
1132
1229
 
1133
- // Walk the list of blocks backwards and filter by slots matching the requested epoch.
1134
- // We'll typically ask for blocks for a very recent epoch, so we shouldn't need an index here.
1135
- let block = await this.getBlock(await this.store.getSynchedL2BlockNumber());
1136
- const slot = (b: L2Block) => b.header.globalVariables.slotNumber;
1137
- while (block && slot(block) >= start) {
1138
- if (slot(block) <= end) {
1139
- blocks.push(block);
1230
+ // Walk the list of checkpoints backwards and filter by slots matching the requested epoch.
1231
+ // We'll typically ask for checkpoints for a very recent epoch, so we shouldn't need an index here.
1232
+ let checkpoint = await this.store.getCheckpointData(await this.store.getSynchedCheckpointNumber());
1233
+ const slot = (b: CheckpointData) => b.header.slotNumber;
1234
+ while (checkpoint && slot(checkpoint) >= start) {
1235
+ if (slot(checkpoint) <= end) {
1236
+ // push the blocks on backwards
1237
+ const endBlock = checkpoint.startBlock + checkpoint.numBlocks - 1;
1238
+ for (let i = endBlock; i >= checkpoint.startBlock; i--) {
1239
+ const block = await this.getBlock(BlockNumber(i));
1240
+ if (block) {
1241
+ blocks.push(block);
1242
+ }
1243
+ }
1140
1244
  }
1141
- block = await this.getBlock(BlockNumber(block.number - 1));
1245
+ checkpoint = await this.store.getCheckpointData(CheckpointNumber(checkpoint.checkpointNumber - 1));
1142
1246
  }
1143
1247
 
1144
1248
  return blocks.reverse();
@@ -1148,17 +1252,22 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1148
1252
  const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1constants);
1149
1253
  const blocks: BlockHeader[] = [];
1150
1254
 
1151
- // Walk the list of blocks backwards and filter by slots matching the requested epoch.
1152
- // We'll typically ask for blocks for a very recent epoch, so we shouldn't need an index here.
1153
- let number = await this.store.getSynchedL2BlockNumber();
1154
- let header = await this.getBlockHeader(number);
1155
- const slot = (b: BlockHeader) => b.globalVariables.slotNumber;
1156
- while (header && slot(header) >= start) {
1157
- if (slot(header) <= end) {
1158
- blocks.push(header);
1255
+ // Walk the list of checkpoints backwards and filter by slots matching the requested epoch.
1256
+ // We'll typically ask for checkpoints for a very recent epoch, so we shouldn't need an index here.
1257
+ let checkpoint = await this.store.getCheckpointData(await this.store.getSynchedCheckpointNumber());
1258
+ const slot = (b: CheckpointData) => b.header.slotNumber;
1259
+ while (checkpoint && slot(checkpoint) >= start) {
1260
+ if (slot(checkpoint) <= end) {
1261
+ // push the blocks on backwards
1262
+ const endBlock = checkpoint.startBlock + checkpoint.numBlocks - 1;
1263
+ for (let i = endBlock; i >= checkpoint.startBlock; i--) {
1264
+ const block = await this.getBlockHeader(BlockNumber(i));
1265
+ if (block) {
1266
+ blocks.push(block);
1267
+ }
1268
+ }
1159
1269
  }
1160
- number = BlockNumber(number - 1);
1161
- header = await this.getBlockHeader(number);
1270
+ checkpoint = await this.store.getCheckpointData(CheckpointNumber(checkpoint.checkpointNumber - 1));
1162
1271
  }
1163
1272
  return blocks.reverse();
1164
1273
  }
@@ -1196,37 +1305,6 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1196
1305
  return this.initialSyncComplete;
1197
1306
  }
1198
1307
 
1199
- public async getPublishedCheckpoints(
1200
- from: CheckpointNumber,
1201
- limit: number,
1202
- proven?: boolean,
1203
- ): Promise<PublishedCheckpoint[]> {
1204
- // TODO: Implement this properly. This only works when we have one block per checkpoint.
1205
- const blocks = await this.getPublishedBlocks(BlockNumber(from), limit, proven);
1206
- return blocks.map(b => b.toPublishedCheckpoint());
1207
- }
1208
-
1209
- public async getCheckpointByArchive(archive: Fr): Promise<Checkpoint | undefined> {
1210
- // TODO: Implement this properly. This only works when we have one block per checkpoint.
1211
- return (await this.getPublishedBlockByArchive(archive))?.block.toCheckpoint();
1212
- }
1213
-
1214
- public async getCheckpoints(from: CheckpointNumber, limit: number, proven?: boolean): Promise<Checkpoint[]> {
1215
- const published = await this.getPublishedCheckpoints(from, limit, proven);
1216
- return published.map(p => p.checkpoint);
1217
- }
1218
-
1219
- public async getCheckpoint(number: CheckpointNumber): Promise<Checkpoint | undefined> {
1220
- if (number < 0) {
1221
- number = await this.getSynchedCheckpointNumber();
1222
- }
1223
- if (number === 0) {
1224
- return undefined;
1225
- }
1226
- const published = await this.getPublishedCheckpoints(number, 1);
1227
- return published[0]?.checkpoint;
1228
- }
1229
-
1230
1308
  public async getCheckpointHeader(number: CheckpointNumber | 'latest'): Promise<CheckpointHeader | undefined> {
1231
1309
  if (number === 'latest') {
1232
1310
  number = await this.getSynchedCheckpointNumber();
@@ -1234,88 +1312,46 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1234
1312
  if (number === 0) {
1235
1313
  return undefined;
1236
1314
  }
1237
- const checkpoint = await this.getCheckpoint(number);
1238
- return checkpoint?.header;
1315
+ const checkpoint = await this.store.getCheckpointData(number);
1316
+ if (!checkpoint) {
1317
+ return undefined;
1318
+ }
1319
+ return checkpoint.header;
1239
1320
  }
1240
1321
 
1241
1322
  public getCheckpointNumber(): Promise<CheckpointNumber> {
1242
1323
  return this.getSynchedCheckpointNumber();
1243
1324
  }
1244
1325
 
1245
- public async getSynchedCheckpointNumber(): Promise<CheckpointNumber> {
1246
- // TODO: Create store and apis for checkpoints.
1247
- // Checkpoint number will no longer be the same as the block number once we support multiple blocks per checkpoint.
1248
- return CheckpointNumber(await this.store.getSynchedL2BlockNumber());
1326
+ public getSynchedCheckpointNumber(): Promise<CheckpointNumber> {
1327
+ return this.store.getSynchedCheckpointNumber();
1249
1328
  }
1250
1329
 
1251
- public async getProvenCheckpointNumber(): Promise<CheckpointNumber> {
1252
- // TODO: Create store and apis for checkpoints.
1253
- // Proven checkpoint number will no longer be the same as the proven block number once we support multiple blocks per checkpoint.
1254
- return CheckpointNumber(await this.store.getProvenL2BlockNumber());
1330
+ public getProvenCheckpointNumber(): Promise<CheckpointNumber> {
1331
+ return this.store.getProvenCheckpointNumber();
1255
1332
  }
1256
1333
 
1257
1334
  public setProvenCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
1258
- // TODO: Create store and apis for checkpoints.
1259
- // Proven checkpoint number will no longer be the same as the proven block number once we support multiple blocks per checkpoint.
1260
- return this.store.setProvenL2BlockNumber(BlockNumber.fromCheckpointNumber(checkpointNumber));
1335
+ return this.store.setProvenCheckpointNumber(checkpointNumber);
1261
1336
  }
1262
1337
 
1263
1338
  public unwindCheckpoints(from: CheckpointNumber, checkpointsToUnwind: number): Promise<boolean> {
1264
- // TODO: Create store and apis for checkpoints.
1265
- // This only works when we have one block per checkpoint.
1266
- return this.store.unwindBlocks(BlockNumber.fromCheckpointNumber(from), checkpointsToUnwind);
1339
+ return this.store.unwindCheckpoints(from, checkpointsToUnwind);
1267
1340
  }
1268
1341
 
1269
- public getLastBlockNumberInCheckpoint(checkpointNumber: CheckpointNumber): Promise<BlockNumber> {
1270
- // TODO: Create store and apis for checkpoints.
1271
- // Checkpoint number will no longer be the same as the block number once we support multiple blocks per checkpoint.
1272
- return Promise.resolve(BlockNumber.fromCheckpointNumber(checkpointNumber));
1342
+ public async getLastBlockNumberInCheckpoint(checkpointNumber: CheckpointNumber): Promise<BlockNumber | undefined> {
1343
+ const checkpointData = await this.store.getCheckpointData(checkpointNumber);
1344
+ if (!checkpointData) {
1345
+ return undefined;
1346
+ }
1347
+ return BlockNumber(checkpointData.startBlock + checkpointData.numBlocks - 1);
1273
1348
  }
1274
1349
 
1275
1350
  public addCheckpoints(
1276
1351
  checkpoints: PublishedCheckpoint[],
1277
1352
  pendingChainValidationStatus?: ValidateBlockResult,
1278
1353
  ): Promise<boolean> {
1279
- // TODO: Create store and apis for checkpoints.
1280
- // This only works when we have one block per checkpoint.
1281
- return this.store.addBlocks(
1282
- checkpoints.map(p => PublishedL2Block.fromPublishedCheckpoint(p)),
1283
- pendingChainValidationStatus,
1284
- );
1285
- }
1286
-
1287
- public async getCheckpointsForEpoch(epochNumber: EpochNumber): Promise<Checkpoint[]> {
1288
- // TODO: Create store and apis for checkpoints.
1289
- // This only works when we have one block per checkpoint.
1290
- const blocks = await this.getBlocksForEpoch(epochNumber);
1291
- return blocks.map(b => b.toCheckpoint());
1292
- }
1293
-
1294
- /**
1295
- * Gets up to `limit` amount of L2 blocks starting from `from`.
1296
- * @param from - Number of the first block to return (inclusive).
1297
- * @param limit - The number of blocks to return.
1298
- * @param proven - If true, only return blocks that have been proven.
1299
- * @returns The requested L2 blocks.
1300
- */
1301
- public getBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<L2Block[]> {
1302
- return this.getPublishedBlocks(from, limit, proven).then(blocks => blocks.map(b => b.block));
1303
- }
1304
-
1305
- /** Equivalent to getBlocks but includes publish data. */
1306
- public async getPublishedBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<PublishedL2Block[]> {
1307
- const limitWithProven = proven
1308
- ? Math.min(limit, Math.max((await this.store.getProvenL2BlockNumber()) - from + 1, 0))
1309
- : limit;
1310
- return limitWithProven === 0 ? [] : await this.store.getPublishedBlocks(from, limitWithProven);
1311
- }
1312
-
1313
- public getPublishedBlockByHash(blockHash: Fr): Promise<PublishedL2Block | undefined> {
1314
- return this.store.getPublishedBlockByHash(blockHash);
1315
- }
1316
-
1317
- public getPublishedBlockByArchive(archive: Fr): Promise<PublishedL2Block | undefined> {
1318
- return this.store.getPublishedBlockByArchive(archive);
1354
+ return this.store.addCheckpoints(checkpoints, pendingChainValidationStatus);
1319
1355
  }
1320
1356
 
1321
1357
  public getBlockHeaderByHash(blockHash: Fr): Promise<BlockHeader | undefined> {
@@ -1331,7 +1367,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1331
1367
  * @param number - The block number to return.
1332
1368
  * @returns The requested L2 block.
1333
1369
  */
1334
- public async getBlock(number: BlockNumber): Promise<L2Block | undefined> {
1370
+ public async getL2BlockNew(number: BlockNumber): Promise<L2BlockNew | undefined> {
1335
1371
  // If the number provided is -ve, then return the latest block.
1336
1372
  if (number < 0) {
1337
1373
  number = await this.store.getSynchedL2BlockNumber();
@@ -1339,8 +1375,8 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1339
1375
  if (number === 0) {
1340
1376
  return undefined;
1341
1377
  }
1342
- const publishedBlock = await this.store.getPublishedBlock(number);
1343
- return publishedBlock?.block;
1378
+ const publishedBlock = await this.store.store.getBlock(number);
1379
+ return publishedBlock;
1344
1380
  }
1345
1381
 
1346
1382
  public async getBlockHeader(number: BlockNumber | 'latest'): Promise<BlockHeader | undefined> {
@@ -1354,6 +1390,21 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1354
1390
  return headers.length === 0 ? undefined : headers[0];
1355
1391
  }
1356
1392
 
1393
+ getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
1394
+ return this.store.getCheckpointedBlock(number);
1395
+ }
1396
+
1397
+ getCheckpointedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
1398
+ return this.store.getCheckpointedBlockByHash(blockHash);
1399
+ }
1400
+
1401
+ getProvenBlockNumber(): Promise<BlockNumber> {
1402
+ return this.store.getProvenBlockNumber();
1403
+ }
1404
+ getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
1405
+ return this.store.getCheckpointedBlockByArchive(archive);
1406
+ }
1407
+
1357
1408
  public getTxEffect(txHash: TxHash) {
1358
1409
  return this.store.getTxEffect(txHash);
1359
1410
  }
@@ -1362,14 +1413,12 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1362
1413
  return this.store.getSettledTxReceipt(txHash);
1363
1414
  }
1364
1415
 
1365
- /**
1366
- * Gets all logs that match any of the received tags (i.e. logs with their first field equal to a tag).
1367
- * @param tags - The tags to filter the logs by.
1368
- * @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
1369
- * that tag.
1370
- */
1371
- getLogsByTags(tags: Fr[]): Promise<TxScopedL2Log[][]> {
1372
- return this.store.getLogsByTags(tags);
1416
+ getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
1417
+ return this.store.getPrivateLogsByTags(tags);
1418
+ }
1419
+
1420
+ getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
1421
+ return this.store.getPublicLogsByTagsFromContract(contractAddress, tags);
1373
1422
  }
1374
1423
 
1375
1424
  /**
@@ -1392,19 +1441,11 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1392
1441
 
1393
1442
  /**
1394
1443
  * Gets the number of the latest L2 block processed by the block source implementation.
1444
+ * This includes both checkpointed and uncheckpointed blocks.
1395
1445
  * @returns The number of the latest L2 block processed by the block source implementation.
1396
1446
  */
1397
1447
  public getBlockNumber(): Promise<BlockNumber> {
1398
- return this.store.getSynchedL2BlockNumber();
1399
- }
1400
-
1401
- public getProvenBlockNumber(): Promise<BlockNumber> {
1402
- return this.store.getProvenL2BlockNumber();
1403
- }
1404
-
1405
- /** Forcefully updates the last proven block number. Use for testing. */
1406
- public setProvenBlockNumber(blockNumber: BlockNumber): Promise<void> {
1407
- return this.store.setProvenL2BlockNumber(blockNumber);
1448
+ return this.store.getLatestBlockNumber();
1408
1449
  }
1409
1450
 
1410
1451
  public getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
@@ -1514,24 +1555,24 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1514
1555
  }
1515
1556
 
1516
1557
  public async rollbackTo(targetL2BlockNumber: BlockNumber): Promise<void> {
1558
+ // TODO(pw/mbps): This still assumes 1 block per checkpoint
1517
1559
  const currentBlocks = await this.getL2Tips();
1518
1560
  const currentL2Block = currentBlocks.latest.number;
1519
1561
  const currentProvenBlock = currentBlocks.proven.number;
1520
- // const currentFinalizedBlock = currentBlocks.finalized.number;
1521
1562
 
1522
1563
  if (targetL2BlockNumber >= currentL2Block) {
1523
1564
  throw new Error(`Target L2 block ${targetL2BlockNumber} must be less than current L2 block ${currentL2Block}`);
1524
1565
  }
1525
1566
  const blocksToUnwind = currentL2Block - targetL2BlockNumber;
1526
- const targetL2Block = await this.store.getPublishedBlock(targetL2BlockNumber);
1567
+ const targetL2Block = await this.store.getCheckpointedBlock(targetL2BlockNumber);
1527
1568
  if (!targetL2Block) {
1528
1569
  throw new Error(`Target L2 block ${targetL2BlockNumber} not found`);
1529
1570
  }
1530
1571
  const targetL1BlockNumber = targetL2Block.l1.blockNumber;
1531
1572
  const targetCheckpointNumber = CheckpointNumber.fromBlockNumber(targetL2BlockNumber);
1532
1573
  const targetL1BlockHash = await this.getL1BlockHash(targetL1BlockNumber);
1533
- this.log.info(`Unwinding ${blocksToUnwind} blocks from L2 block ${currentL2Block}`);
1534
- await this.store.unwindBlocks(BlockNumber(currentL2Block), blocksToUnwind);
1574
+ this.log.info(`Unwinding ${blocksToUnwind} checkpoints from L2 block ${currentL2Block}`);
1575
+ await this.store.unwindCheckpoints(CheckpointNumber(currentL2Block), blocksToUnwind);
1535
1576
  this.log.info(`Unwinding L1 to L2 messages to checkpoint ${targetCheckpointNumber}`);
1536
1577
  await this.store.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
1537
1578
  this.log.info(`Setting L1 syncpoints to ${targetL1BlockNumber}`);
@@ -1539,7 +1580,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1539
1580
  await this.store.setMessageSynchedL1Block({ l1BlockNumber: targetL1BlockNumber, l1BlockHash: targetL1BlockHash });
1540
1581
  if (targetL2BlockNumber < currentProvenBlock) {
1541
1582
  this.log.info(`Clearing proven L2 block number`);
1542
- await this.store.setProvenL2BlockNumber(BlockNumber.ZERO);
1583
+ await this.store.setProvenCheckpointNumber(CheckpointNumber.ZERO);
1543
1584
  }
1544
1585
  // TODO(palla/reorg): Set the finalized block when we add support for it.
1545
1586
  // if (targetL2BlockNumber < currentFinalizedBlock) {
@@ -1547,6 +1588,150 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
1547
1588
  // await this.store.setFinalizedL2BlockNumber(0);
1548
1589
  // }
1549
1590
  }
1591
+
1592
+ public async getPublishedCheckpoints(
1593
+ checkpointNumber: CheckpointNumber,
1594
+ limit: number,
1595
+ ): Promise<PublishedCheckpoint[]> {
1596
+ const checkpoints = await this.store.getRangeOfCheckpoints(checkpointNumber, limit);
1597
+ const blocks = (
1598
+ await Promise.all(checkpoints.map(ch => this.store.getBlocksForCheckpoint(ch.checkpointNumber)))
1599
+ ).filter(isDefined);
1600
+
1601
+ const fullCheckpoints: PublishedCheckpoint[] = [];
1602
+ for (let i = 0; i < checkpoints.length; i++) {
1603
+ const blocksForCheckpoint = blocks[i];
1604
+ const checkpoint = checkpoints[i];
1605
+ const fullCheckpoint = new Checkpoint(
1606
+ checkpoint.archive,
1607
+ checkpoint.header,
1608
+ blocksForCheckpoint,
1609
+ checkpoint.checkpointNumber,
1610
+ );
1611
+ const publishedCheckpoint = new PublishedCheckpoint(
1612
+ fullCheckpoint,
1613
+ checkpoint.l1,
1614
+ checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
1615
+ );
1616
+ fullCheckpoints.push(publishedCheckpoint);
1617
+ }
1618
+ return fullCheckpoints;
1619
+ }
1620
+
1621
+ public async getCheckpointsForEpoch(epochNumber: EpochNumber): Promise<Checkpoint[]> {
1622
+ const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1constants);
1623
+ const checkpoints: Checkpoint[] = [];
1624
+
1625
+ // Walk the list of checkpoints backwards and filter by slots matching the requested epoch.
1626
+ // We'll typically ask for checkpoints for a very recent epoch, so we shouldn't need an index here.
1627
+ let checkpointData = await this.store.getCheckpointData(await this.store.getSynchedCheckpointNumber());
1628
+ const slot = (b: CheckpointData) => b.header.slotNumber;
1629
+ while (checkpointData && slot(checkpointData) >= start) {
1630
+ if (slot(checkpointData) <= end) {
1631
+ // push the checkpoints on backwards
1632
+ const [checkpoint] = await this.getPublishedCheckpoints(checkpointData.checkpointNumber, 1);
1633
+ checkpoints.push(checkpoint.checkpoint);
1634
+ }
1635
+ checkpointData = await this.store.getCheckpointData(CheckpointNumber(checkpointData.checkpointNumber - 1));
1636
+ }
1637
+
1638
+ return checkpoints.reverse();
1639
+ }
1640
+
1641
+ /* Legacy APIs */
1642
+
1643
+ public async getPublishedBlockByHash(blockHash: Fr): Promise<PublishedL2Block | undefined> {
1644
+ const checkpointedBlock = await this.store.getCheckpointedBlockByHash(blockHash);
1645
+ return this.buildOldBlockFromCheckpointedBlock(checkpointedBlock);
1646
+ }
1647
+ public async getPublishedBlockByArchive(archive: Fr): Promise<PublishedL2Block | undefined> {
1648
+ const checkpointedBlock = await this.store.getCheckpointedBlockByArchive(archive);
1649
+ return this.buildOldBlockFromCheckpointedBlock(checkpointedBlock);
1650
+ }
1651
+
1652
+ /**
1653
+ * Gets up to `limit` amount of L2 blocks starting from `from`.
1654
+ * @param from - Number of the first block to return (inclusive).
1655
+ * @param limit - The number of blocks to return.
1656
+ * @param proven - If true, only return blocks that have been proven.
1657
+ * @returns The requested L2 blocks.
1658
+ */
1659
+ public async getBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<L2Block[]> {
1660
+ const publishedBlocks = await this.getPublishedBlocks(from, limit, proven);
1661
+ return publishedBlocks.map(x => x.block);
1662
+ }
1663
+
1664
+ public async getPublishedBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<PublishedL2Block[]> {
1665
+ const checkpoints = await this.store.getRangeOfCheckpoints(CheckpointNumber(from), limit);
1666
+ const provenCheckpointNumber = await this.getProvenCheckpointNumber();
1667
+ const blocks = (
1668
+ await Promise.all(checkpoints.map(ch => this.store.getBlocksForCheckpoint(ch.checkpointNumber)))
1669
+ ).filter(isDefined);
1670
+
1671
+ const olbBlocks: PublishedL2Block[] = [];
1672
+ for (let i = 0; i < checkpoints.length; i++) {
1673
+ const blockForCheckpoint = blocks[i][0];
1674
+ const checkpoint = checkpoints[i];
1675
+ if (checkpoint.checkpointNumber > provenCheckpointNumber && proven === true) {
1676
+ // this checkpointisn't proven and we only want proven
1677
+ continue;
1678
+ }
1679
+ const oldCheckpoint = new Checkpoint(
1680
+ blockForCheckpoint.archive,
1681
+ checkpoint.header,
1682
+ [blockForCheckpoint],
1683
+ checkpoint.checkpointNumber,
1684
+ );
1685
+ const oldBlock = L2Block.fromCheckpoint(oldCheckpoint);
1686
+ const publishedBlock = new PublishedL2Block(
1687
+ oldBlock,
1688
+ checkpoint.l1,
1689
+ checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
1690
+ );
1691
+ olbBlocks.push(publishedBlock);
1692
+ }
1693
+ return olbBlocks;
1694
+ }
1695
+
1696
+ private async buildOldBlockFromCheckpointedBlock(
1697
+ checkpointedBlock: CheckpointedL2Block | undefined,
1698
+ ): Promise<PublishedL2Block | undefined> {
1699
+ if (!checkpointedBlock) {
1700
+ return undefined;
1701
+ }
1702
+ const checkpoint = await this.store.getCheckpointData(checkpointedBlock.checkpointNumber);
1703
+ if (!checkpoint) {
1704
+ return checkpoint;
1705
+ }
1706
+ const fullCheckpoint = new Checkpoint(
1707
+ checkpointedBlock?.block.archive,
1708
+ checkpoint?.header,
1709
+ [checkpointedBlock.block],
1710
+ checkpoint.checkpointNumber,
1711
+ );
1712
+ const oldBlock = L2Block.fromCheckpoint(fullCheckpoint);
1713
+ const published = new PublishedL2Block(
1714
+ oldBlock,
1715
+ checkpoint.l1,
1716
+ checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
1717
+ );
1718
+ return published;
1719
+ }
1720
+
1721
+ public async getBlock(number: BlockNumber): Promise<L2Block | undefined> {
1722
+ // If the number provided is -ve, then return the latest block.
1723
+ if (number < 0) {
1724
+ number = await this.store.getSynchedL2BlockNumber();
1725
+ }
1726
+ if (number === 0) {
1727
+ return undefined;
1728
+ }
1729
+ const publishedBlocks = await this.getPublishedBlocks(number, 1);
1730
+ if (publishedBlocks.length === 0) {
1731
+ return undefined;
1732
+ }
1733
+ return publishedBlocks[0].block;
1734
+ }
1550
1735
  }
1551
1736
 
1552
1737
  enum Operation {
@@ -1577,11 +1762,13 @@ export class ArchiverStoreHelper
1577
1762
  | 'close'
1578
1763
  | 'transactionAsync'
1579
1764
  | 'addBlocks'
1765
+ | 'getBlock'
1766
+ | 'getBlocks'
1580
1767
  >
1581
1768
  {
1582
1769
  #log = createLogger('archiver:block-helper');
1583
1770
 
1584
- constructor(protected readonly store: ArchiverDataStore) {}
1771
+ constructor(public readonly store: ArchiverDataStore) {}
1585
1772
 
1586
1773
  /**
1587
1774
  * Extracts and stores contract classes out of ContractClassPublished events emitted by the class registry contract.
@@ -1719,7 +1906,23 @@ export class ArchiverStoreHelper
1719
1906
  return true;
1720
1907
  }
1721
1908
 
1722
- public addBlocks(blocks: PublishedL2Block[], pendingChainValidationStatus?: ValidateBlockResult): Promise<boolean> {
1909
+ private async addBlockDataToDB(block: L2BlockNew) {
1910
+ const contractClassLogs = block.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
1911
+ // ContractInstancePublished event logs are broadcast in privateLogs.
1912
+ const privateLogs = block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
1913
+ const publicLogs = block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
1914
+
1915
+ return (
1916
+ await Promise.all([
1917
+ this.#updatePublishedContractClasses(contractClassLogs, block.number, Operation.Store),
1918
+ this.#updateDeployedContractInstances(privateLogs, block.number, Operation.Store),
1919
+ this.#updateUpdatedContractInstances(publicLogs, block.header.globalVariables.timestamp, Operation.Store),
1920
+ this.#storeBroadcastedIndividualFunctions(contractClassLogs, block.number),
1921
+ ])
1922
+ ).every(Boolean);
1923
+ }
1924
+
1925
+ public addBlocks(blocks: L2BlockNew[], pendingChainValidationStatus?: ValidateBlockResult): Promise<boolean> {
1723
1926
  // Add the blocks to the store. Store will throw if the blocks are not in order, there are gaps,
1724
1927
  // or if the previous block is not in the store.
1725
1928
  return this.store.transactionAsync(async () => {
@@ -1729,25 +1932,10 @@ export class ArchiverStoreHelper
1729
1932
  // Update the pending chain validation status if provided
1730
1933
  pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
1731
1934
  // Add any logs emitted during the retrieved blocks
1732
- this.store.addLogs(blocks.map(block => block.block)),
1935
+ this.store.addLogs(blocks),
1733
1936
  // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
1734
- ...blocks.map(async block => {
1735
- const contractClassLogs = block.block.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
1736
- // ContractInstancePublished event logs are broadcast in privateLogs.
1737
- const privateLogs = block.block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
1738
- const publicLogs = block.block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
1739
- return (
1740
- await Promise.all([
1741
- this.#updatePublishedContractClasses(contractClassLogs, block.block.number, Operation.Store),
1742
- this.#updateDeployedContractInstances(privateLogs, block.block.number, Operation.Store),
1743
- this.#updateUpdatedContractInstances(
1744
- publicLogs,
1745
- block.block.header.globalVariables.timestamp,
1746
- Operation.Store,
1747
- ),
1748
- this.#storeBroadcastedIndividualFunctions(contractClassLogs, block.block.number),
1749
- ])
1750
- ).every(Boolean);
1937
+ ...blocks.map(block => {
1938
+ return this.addBlockDataToDB(block);
1751
1939
  }),
1752
1940
  ]);
1753
1941
 
@@ -1755,59 +1943,102 @@ export class ArchiverStoreHelper
1755
1943
  });
1756
1944
  }
1757
1945
 
1758
- public async unwindBlocks(from: BlockNumber, blocksToUnwind: number): Promise<boolean> {
1759
- const last = await this.getSynchedL2BlockNumber();
1760
- if (from != last) {
1761
- throw new Error(`Cannot unwind blocks from block ${from} when the last block is ${last}`);
1946
+ public addCheckpoints(
1947
+ checkpoints: PublishedCheckpoint[],
1948
+ pendingChainValidationStatus?: ValidateBlockResult,
1949
+ ): Promise<boolean> {
1950
+ // Add the blocks to the store. Store will throw if the blocks are not in order, there are gaps,
1951
+ // or if the previous block is not in the store.
1952
+ return this.store.transactionAsync(async () => {
1953
+ await this.store.addCheckpoints(checkpoints);
1954
+ const allBlocks = checkpoints.flatMap((ch: PublishedCheckpoint) => ch.checkpoint.blocks);
1955
+
1956
+ const opResults = await Promise.all([
1957
+ // Update the pending chain validation status if provided
1958
+ pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
1959
+ // Add any logs emitted during the retrieved blocks
1960
+ this.store.addLogs(allBlocks),
1961
+ // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
1962
+ ...allBlocks.map(block => {
1963
+ return this.addBlockDataToDB(block);
1964
+ }),
1965
+ ]);
1966
+
1967
+ return opResults.every(Boolean);
1968
+ });
1969
+ }
1970
+
1971
+ public async unwindCheckpoints(from: CheckpointNumber, checkpointsToUnwind: number): Promise<boolean> {
1972
+ if (checkpointsToUnwind <= 0) {
1973
+ throw new Error(`Cannot unwind ${checkpointsToUnwind} blocks`);
1762
1974
  }
1763
- if (blocksToUnwind <= 0) {
1764
- throw new Error(`Cannot unwind ${blocksToUnwind} blocks`);
1975
+
1976
+ const last = await this.getSynchedCheckpointNumber();
1977
+ if (from != last) {
1978
+ throw new Error(`Cannot unwind checkpoints from checkpoint ${from} when the last checkpoint is ${last}`);
1765
1979
  }
1766
1980
 
1767
- // from - blocksToUnwind = the new head, so + 1 for what we need to remove
1768
- const blocks = await this.getPublishedBlocks(BlockNumber(from - blocksToUnwind + 1), blocksToUnwind);
1981
+ const blocks = [];
1982
+ const lastCheckpointNumber = from + checkpointsToUnwind - 1;
1983
+ for (let checkpointNumber = from; checkpointNumber <= lastCheckpointNumber; checkpointNumber++) {
1984
+ const blocksForCheckpoint = await this.store.getBlocksForCheckpoint(checkpointNumber);
1985
+ if (!blocksForCheckpoint) {
1986
+ continue;
1987
+ }
1988
+ blocks.push(...blocksForCheckpoint);
1989
+ }
1769
1990
 
1770
1991
  const opResults = await Promise.all([
1771
1992
  // Prune rolls back to the last proven block, which is by definition valid
1772
1993
  this.store.setPendingChainValidationStatus({ valid: true }),
1773
1994
  // Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
1774
1995
  ...blocks.map(async block => {
1775
- const contractClassLogs = block.block.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
1996
+ const contractClassLogs = block.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
1776
1997
  // ContractInstancePublished event logs are broadcast in privateLogs.
1777
- const privateLogs = block.block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
1778
- const publicLogs = block.block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
1998
+ const privateLogs = block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
1999
+ const publicLogs = block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
1779
2000
 
1780
2001
  return (
1781
2002
  await Promise.all([
1782
- this.#updatePublishedContractClasses(contractClassLogs, block.block.number, Operation.Delete),
1783
- this.#updateDeployedContractInstances(privateLogs, block.block.number, Operation.Delete),
1784
- this.#updateUpdatedContractInstances(
1785
- publicLogs,
1786
- block.block.header.globalVariables.timestamp,
1787
- Operation.Delete,
1788
- ),
2003
+ this.#updatePublishedContractClasses(contractClassLogs, block.number, Operation.Delete),
2004
+ this.#updateDeployedContractInstances(privateLogs, block.number, Operation.Delete),
2005
+ this.#updateUpdatedContractInstances(publicLogs, block.header.globalVariables.timestamp, Operation.Delete),
1789
2006
  ])
1790
2007
  ).every(Boolean);
1791
2008
  }),
1792
2009
 
1793
- this.store.deleteLogs(blocks.map(b => b.block)),
1794
- this.store.unwindBlocks(from, blocksToUnwind),
2010
+ this.store.deleteLogs(blocks),
2011
+ this.store.unwindCheckpoints(from, checkpointsToUnwind),
1795
2012
  ]);
1796
2013
 
1797
2014
  return opResults.every(Boolean);
1798
2015
  }
1799
2016
 
1800
- getPublishedBlocks(from: BlockNumber, limit: number): Promise<PublishedL2Block[]> {
1801
- return this.store.getPublishedBlocks(from, limit);
2017
+ getCheckpointData(checkpointNumber: CheckpointNumber): Promise<CheckpointData | undefined> {
2018
+ return this.store.getCheckpointData(checkpointNumber);
1802
2019
  }
1803
- getPublishedBlock(number: BlockNumber): Promise<PublishedL2Block | undefined> {
1804
- return this.store.getPublishedBlock(number);
2020
+
2021
+ getRangeOfCheckpoints(from: CheckpointNumber, limit: number): Promise<CheckpointData[]> {
2022
+ return this.store.getRangeOfCheckpoints(from, limit);
2023
+ }
2024
+
2025
+ getCheckpointedL2BlockNumber(): Promise<BlockNumber> {
2026
+ return this.store.getCheckpointedL2BlockNumber();
2027
+ }
2028
+ getSynchedCheckpointNumber(): Promise<CheckpointNumber> {
2029
+ return this.store.getSynchedCheckpointNumber();
2030
+ }
2031
+ setCheckpointSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<void> {
2032
+ return this.store.setCheckpointSynchedL1BlockNumber(l1BlockNumber);
2033
+ }
2034
+ getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
2035
+ return this.store.getCheckpointedBlock(number);
1805
2036
  }
1806
- getPublishedBlockByHash(blockHash: Fr): Promise<PublishedL2Block | undefined> {
1807
- return this.store.getPublishedBlockByHash(blockHash);
2037
+ getCheckpointedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
2038
+ return this.store.getCheckpointedBlockByHash(blockHash);
1808
2039
  }
1809
- getPublishedBlockByArchive(archive: Fr): Promise<PublishedL2Block | undefined> {
1810
- return this.store.getPublishedBlockByArchive(archive);
2040
+ getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
2041
+ return this.store.getCheckpointedBlockByArchive(archive);
1811
2042
  }
1812
2043
  getBlockHeaders(from: BlockNumber, limit: number): Promise<BlockHeader[]> {
1813
2044
  return this.store.getBlockHeaders(from, limit);
@@ -1818,6 +2049,18 @@ export class ArchiverStoreHelper
1818
2049
  getBlockHeaderByArchive(archive: Fr): Promise<BlockHeader | undefined> {
1819
2050
  return this.store.getBlockHeaderByArchive(archive);
1820
2051
  }
2052
+ getBlockByHash(blockHash: Fr): Promise<L2BlockNew | undefined> {
2053
+ return this.store.getBlockByHash(blockHash);
2054
+ }
2055
+ getBlockByArchive(archive: Fr): Promise<L2BlockNew | undefined> {
2056
+ return this.store.getBlockByArchive(archive);
2057
+ }
2058
+ getLatestBlockNumber(): Promise<BlockNumber> {
2059
+ return this.store.getLatestBlockNumber();
2060
+ }
2061
+ getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<L2BlockNew[] | undefined> {
2062
+ return this.store.getBlocksForCheckpoint(checkpointNumber);
2063
+ }
1821
2064
  getTxEffect(txHash: TxHash): Promise<IndexedTxEffect | undefined> {
1822
2065
  return this.store.getTxEffect(txHash);
1823
2066
  }
@@ -1833,8 +2076,11 @@ export class ArchiverStoreHelper
1833
2076
  getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
1834
2077
  return this.store.getL1ToL2MessageIndex(l1ToL2Message);
1835
2078
  }
1836
- getLogsByTags(tags: Fr[], logsPerTag?: number): Promise<TxScopedL2Log[][]> {
1837
- return this.store.getLogsByTags(tags, logsPerTag);
2079
+ getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
2080
+ return this.store.getPrivateLogsByTags(tags);
2081
+ }
2082
+ getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
2083
+ return this.store.getPublicLogsByTagsFromContract(contractAddress, tags);
1838
2084
  }
1839
2085
  getPublicLogs(filter: LogFilter): Promise<GetPublicLogsResponse> {
1840
2086
  return this.store.getPublicLogs(filter);
@@ -1843,16 +2089,19 @@ export class ArchiverStoreHelper
1843
2089
  return this.store.getContractClassLogs(filter);
1844
2090
  }
1845
2091
  getSynchedL2BlockNumber(): Promise<BlockNumber> {
1846
- return this.store.getSynchedL2BlockNumber();
2092
+ return this.store.getCheckpointedL2BlockNumber();
2093
+ }
2094
+ getProvenCheckpointNumber(): Promise<CheckpointNumber> {
2095
+ return this.store.getProvenCheckpointNumber();
1847
2096
  }
1848
- getProvenL2BlockNumber(): Promise<BlockNumber> {
1849
- return this.store.getProvenL2BlockNumber();
2097
+ getProvenBlockNumber(): Promise<BlockNumber> {
2098
+ return this.store.getProvenBlockNumber();
1850
2099
  }
1851
- setProvenL2BlockNumber(l2BlockNumber: BlockNumber): Promise<void> {
1852
- return this.store.setProvenL2BlockNumber(l2BlockNumber);
2100
+ setProvenCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
2101
+ return this.store.setProvenCheckpointNumber(checkpointNumber);
1853
2102
  }
1854
2103
  setBlockSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<void> {
1855
- return this.store.setBlockSynchedL1BlockNumber(l1BlockNumber);
2104
+ return this.store.setCheckpointSynchedL1BlockNumber(l1BlockNumber);
1856
2105
  }
1857
2106
  setMessageSynchedL1Block(l1Block: L1BlockId): Promise<void> {
1858
2107
  return this.store.setMessageSynchedL1Block(l1Block);