@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.
- package/dest/archiver.d.ts +7 -4
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +62 -110
- package/dest/errors.d.ts +7 -9
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +9 -14
- package/dest/factory.d.ts +3 -4
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +15 -13
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/l1/bin/retrieve-calldata.js +36 -33
- package/dest/l1/calldata_retriever.d.ts +73 -50
- package/dest/l1/calldata_retriever.d.ts.map +1 -1
- package/dest/l1/calldata_retriever.js +190 -259
- package/dest/l1/data_retrieval.d.ts +9 -9
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +21 -19
- package/dest/l1/spire_proposer.d.ts +5 -5
- package/dest/l1/spire_proposer.d.ts.map +1 -1
- package/dest/l1/spire_proposer.js +9 -17
- package/dest/modules/data_source_base.d.ts +10 -5
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +29 -73
- package/dest/modules/data_store_updater.d.ts +22 -7
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +69 -29
- package/dest/modules/instrumentation.d.ts +15 -2
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +19 -2
- package/dest/modules/l1_synchronizer.d.ts +5 -8
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +41 -10
- package/dest/store/block_store.d.ts +29 -26
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +130 -78
- package/dest/store/kv_archiver_store.d.ts +34 -11
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +39 -9
- package/dest/store/l2_tips_cache.d.ts +19 -0
- package/dest/store/l2_tips_cache.d.ts.map +1 -0
- package/dest/store/l2_tips_cache.js +89 -0
- package/dest/store/log_store.d.ts +1 -1
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +55 -35
- package/dest/store/message_store.js +1 -1
- package/dest/test/fake_l1_state.d.ts +13 -1
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +84 -20
- package/dest/test/mock_archiver.d.ts +1 -1
- package/dest/test/mock_archiver.d.ts.map +1 -1
- package/dest/test/mock_archiver.js +3 -2
- package/dest/test/mock_l2_block_source.d.ts +21 -5
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +132 -86
- package/dest/test/mock_structs.d.ts +4 -1
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +13 -1
- package/dest/test/noop_l1_archiver.d.ts +4 -1
- package/dest/test/noop_l1_archiver.d.ts.map +1 -1
- package/dest/test/noop_l1_archiver.js +5 -1
- package/package.json +13 -13
- package/src/archiver.ts +74 -130
- package/src/errors.ts +10 -24
- package/src/factory.ts +29 -14
- package/src/index.ts +1 -0
- package/src/l1/README.md +25 -68
- package/src/l1/bin/retrieve-calldata.ts +46 -39
- package/src/l1/calldata_retriever.ts +249 -379
- package/src/l1/data_retrieval.ts +23 -25
- package/src/l1/spire_proposer.ts +7 -15
- package/src/modules/data_source_base.ts +56 -95
- package/src/modules/data_store_updater.ts +71 -30
- package/src/modules/instrumentation.ts +29 -2
- package/src/modules/l1_synchronizer.ts +46 -14
- package/src/store/block_store.ts +157 -105
- package/src/store/kv_archiver_store.ts +62 -12
- package/src/store/l2_tips_cache.ts +89 -0
- package/src/store/log_store.ts +93 -31
- package/src/store/message_store.ts +1 -1
- package/src/test/fake_l1_state.ts +110 -21
- package/src/test/mock_archiver.ts +3 -2
- package/src/test/mock_l2_block_source.ts +173 -81
- package/src/test/mock_structs.ts +20 -6
- 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
|
|
131
|
-
|
|
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 & {
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
);
|