@aztec/archiver 0.0.1-commit.87a0206 → 0.0.1-commit.88c5703d4

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 (88) 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 +21 -9
  5. package/dest/errors.d.ts.map +1 -1
  6. package/dest/errors.js +27 -14
  7. package/dest/factory.d.ts +3 -4
  8. package/dest/factory.d.ts.map +1 -1
  9. package/dest/factory.js +24 -20
  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 +32 -28
  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 +12 -7
  24. package/dest/modules/data_source_base.d.ts.map +1 -1
  25. package/dest/modules/data_source_base.js +33 -77
  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 +42 -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 +40 -13
  39. package/dest/store/kv_archiver_store.d.ts.map +1 -1
  40. package/dest/store/kv_archiver_store.js +48 -13
  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 +6 -3
  45. package/dest/store/log_store.d.ts.map +1 -1
  46. package/dest/store/log_store.js +45 -6
  47. package/dest/store/message_store.d.ts +5 -1
  48. package/dest/store/message_store.d.ts.map +1 -1
  49. package/dest/store/message_store.js +14 -1
  50. package/dest/test/fake_l1_state.d.ts +13 -1
  51. package/dest/test/fake_l1_state.d.ts.map +1 -1
  52. package/dest/test/fake_l1_state.js +95 -23
  53. package/dest/test/mock_archiver.d.ts +1 -1
  54. package/dest/test/mock_archiver.d.ts.map +1 -1
  55. package/dest/test/mock_archiver.js +3 -2
  56. package/dest/test/mock_l2_block_source.d.ts +21 -5
  57. package/dest/test/mock_l2_block_source.d.ts.map +1 -1
  58. package/dest/test/mock_l2_block_source.js +132 -86
  59. package/dest/test/mock_structs.d.ts +4 -1
  60. package/dest/test/mock_structs.d.ts.map +1 -1
  61. package/dest/test/mock_structs.js +13 -1
  62. package/dest/test/noop_l1_archiver.d.ts +4 -1
  63. package/dest/test/noop_l1_archiver.d.ts.map +1 -1
  64. package/dest/test/noop_l1_archiver.js +5 -1
  65. package/package.json +13 -13
  66. package/src/archiver.ts +74 -130
  67. package/src/errors.ts +40 -24
  68. package/src/factory.ts +34 -17
  69. package/src/index.ts +1 -0
  70. package/src/l1/README.md +25 -68
  71. package/src/l1/bin/retrieve-calldata.ts +40 -27
  72. package/src/l1/calldata_retriever.ts +249 -379
  73. package/src/l1/data_retrieval.ts +23 -25
  74. package/src/l1/spire_proposer.ts +7 -15
  75. package/src/modules/data_source_base.ts +64 -98
  76. package/src/modules/data_store_updater.ts +71 -30
  77. package/src/modules/instrumentation.ts +29 -2
  78. package/src/modules/l1_synchronizer.ts +47 -14
  79. package/src/store/block_store.ts +157 -105
  80. package/src/store/kv_archiver_store.ts +73 -15
  81. package/src/store/l2_tips_cache.ts +89 -0
  82. package/src/store/log_store.ts +60 -15
  83. package/src/store/message_store.ts +20 -1
  84. package/src/test/fake_l1_state.ts +125 -26
  85. package/src/test/mock_archiver.ts +3 -2
  86. package/src/test/mock_l2_block_source.ts +173 -81
  87. package/src/test/mock_structs.ts +20 -6
  88. 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([
@@ -366,6 +391,7 @@ export class ArchiverL1Synchronizer implements Traceable {
366
391
  const localMessagesInserted = await this.store.getTotalL1ToL2MessageCount();
367
392
  const localLastMessage = await this.store.getLastL1ToL2Message();
368
393
  const remoteMessagesState = await this.inbox.getState({ blockNumber: currentL1BlockNumber });
394
+ await this.store.setInboxTreeInProgress(remoteMessagesState.treeInProgress);
369
395
 
370
396
  this.log.trace(`Retrieved remote inbox state at L1 block ${currentL1BlockNumber}.`, {
371
397
  localMessagesInserted,
@@ -550,7 +576,7 @@ export class ArchiverL1Synchronizer implements Traceable {
550
576
  if (provenCheckpointNumber === 0) {
551
577
  const localProvenCheckpointNumber = await this.store.getProvenCheckpointNumber();
552
578
  if (localProvenCheckpointNumber !== provenCheckpointNumber) {
553
- await this.store.setProvenCheckpointNumber(provenCheckpointNumber);
579
+ await this.updater.setProvenCheckpointNumber(provenCheckpointNumber);
554
580
  this.log.info(`Rolled back proven chain to checkpoint ${provenCheckpointNumber}`, { provenCheckpointNumber });
555
581
  }
556
582
  }
@@ -582,13 +608,13 @@ export class ArchiverL1Synchronizer implements Traceable {
582
608
  ) {
583
609
  const localProvenCheckpointNumber = await this.store.getProvenCheckpointNumber();
584
610
  if (localProvenCheckpointNumber !== provenCheckpointNumber) {
585
- await this.store.setProvenCheckpointNumber(provenCheckpointNumber);
611
+ await this.updater.setProvenCheckpointNumber(provenCheckpointNumber);
586
612
  this.log.info(`Updated proven chain to checkpoint ${provenCheckpointNumber}`, { provenCheckpointNumber });
587
613
  const provenSlotNumber = localCheckpointForDestinationProvenCheckpointNumber.header.slotNumber;
588
614
  const provenEpochNumber: EpochNumber = getEpochAtSlot(provenSlotNumber, this.l1Constants);
589
615
  const lastBlockNumberInCheckpoint =
590
616
  localCheckpointForDestinationProvenCheckpointNumber.startBlock +
591
- localCheckpointForDestinationProvenCheckpointNumber.numBlocks -
617
+ localCheckpointForDestinationProvenCheckpointNumber.blockCount -
592
618
  1;
593
619
 
594
620
  this.events.emit(L2BlockSourceEvents.L2BlockProven, {
@@ -597,7 +623,7 @@ export class ArchiverL1Synchronizer implements Traceable {
597
623
  slotNumber: provenSlotNumber,
598
624
  epochNumber: provenEpochNumber,
599
625
  });
600
- this.instrumentation.updateLastProvenBlock(lastBlockNumberInCheckpoint);
626
+ this.instrumentation.updateLastProvenCheckpoint(localCheckpointForDestinationProvenCheckpointNumber);
601
627
  } else {
602
628
  this.log.trace(`Proven checkpoint ${provenCheckpointNumber} already stored.`);
603
629
  }
@@ -706,7 +732,6 @@ export class ArchiverL1Synchronizer implements Traceable {
706
732
  this.blobClient,
707
733
  searchStartBlock, // TODO(palla/reorg): If the L2 reorg was due to an L1 reorg, we need to start search earlier
708
734
  searchEndBlock,
709
- this.l1Addresses,
710
735
  this.instrumentation,
711
736
  this.log,
712
737
  !initialSyncComplete, // isHistoricalSync
@@ -801,6 +826,14 @@ export class ArchiverL1Synchronizer implements Traceable {
801
826
  );
802
827
  }
803
828
 
829
+ for (const published of validCheckpoints) {
830
+ this.instrumentation.processCheckpointL1Timing({
831
+ slotNumber: published.checkpoint.header.slotNumber,
832
+ l1Timestamp: published.l1.timestamp,
833
+ l1Constants: this.l1Constants,
834
+ });
835
+ }
836
+
804
837
  try {
805
838
  const updatedValidationResult =
806
839
  rollupStatus.validationResult === initialValidationResult ? undefined : rollupStatus.validationResult;
@@ -819,7 +852,7 @@ export class ArchiverL1Synchronizer implements Traceable {
819
852
  const prunedCheckpointNumber = result.prunedBlocks[0].checkpointNumber;
820
853
  const prunedSlotNumber = result.prunedBlocks[0].header.globalVariables.slotNumber;
821
854
 
822
- this.log.warn(
855
+ this.log.info(
823
856
  `Pruned ${result.prunedBlocks.length} mismatching blocks for checkpoint ${prunedCheckpointNumber}`,
824
857
  { prunedBlocks: result.prunedBlocks.map(b => b.toBlockInfo()), prunedSlotNumber, prunedCheckpointNumber },
825
858
  );