@aztec/archiver 0.0.1-commit.b468ad8 → 0.0.1-commit.b64cb54f6

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 (86) hide show
  1. package/dest/archiver.d.ts +7 -4
  2. package/dest/archiver.d.ts.map +1 -1
  3. package/dest/archiver.js +62 -110
  4. package/dest/errors.d.ts +7 -9
  5. package/dest/errors.d.ts.map +1 -1
  6. package/dest/errors.js +9 -14
  7. package/dest/factory.d.ts +3 -4
  8. package/dest/factory.d.ts.map +1 -1
  9. package/dest/factory.js +15 -13
  10. package/dest/index.d.ts +2 -1
  11. package/dest/index.d.ts.map +1 -1
  12. package/dest/index.js +1 -0
  13. package/dest/l1/bin/retrieve-calldata.js +36 -33
  14. package/dest/l1/calldata_retriever.d.ts +73 -50
  15. package/dest/l1/calldata_retriever.d.ts.map +1 -1
  16. package/dest/l1/calldata_retriever.js +190 -259
  17. package/dest/l1/data_retrieval.d.ts +9 -9
  18. package/dest/l1/data_retrieval.d.ts.map +1 -1
  19. package/dest/l1/data_retrieval.js +21 -19
  20. package/dest/l1/spire_proposer.d.ts +5 -5
  21. package/dest/l1/spire_proposer.d.ts.map +1 -1
  22. package/dest/l1/spire_proposer.js +9 -17
  23. package/dest/modules/data_source_base.d.ts +10 -5
  24. package/dest/modules/data_source_base.d.ts.map +1 -1
  25. package/dest/modules/data_source_base.js +29 -73
  26. package/dest/modules/data_store_updater.d.ts +22 -7
  27. package/dest/modules/data_store_updater.d.ts.map +1 -1
  28. package/dest/modules/data_store_updater.js +69 -29
  29. package/dest/modules/instrumentation.d.ts +15 -2
  30. package/dest/modules/instrumentation.d.ts.map +1 -1
  31. package/dest/modules/instrumentation.js +19 -2
  32. package/dest/modules/l1_synchronizer.d.ts +5 -8
  33. package/dest/modules/l1_synchronizer.d.ts.map +1 -1
  34. package/dest/modules/l1_synchronizer.js +41 -10
  35. package/dest/store/block_store.d.ts +29 -26
  36. package/dest/store/block_store.d.ts.map +1 -1
  37. package/dest/store/block_store.js +130 -78
  38. package/dest/store/kv_archiver_store.d.ts +34 -11
  39. package/dest/store/kv_archiver_store.d.ts.map +1 -1
  40. package/dest/store/kv_archiver_store.js +39 -9
  41. package/dest/store/l2_tips_cache.d.ts +19 -0
  42. package/dest/store/l2_tips_cache.d.ts.map +1 -0
  43. package/dest/store/l2_tips_cache.js +89 -0
  44. package/dest/store/log_store.d.ts +1 -1
  45. package/dest/store/log_store.d.ts.map +1 -1
  46. package/dest/store/log_store.js +55 -35
  47. package/dest/store/message_store.js +1 -1
  48. package/dest/test/fake_l1_state.d.ts +13 -1
  49. package/dest/test/fake_l1_state.d.ts.map +1 -1
  50. package/dest/test/fake_l1_state.js +84 -20
  51. package/dest/test/mock_archiver.d.ts +1 -1
  52. package/dest/test/mock_archiver.d.ts.map +1 -1
  53. package/dest/test/mock_archiver.js +3 -2
  54. package/dest/test/mock_l2_block_source.d.ts +21 -5
  55. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  56. package/dest/test/mock_l2_block_source.js +132 -86
  57. package/dest/test/mock_structs.d.ts +4 -1
  58. package/dest/test/mock_structs.d.ts.map +1 -1
  59. package/dest/test/mock_structs.js +13 -1
  60. package/dest/test/noop_l1_archiver.d.ts +4 -1
  61. package/dest/test/noop_l1_archiver.d.ts.map +1 -1
  62. package/dest/test/noop_l1_archiver.js +5 -1
  63. package/package.json +13 -13
  64. package/src/archiver.ts +74 -130
  65. package/src/errors.ts +10 -24
  66. package/src/factory.ts +29 -14
  67. package/src/index.ts +1 -0
  68. package/src/l1/README.md +25 -68
  69. package/src/l1/bin/retrieve-calldata.ts +46 -39
  70. package/src/l1/calldata_retriever.ts +249 -379
  71. package/src/l1/data_retrieval.ts +23 -25
  72. package/src/l1/spire_proposer.ts +7 -15
  73. package/src/modules/data_source_base.ts +56 -95
  74. package/src/modules/data_store_updater.ts +71 -30
  75. package/src/modules/instrumentation.ts +29 -2
  76. package/src/modules/l1_synchronizer.ts +46 -14
  77. package/src/store/block_store.ts +157 -105
  78. package/src/store/kv_archiver_store.ts +62 -12
  79. package/src/store/l2_tips_cache.ts +89 -0
  80. package/src/store/log_store.ts +93 -31
  81. package/src/store/message_store.ts +1 -1
  82. package/src/test/fake_l1_state.ts +110 -21
  83. package/src/test/mock_archiver.ts +3 -2
  84. package/src/test/mock_l2_block_source.ts +173 -81
  85. package/src/test/mock_structs.ts +20 -6
  86. package/src/test/noop_l1_archiver.ts +7 -1
@@ -1,5 +1,9 @@
1
+ import type { SlotNumber } from '@aztec/foundation/branded-types';
1
2
  import { createLogger } from '@aztec/foundation/log';
2
3
  import type { L2Block } from '@aztec/stdlib/block';
4
+ import type { CheckpointData } from '@aztec/stdlib/checkpoint';
5
+ import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
6
+ import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
3
7
  import {
4
8
  Attributes,
5
9
  type Gauge,
@@ -17,6 +21,7 @@ export class ArchiverInstrumentation {
17
21
  public readonly tracer: Tracer;
18
22
 
19
23
  private blockHeight: Gauge;
24
+ private checkpointHeight: Gauge;
20
25
  private txCount: UpDownCounter;
21
26
  private l1BlockHeight: Gauge;
22
27
  private proofsSubmittedDelay: Histogram;
@@ -36,6 +41,8 @@ export class ArchiverInstrumentation {
36
41
 
37
42
  private blockProposalTxTargetCount: UpDownCounter;
38
43
 
44
+ private checkpointL1InclusionDelay: Histogram;
45
+
39
46
  private log = createLogger('archiver:instrumentation');
40
47
 
41
48
  private constructor(
@@ -47,6 +54,8 @@ export class ArchiverInstrumentation {
47
54
 
48
55
  this.blockHeight = meter.createGauge(Metrics.ARCHIVER_BLOCK_HEIGHT);
49
56
 
57
+ this.checkpointHeight = meter.createGauge(Metrics.ARCHIVER_CHECKPOINT_HEIGHT);
58
+
50
59
  this.l1BlockHeight = meter.createGauge(Metrics.ARCHIVER_L1_BLOCK_HEIGHT);
51
60
 
52
61
  this.txCount = createUpDownCounterWithDefault(meter, Metrics.ARCHIVER_TOTAL_TXS);
@@ -81,6 +90,8 @@ export class ArchiverInstrumentation {
81
90
  },
82
91
  );
83
92
 
93
+ this.checkpointL1InclusionDelay = meter.createHistogram(Metrics.ARCHIVER_CHECKPOINT_L1_INCLUSION_DELAY);
94
+
84
95
  this.dbMetrics = new LmdbMetrics(
85
96
  meter,
86
97
  {
@@ -105,6 +116,7 @@ export class ArchiverInstrumentation {
105
116
  public processNewBlocks(syncTimePerBlock: number, blocks: L2Block[]) {
106
117
  this.syncDurationPerBlock.record(Math.ceil(syncTimePerBlock));
107
118
  this.blockHeight.record(Math.max(...blocks.map(b => b.number)));
119
+ this.checkpointHeight.record(Math.max(...blocks.map(b => b.checkpointNumber)));
108
120
  this.syncBlockCount.add(blocks.length);
109
121
 
110
122
  for (const block of blocks) {
@@ -127,8 +139,10 @@ export class ArchiverInstrumentation {
127
139
  this.pruneDuration.record(Math.ceil(duration));
128
140
  }
129
141
 
130
- public updateLastProvenBlock(blockNumber: number) {
131
- this.blockHeight.record(blockNumber, { [Attributes.STATUS]: 'proven' });
142
+ public updateLastProvenCheckpoint(checkpoint: CheckpointData) {
143
+ const lastBlockNumberInCheckpoint = checkpoint.startBlock + checkpoint.blockCount - 1;
144
+ this.blockHeight.record(lastBlockNumberInCheckpoint, { [Attributes.STATUS]: 'proven' });
145
+ this.checkpointHeight.record(checkpoint.checkpointNumber, { [Attributes.STATUS]: 'proven' });
132
146
  }
133
147
 
134
148
  public processProofsVerified(logs: { proverId: string; l2BlockNumber: bigint; delay: bigint }[]) {
@@ -154,4 +168,17 @@ export class ArchiverInstrumentation {
154
168
  [Attributes.L1_BLOCK_PROPOSAL_USED_TRACE]: usedTrace,
155
169
  });
156
170
  }
171
+
172
+ /**
173
+ * Records L1 inclusion timing for a checkpoint observed on L1 (seconds into the L2 slot).
174
+ */
175
+ public processCheckpointL1Timing(data: {
176
+ slotNumber: SlotNumber;
177
+ l1Timestamp: bigint;
178
+ l1Constants: Pick<L1RollupConstants, 'l1GenesisTime' | 'slotDuration'>;
179
+ }): void {
180
+ const slotStartTs = getTimestampForSlot(data.slotNumber, data.l1Constants);
181
+ const inclusionDelaySeconds = Number(data.l1Timestamp - slotStartTs);
182
+ this.checkpointL1InclusionDelay.record(inclusionDelaySeconds);
183
+ }
157
184
  }
@@ -1,7 +1,6 @@
1
1
  import type { BlobClientInterface } from '@aztec/blob-client/client';
2
2
  import { EpochCache } from '@aztec/epoch-cache';
3
3
  import { InboxContract, RollupContract } from '@aztec/ethereum/contracts';
4
- import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
5
4
  import type { L1BlockId } from '@aztec/ethereum/l1-types';
6
5
  import type { ViemPublicClient, ViemPublicDebugClient } from '@aztec/ethereum/types';
7
6
  import { maxBigint } from '@aztec/foundation/bigint';
@@ -9,7 +8,6 @@ import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/br
9
8
  import { Buffer32 } from '@aztec/foundation/buffer';
10
9
  import { pick } from '@aztec/foundation/collection';
11
10
  import { Fr } from '@aztec/foundation/curves/bn254';
12
- import { EthAddress } from '@aztec/foundation/eth-address';
13
11
  import { type Logger, createLogger } from '@aztec/foundation/log';
14
12
  import { count } from '@aztec/foundation/string';
15
13
  import { DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
@@ -28,6 +26,7 @@ import {
28
26
  retrievedToPublishedCheckpoint,
29
27
  } from '../l1/data_retrieval.js';
30
28
  import type { KVArchiverDataStore } from '../store/kv_archiver_store.js';
29
+ import type { L2TipsCache } from '../store/l2_tips_cache.js';
31
30
  import type { InboxMessage } from '../structs/inbox_message.js';
32
31
  import { ArchiverDataStoreUpdater } from './data_store_updater.js';
33
32
  import type { ArchiverInstrumentation } from './instrumentation.js';
@@ -60,10 +59,6 @@ export class ArchiverL1Synchronizer implements Traceable {
60
59
  private readonly debugClient: ViemPublicDebugClient,
61
60
  private readonly rollup: RollupContract,
62
61
  private readonly inbox: InboxContract,
63
- private readonly l1Addresses: Pick<
64
- L1ContractAddresses,
65
- 'registryAddress' | 'governanceProposerAddress' | 'slashFactoryAddress'
66
- > & { slashingProposerAddress: EthAddress },
67
62
  private readonly store: KVArchiverDataStore,
68
63
  private config: {
69
64
  batchSize: number;
@@ -74,12 +69,18 @@ export class ArchiverL1Synchronizer implements Traceable {
74
69
  private readonly epochCache: EpochCache,
75
70
  private readonly dateProvider: DateProvider,
76
71
  private readonly instrumentation: ArchiverInstrumentation,
77
- private readonly l1Constants: L1RollupConstants & { l1StartBlockHash: Buffer32; genesisArchiveRoot: Fr },
72
+ private readonly l1Constants: L1RollupConstants & {
73
+ l1StartBlockHash: Buffer32;
74
+ genesisArchiveRoot: Fr;
75
+ },
78
76
  private readonly events: ArchiverEmitter,
79
77
  tracer: Tracer,
78
+ l2TipsCache?: L2TipsCache,
80
79
  private readonly log: Logger = createLogger('archiver:l1-sync'),
81
80
  ) {
82
- this.updater = new ArchiverDataStoreUpdater(this.store);
81
+ this.updater = new ArchiverDataStoreUpdater(this.store, l2TipsCache, {
82
+ rollupManaLimit: l1Constants.rollupManaLimit,
83
+ });
83
84
  this.tracer = tracer;
84
85
  }
85
86
 
@@ -215,6 +216,9 @@ export class ArchiverL1Synchronizer implements Traceable {
215
216
  this.instrumentation.updateL1BlockHeight(currentL1BlockNumber);
216
217
  }
217
218
 
219
+ // Update the finalized L2 checkpoint based on L1 finality.
220
+ await this.updateFinalizedCheckpoint();
221
+
218
222
  // After syncing has completed, update the current l1 block number and timestamp,
219
223
  // otherwise we risk announcing to the world that we've synced to a given point,
220
224
  // but the corresponding blocks have not been processed (see #12631).
@@ -230,6 +234,27 @@ export class ArchiverL1Synchronizer implements Traceable {
230
234
  });
231
235
  }
232
236
 
237
+ /** Query L1 for its finalized block and update the finalized checkpoint accordingly. */
238
+ private async updateFinalizedCheckpoint(): Promise<void> {
239
+ try {
240
+ const finalizedL1Block = await this.publicClient.getBlock({ blockTag: 'finalized', includeTransactions: false });
241
+ const finalizedL1BlockNumber = finalizedL1Block.number;
242
+ const finalizedCheckpointNumber = await this.rollup.getProvenCheckpointNumber({
243
+ blockNumber: finalizedL1BlockNumber,
244
+ });
245
+ const localFinalizedCheckpointNumber = await this.store.getFinalizedCheckpointNumber();
246
+ if (localFinalizedCheckpointNumber !== finalizedCheckpointNumber) {
247
+ await this.updater.setFinalizedCheckpointNumber(finalizedCheckpointNumber);
248
+ this.log.info(`Updated finalized chain to checkpoint ${finalizedCheckpointNumber}`, {
249
+ finalizedCheckpointNumber,
250
+ finalizedL1BlockNumber,
251
+ });
252
+ }
253
+ } catch (err) {
254
+ this.log.warn(`Failed to update finalized checkpoint: ${err}`);
255
+ }
256
+ }
257
+
233
258
  /** Prune all proposed local blocks that should have been checkpointed by now. */
234
259
  private async pruneUncheckpointedBlocks(currentL1Timestamp: bigint) {
235
260
  const [lastCheckpointedBlockNumber, lastProposedBlockNumber] = await Promise.all([
@@ -550,7 +575,7 @@ export class ArchiverL1Synchronizer implements Traceable {
550
575
  if (provenCheckpointNumber === 0) {
551
576
  const localProvenCheckpointNumber = await this.store.getProvenCheckpointNumber();
552
577
  if (localProvenCheckpointNumber !== provenCheckpointNumber) {
553
- await this.store.setProvenCheckpointNumber(provenCheckpointNumber);
578
+ await this.updater.setProvenCheckpointNumber(provenCheckpointNumber);
554
579
  this.log.info(`Rolled back proven chain to checkpoint ${provenCheckpointNumber}`, { provenCheckpointNumber });
555
580
  }
556
581
  }
@@ -582,13 +607,13 @@ export class ArchiverL1Synchronizer implements Traceable {
582
607
  ) {
583
608
  const localProvenCheckpointNumber = await this.store.getProvenCheckpointNumber();
584
609
  if (localProvenCheckpointNumber !== provenCheckpointNumber) {
585
- await this.store.setProvenCheckpointNumber(provenCheckpointNumber);
610
+ await this.updater.setProvenCheckpointNumber(provenCheckpointNumber);
586
611
  this.log.info(`Updated proven chain to checkpoint ${provenCheckpointNumber}`, { provenCheckpointNumber });
587
612
  const provenSlotNumber = localCheckpointForDestinationProvenCheckpointNumber.header.slotNumber;
588
613
  const provenEpochNumber: EpochNumber = getEpochAtSlot(provenSlotNumber, this.l1Constants);
589
614
  const lastBlockNumberInCheckpoint =
590
615
  localCheckpointForDestinationProvenCheckpointNumber.startBlock +
591
- localCheckpointForDestinationProvenCheckpointNumber.numBlocks -
616
+ localCheckpointForDestinationProvenCheckpointNumber.blockCount -
592
617
  1;
593
618
 
594
619
  this.events.emit(L2BlockSourceEvents.L2BlockProven, {
@@ -597,7 +622,7 @@ export class ArchiverL1Synchronizer implements Traceable {
597
622
  slotNumber: provenSlotNumber,
598
623
  epochNumber: provenEpochNumber,
599
624
  });
600
- this.instrumentation.updateLastProvenBlock(lastBlockNumberInCheckpoint);
625
+ this.instrumentation.updateLastProvenCheckpoint(localCheckpointForDestinationProvenCheckpointNumber);
601
626
  } else {
602
627
  this.log.trace(`Proven checkpoint ${provenCheckpointNumber} already stored.`);
603
628
  }
@@ -706,7 +731,6 @@ export class ArchiverL1Synchronizer implements Traceable {
706
731
  this.blobClient,
707
732
  searchStartBlock, // TODO(palla/reorg): If the L2 reorg was due to an L1 reorg, we need to start search earlier
708
733
  searchEndBlock,
709
- this.l1Addresses,
710
734
  this.instrumentation,
711
735
  this.log,
712
736
  !initialSyncComplete, // isHistoricalSync
@@ -801,6 +825,14 @@ export class ArchiverL1Synchronizer implements Traceable {
801
825
  );
802
826
  }
803
827
 
828
+ for (const published of validCheckpoints) {
829
+ this.instrumentation.processCheckpointL1Timing({
830
+ slotNumber: published.checkpoint.header.slotNumber,
831
+ l1Timestamp: published.l1.timestamp,
832
+ l1Constants: this.l1Constants,
833
+ });
834
+ }
835
+
804
836
  try {
805
837
  const updatedValidationResult =
806
838
  rollupStatus.validationResult === initialValidationResult ? undefined : rollupStatus.validationResult;
@@ -819,7 +851,7 @@ export class ArchiverL1Synchronizer implements Traceable {
819
851
  const prunedCheckpointNumber = result.prunedBlocks[0].checkpointNumber;
820
852
  const prunedSlotNumber = result.prunedBlocks[0].header.globalVariables.slotNumber;
821
853
 
822
- this.log.warn(
854
+ this.log.info(
823
855
  `Pruned ${result.prunedBlocks.length} mismatching blocks for checkpoint ${prunedCheckpointNumber}`,
824
856
  { prunedBlocks: result.prunedBlocks.map(b => b.toBlockInfo()), prunedSlotNumber, prunedCheckpointNumber },
825
857
  );