@aztec/archiver 4.0.0-nightly.20260125 → 4.0.0-nightly.20260127
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 +2 -2
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +8 -9
- package/dest/errors.d.ts +6 -1
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +8 -0
- package/dest/modules/data_store_updater.d.ts +21 -17
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +47 -49
- package/dest/modules/l1_synchronizer.js +7 -7
- package/dest/store/block_store.d.ts +15 -11
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +46 -34
- package/dest/store/kv_archiver_store.d.ts +12 -11
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +13 -12
- package/dest/test/mock_archiver.js +1 -1
- package/dest/test/mock_l2_block_source.d.ts +2 -2
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +2 -2
- package/package.json +13 -13
- package/src/archiver.ts +10 -9
- package/src/errors.ts +12 -0
- package/src/modules/data_store_updater.ts +57 -53
- package/src/modules/l1_synchronizer.ts +9 -9
- package/src/store/block_store.ts +46 -37
- package/src/store/kv_archiver_store.ts +14 -13
- package/src/test/mock_archiver.ts +1 -1
- package/src/test/mock_l2_block_source.ts +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BlockNumber,
|
|
1
|
+
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import {
|
|
@@ -47,17 +47,21 @@ export class ArchiverDataStoreUpdater {
|
|
|
47
47
|
constructor(private store: KVArchiverDataStore) {}
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
* Adds blocks to the store with contract class/instance extraction from logs.
|
|
50
|
+
* Adds proposed blocks to the store with contract class/instance extraction from logs.
|
|
51
|
+
* These are uncheckpointed blocks that have been proposed by the sequencer but not yet included in a checkpoint on L1.
|
|
51
52
|
* Extracts ContractClassPublished, ContractInstancePublished, ContractInstanceUpdated events,
|
|
52
53
|
* and individually broadcasted functions from the block logs.
|
|
53
54
|
*
|
|
54
|
-
* @param blocks - The L2 blocks to add.
|
|
55
|
+
* @param blocks - The proposed L2 blocks to add.
|
|
55
56
|
* @param pendingChainValidationStatus - Optional validation status to set.
|
|
56
57
|
* @returns True if the operation is successful.
|
|
57
58
|
*/
|
|
58
|
-
public
|
|
59
|
+
public addProposedBlocks(
|
|
60
|
+
blocks: L2Block[],
|
|
61
|
+
pendingChainValidationStatus?: ValidateCheckpointResult,
|
|
62
|
+
): Promise<boolean> {
|
|
59
63
|
return this.store.transactionAsync(async () => {
|
|
60
|
-
await this.store.
|
|
64
|
+
await this.store.addProposedBlocks(blocks);
|
|
61
65
|
|
|
62
66
|
const opResults = await Promise.all([
|
|
63
67
|
// Update the pending chain validation status if provided
|
|
@@ -65,7 +69,7 @@ export class ArchiverDataStoreUpdater {
|
|
|
65
69
|
// Add any logs emitted during the retrieved blocks
|
|
66
70
|
this.store.addLogs(blocks),
|
|
67
71
|
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
68
|
-
...blocks.map(block => this.
|
|
72
|
+
...blocks.map(block => this.addContractDataToDb(block)),
|
|
69
73
|
]);
|
|
70
74
|
|
|
71
75
|
return opResults.every(Boolean);
|
|
@@ -74,7 +78,7 @@ export class ArchiverDataStoreUpdater {
|
|
|
74
78
|
|
|
75
79
|
/**
|
|
76
80
|
* Reconciles local blocks with incoming checkpoints from L1.
|
|
77
|
-
* Adds checkpoints to the store with contract class/instance extraction from logs.
|
|
81
|
+
* Adds new checkpoints to the store with contract class/instance extraction from logs.
|
|
78
82
|
* Prunes any local blocks that conflict with checkpoint data (by comparing archive roots).
|
|
79
83
|
* Extracts ContractClassPublished, ContractInstancePublished, ContractInstanceUpdated events,
|
|
80
84
|
* and individually broadcasted functions from the checkpoint block logs.
|
|
@@ -83,7 +87,7 @@ export class ArchiverDataStoreUpdater {
|
|
|
83
87
|
* @param pendingChainValidationStatus - Optional validation status to set.
|
|
84
88
|
* @returns Result with information about any pruned blocks.
|
|
85
89
|
*/
|
|
86
|
-
public
|
|
90
|
+
public addCheckpoints(
|
|
87
91
|
checkpoints: PublishedCheckpoint[],
|
|
88
92
|
pendingChainValidationStatus?: ValidateCheckpointResult,
|
|
89
93
|
): Promise<ReconcileCheckpointsResult> {
|
|
@@ -93,7 +97,7 @@ export class ArchiverDataStoreUpdater {
|
|
|
93
97
|
|
|
94
98
|
await this.store.addCheckpoints(checkpoints);
|
|
95
99
|
|
|
96
|
-
// Filter out blocks that were already inserted via
|
|
100
|
+
// Filter out blocks that were already inserted via addProposedBlocks() to avoid duplicating logs/contract data
|
|
97
101
|
const newBlocks = checkpoints
|
|
98
102
|
.flatMap((ch: PublishedCheckpoint) => ch.checkpoint.blocks)
|
|
99
103
|
.filter(b => lastAlreadyInsertedBlockNumber === undefined || b.number > lastAlreadyInsertedBlockNumber);
|
|
@@ -104,7 +108,7 @@ export class ArchiverDataStoreUpdater {
|
|
|
104
108
|
// Add any logs emitted during the retrieved blocks
|
|
105
109
|
this.store.addLogs(newBlocks),
|
|
106
110
|
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
107
|
-
...newBlocks.map(block => this.
|
|
111
|
+
...newBlocks.map(block => this.addContractDataToDb(block)),
|
|
108
112
|
]);
|
|
109
113
|
|
|
110
114
|
return { prunedBlocks, lastAlreadyInsertedBlockNumber };
|
|
@@ -185,80 +189,80 @@ export class ArchiverDataStoreUpdater {
|
|
|
185
189
|
}
|
|
186
190
|
|
|
187
191
|
/**
|
|
188
|
-
* Removes all blocks strictly after the specified block number and cleans up associated contract data.
|
|
192
|
+
* Removes all uncheckpointed blocks strictly after the specified block number and cleans up associated contract data.
|
|
189
193
|
* This handles removal of provisionally added blocks along with their contract classes/instances.
|
|
194
|
+
* Verifies that each block being removed is not part of a stored checkpoint.
|
|
190
195
|
*
|
|
191
196
|
* @param blockNumber - Remove all blocks with number greater than this.
|
|
192
197
|
* @returns The removed blocks.
|
|
198
|
+
* @throws Error if any block to be removed is checkpointed.
|
|
193
199
|
*/
|
|
194
|
-
public
|
|
200
|
+
public removeUncheckpointedBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]> {
|
|
195
201
|
return this.store.transactionAsync(async () => {
|
|
196
|
-
//
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
]);
|
|
202
|
+
// Verify we're only removing uncheckpointed blocks
|
|
203
|
+
const lastCheckpointedBlockNumber = await this.store.getCheckpointedL2BlockNumber();
|
|
204
|
+
if (blockNumber < lastCheckpointedBlockNumber) {
|
|
205
|
+
throw new Error(
|
|
206
|
+
`Cannot remove blocks after ${blockNumber} because checkpointed blocks exist up to ${lastCheckpointedBlockNumber}`,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
204
209
|
|
|
205
|
-
return
|
|
210
|
+
return await this.removeBlocksAfter(blockNumber);
|
|
206
211
|
});
|
|
207
212
|
}
|
|
208
213
|
|
|
209
214
|
/**
|
|
210
|
-
*
|
|
215
|
+
* Removes all blocks strictly after the given block number along with any logs and contract data.
|
|
216
|
+
* Does not remove their checkpoints.
|
|
217
|
+
*/
|
|
218
|
+
private async removeBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]> {
|
|
219
|
+
// First get the blocks to be removed so we can clean up contract data
|
|
220
|
+
const removedBlocks = await this.store.removeBlocksAfter(blockNumber);
|
|
221
|
+
|
|
222
|
+
// Clean up contract data and logs for the removed blocks
|
|
223
|
+
await Promise.all([
|
|
224
|
+
this.store.deleteLogs(removedBlocks),
|
|
225
|
+
...removedBlocks.map(block => this.removeContractDataFromDb(block)),
|
|
226
|
+
]);
|
|
227
|
+
|
|
228
|
+
return removedBlocks;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Removes all checkpoints after the given checkpoint number.
|
|
211
233
|
* Deletes ContractClassPublished, ContractInstancePublished, ContractInstanceUpdated data
|
|
212
|
-
* that was stored for the
|
|
234
|
+
* that was stored for the removed checkpoints. Also removes ALL blocks (both checkpointed
|
|
235
|
+
* and uncheckpointed) after the last block of the given checkpoint.
|
|
213
236
|
*
|
|
214
|
-
* @param
|
|
215
|
-
* @param checkpointsToUnwind - The number of checkpoints to unwind.
|
|
237
|
+
* @param checkpointNumber - Remove all checkpoints strictly after this one.
|
|
216
238
|
* @returns True if the operation is successful.
|
|
217
239
|
*/
|
|
218
|
-
public async
|
|
219
|
-
|
|
220
|
-
throw new Error(`Cannot unwind ${checkpointsToUnwind} blocks`);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const last = await this.store.getSynchedCheckpointNumber();
|
|
224
|
-
if (from != last) {
|
|
225
|
-
throw new Error(`Cannot unwind checkpoints from checkpoint ${from} when the last checkpoint is ${last}`);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
const blocks = [];
|
|
229
|
-
const lastCheckpointNumber = from + checkpointsToUnwind - 1;
|
|
230
|
-
for (let checkpointNumber = from; checkpointNumber <= lastCheckpointNumber; checkpointNumber++) {
|
|
231
|
-
const blocksForCheckpoint = await this.store.getBlocksForCheckpoint(checkpointNumber);
|
|
232
|
-
if (!blocksForCheckpoint) {
|
|
233
|
-
continue;
|
|
234
|
-
}
|
|
235
|
-
blocks.push(...blocksForCheckpoint);
|
|
236
|
-
}
|
|
240
|
+
public async removeCheckpointsAfter(checkpointNumber: CheckpointNumber): Promise<boolean> {
|
|
241
|
+
const { blocksRemoved = [] } = await this.store.removeCheckpointsAfter(checkpointNumber);
|
|
237
242
|
|
|
238
243
|
const opResults = await Promise.all([
|
|
239
244
|
// Prune rolls back to the last proven block, which is by definition valid
|
|
240
245
|
this.store.setPendingChainValidationStatus({ valid: true }),
|
|
241
|
-
// Remove contract data for all blocks being
|
|
242
|
-
...
|
|
243
|
-
this.store.deleteLogs(
|
|
244
|
-
this.store.unwindCheckpoints(from, checkpointsToUnwind),
|
|
246
|
+
// Remove contract data for all blocks being removed
|
|
247
|
+
...blocksRemoved.map(block => this.removeContractDataFromDb(block)),
|
|
248
|
+
this.store.deleteLogs(blocksRemoved),
|
|
245
249
|
]);
|
|
246
250
|
|
|
247
251
|
return opResults.every(Boolean);
|
|
248
252
|
}
|
|
249
253
|
|
|
250
254
|
/** Extracts and stores contract data from a single block. */
|
|
251
|
-
private
|
|
252
|
-
return this.
|
|
255
|
+
private addContractDataToDb(block: L2Block): Promise<boolean> {
|
|
256
|
+
return this.updateContractDataOnDb(block, Operation.Store);
|
|
253
257
|
}
|
|
254
258
|
|
|
255
259
|
/** Removes contract data associated with a block. */
|
|
256
|
-
private
|
|
257
|
-
return this.
|
|
260
|
+
private removeContractDataFromDb(block: L2Block): Promise<boolean> {
|
|
261
|
+
return this.updateContractDataOnDb(block, Operation.Delete);
|
|
258
262
|
}
|
|
259
263
|
|
|
260
264
|
/** Adds or remove contract data associated with a block. */
|
|
261
|
-
private async
|
|
265
|
+
private async updateContractDataOnDb(block: L2Block, operation: Operation): Promise<boolean> {
|
|
262
266
|
const contractClassLogs = block.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
|
|
263
267
|
const privateLogs = block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
|
|
264
268
|
const publicLogs = block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
|
|
@@ -258,7 +258,7 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
258
258
|
`Pruning blocks after block ${lastCheckpointedBlockNumber} due to slot ${firstUncheckpointedBlockSlot} not being checkpointed`,
|
|
259
259
|
{ firstUncheckpointedBlockHeader: firstUncheckpointedBlockHeader.toInspect(), slotAtNextL1Block },
|
|
260
260
|
);
|
|
261
|
-
const prunedBlocks = await this.updater.
|
|
261
|
+
const prunedBlocks = await this.updater.removeUncheckpointedBlocksAfter(lastCheckpointedBlockNumber);
|
|
262
262
|
|
|
263
263
|
if (prunedBlocks.length > 0) {
|
|
264
264
|
this.events.emit(L2BlockSourceEvents.L2PruneUncheckpointed, {
|
|
@@ -331,10 +331,10 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
331
331
|
this.log.debug(
|
|
332
332
|
`L2 prune from ${provenCheckpointNumber + 1} to ${localPendingCheckpointNumber} will occur on next checkpoint submission.`,
|
|
333
333
|
);
|
|
334
|
-
await this.updater.
|
|
334
|
+
await this.updater.removeCheckpointsAfter(provenCheckpointNumber);
|
|
335
335
|
this.log.warn(
|
|
336
|
-
`
|
|
337
|
-
`
|
|
336
|
+
`Removed ${count(checkpointsToUnwind, 'checkpoint')} after checkpoint ${provenCheckpointNumber} ` +
|
|
337
|
+
`due to predicted reorg at L1 block ${currentL1BlockNumber}. ` +
|
|
338
338
|
`Updated latest checkpoint is ${await this.store.getSynchedCheckpointNumber()}.`,
|
|
339
339
|
);
|
|
340
340
|
this.instrumentation.processPrune(timer.ms());
|
|
@@ -675,11 +675,11 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
675
675
|
tipAfterUnwind--;
|
|
676
676
|
}
|
|
677
677
|
|
|
678
|
-
const
|
|
679
|
-
await this.updater.
|
|
678
|
+
const checkpointsToRemove = localPendingCheckpointNumber - tipAfterUnwind;
|
|
679
|
+
await this.updater.removeCheckpointsAfter(CheckpointNumber(tipAfterUnwind));
|
|
680
680
|
|
|
681
681
|
this.log.warn(
|
|
682
|
-
`
|
|
682
|
+
`Removed ${count(checkpointsToRemove, 'checkpoint')} after checkpoint ${tipAfterUnwind} ` +
|
|
683
683
|
`due to mismatched checkpoint hashes at L1 block ${currentL1BlockNumber}. ` +
|
|
684
684
|
`Updated L2 latest checkpoint is ${await this.store.getSynchedCheckpointNumber()}.`,
|
|
685
685
|
);
|
|
@@ -806,8 +806,8 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
806
806
|
const updatedValidationResult =
|
|
807
807
|
rollupStatus.validationResult === initialValidationResult ? undefined : rollupStatus.validationResult;
|
|
808
808
|
const [processDuration, result] = await elapsed(() =>
|
|
809
|
-
execInSpan(this.tracer, 'Archiver.
|
|
810
|
-
this.updater.
|
|
809
|
+
execInSpan(this.tracer, 'Archiver.addCheckpoints', () =>
|
|
810
|
+
this.updater.addCheckpoints(validCheckpoints, updatedValidationResult),
|
|
811
811
|
),
|
|
812
812
|
);
|
|
813
813
|
this.instrumentation.processNewBlocks(
|
package/src/store/block_store.ts
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
BlockIndexNotSequentialError,
|
|
39
39
|
BlockNotFoundError,
|
|
40
40
|
BlockNumberNotSequentialError,
|
|
41
|
+
CannotOverwriteCheckpointedBlockError,
|
|
41
42
|
CheckpointNotFoundError,
|
|
42
43
|
CheckpointNumberNotConsistentError,
|
|
43
44
|
CheckpointNumberNotSequentialError,
|
|
@@ -77,6 +78,8 @@ export type CheckpointData = {
|
|
|
77
78
|
attestations: Buffer[];
|
|
78
79
|
};
|
|
79
80
|
|
|
81
|
+
export type RemoveCheckpointsResult = { blocksRemoved: L2Block[] | undefined };
|
|
82
|
+
|
|
80
83
|
/**
|
|
81
84
|
* LMDB-based block storage for the archiver.
|
|
82
85
|
*/
|
|
@@ -142,11 +145,13 @@ export class BlockStore {
|
|
|
142
145
|
}
|
|
143
146
|
|
|
144
147
|
/**
|
|
145
|
-
* Append new blocks to the store's list. All blocks must be for the 'current' checkpoint
|
|
146
|
-
*
|
|
148
|
+
* Append new proposed blocks to the store's list. All blocks must be for the 'current' checkpoint.
|
|
149
|
+
* These are uncheckpointed blocks that have been proposed by the sequencer but not yet included in a checkpoint on L1.
|
|
150
|
+
* For checkpointed blocks (already published to L1), use addCheckpoints() instead.
|
|
151
|
+
* @param blocks - The proposed L2 blocks to be added to the store.
|
|
147
152
|
* @returns True if the operation is successful.
|
|
148
153
|
*/
|
|
149
|
-
async
|
|
154
|
+
async addProposedBlocks(blocks: L2Block[], opts: { force?: boolean } = {}): Promise<boolean> {
|
|
150
155
|
if (blocks.length === 0) {
|
|
151
156
|
return true;
|
|
152
157
|
}
|
|
@@ -162,6 +167,12 @@ export class BlockStore {
|
|
|
162
167
|
const previousBlockNumber = await this.getLatestBlockNumber();
|
|
163
168
|
const previousCheckpointNumber = await this.getLatestCheckpointNumber();
|
|
164
169
|
|
|
170
|
+
// Verify we're not overwriting checkpointed blocks
|
|
171
|
+
const lastCheckpointedBlockNumber = await this.getCheckpointedL2BlockNumber();
|
|
172
|
+
if (!opts.force && firstBlockNumber <= lastCheckpointedBlockNumber) {
|
|
173
|
+
throw new CannotOverwriteCheckpointedBlockError(firstBlockNumber, lastCheckpointedBlockNumber);
|
|
174
|
+
}
|
|
175
|
+
|
|
165
176
|
// Check that the first block number is the expected one
|
|
166
177
|
if (!opts.force && previousBlockNumber !== firstBlockNumber - 1) {
|
|
167
178
|
throw new InitialBlockNumberNotSequentialError(firstBlockNumber, previousBlockNumber);
|
|
@@ -385,51 +396,48 @@ export class BlockStore {
|
|
|
385
396
|
}
|
|
386
397
|
|
|
387
398
|
/**
|
|
388
|
-
*
|
|
389
|
-
*
|
|
390
|
-
*
|
|
391
|
-
* @param checkpointsToUnwind - The number of checkpoints we are to unwind
|
|
392
|
-
* @returns True if the operation is successful
|
|
399
|
+
* Removes all checkpoints with checkpoint number > checkpointNumber.
|
|
400
|
+
* Also removes ALL blocks (both checkpointed and uncheckpointed) after the last block of the given checkpoint.
|
|
401
|
+
* @param checkpointNumber - Remove all checkpoints strictly after this one.
|
|
393
402
|
*/
|
|
394
|
-
async
|
|
403
|
+
async removeCheckpointsAfter(checkpointNumber: CheckpointNumber): Promise<RemoveCheckpointsResult> {
|
|
395
404
|
return await this.db.transactionAsync(async () => {
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
405
|
+
const latestCheckpointNumber = await this.getLatestCheckpointNumber();
|
|
406
|
+
|
|
407
|
+
if (checkpointNumber >= latestCheckpointNumber) {
|
|
408
|
+
this.#log.warn(`No checkpoints to remove after ${checkpointNumber} (latest is ${latestCheckpointNumber})`);
|
|
409
|
+
return { blocksRemoved: undefined };
|
|
399
410
|
}
|
|
400
411
|
|
|
412
|
+
// If the proven checkpoint is beyond the target, update it
|
|
401
413
|
const proven = await this.getProvenCheckpointNumber();
|
|
402
|
-
if (
|
|
403
|
-
|
|
414
|
+
if (proven > checkpointNumber) {
|
|
415
|
+
this.#log.warn(`Updating proven checkpoint ${proven} to last valid checkpoint ${checkpointNumber}`);
|
|
416
|
+
await this.setProvenCheckpointNumber(checkpointNumber);
|
|
404
417
|
}
|
|
405
418
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
419
|
+
// Find the last block number to keep (last block of the given checkpoint, or 0 if no checkpoint)
|
|
420
|
+
let lastBlockToKeep: BlockNumber;
|
|
421
|
+
if (checkpointNumber <= 0) {
|
|
422
|
+
lastBlockToKeep = BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
423
|
+
} else {
|
|
424
|
+
const targetCheckpoint = await this.#checkpoints.getAsync(checkpointNumber);
|
|
425
|
+
if (!targetCheckpoint) {
|
|
426
|
+
throw new Error(`Target checkpoint ${checkpointNumber} not found in store`);
|
|
413
427
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
for (let blockNumber = checkpoint.startBlock; blockNumber <= maxBlock; blockNumber++) {
|
|
418
|
-
const block = await this.getBlock(BlockNumber(blockNumber));
|
|
428
|
+
lastBlockToKeep = BlockNumber(targetCheckpoint.startBlock + targetCheckpoint.numBlocks - 1);
|
|
429
|
+
}
|
|
419
430
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
continue;
|
|
423
|
-
}
|
|
431
|
+
// Remove all blocks after lastBlockToKeep (both checkpointed and uncheckpointed)
|
|
432
|
+
const blocksRemoved = await this.removeBlocksAfter(lastBlockToKeep);
|
|
424
433
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}
|
|
434
|
+
// Remove all checkpoints after the target
|
|
435
|
+
for (let c = latestCheckpointNumber; c > checkpointNumber; c = CheckpointNumber(c - 1)) {
|
|
436
|
+
await this.#checkpoints.delete(c);
|
|
437
|
+
this.#log.debug(`Removed checkpoint ${c}`);
|
|
430
438
|
}
|
|
431
439
|
|
|
432
|
-
return
|
|
440
|
+
return { blocksRemoved };
|
|
433
441
|
});
|
|
434
442
|
}
|
|
435
443
|
|
|
@@ -510,10 +518,11 @@ export class BlockStore {
|
|
|
510
518
|
|
|
511
519
|
/**
|
|
512
520
|
* Removes all blocks with block number > blockNumber.
|
|
521
|
+
* Does not remove any associated checkpoints.
|
|
513
522
|
* @param blockNumber - The block number to remove after.
|
|
514
523
|
* @returns The removed blocks (for event emission).
|
|
515
524
|
*/
|
|
516
|
-
async
|
|
525
|
+
async removeBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]> {
|
|
517
526
|
return await this.db.transactionAsync(async () => {
|
|
518
527
|
const removedBlocks: L2Block[] = [];
|
|
519
528
|
|
|
@@ -25,7 +25,7 @@ import type { UInt64 } from '@aztec/stdlib/types';
|
|
|
25
25
|
import { join } from 'path';
|
|
26
26
|
|
|
27
27
|
import type { InboxMessage } from '../structs/inbox_message.js';
|
|
28
|
-
import { BlockStore, type CheckpointData } from './block_store.js';
|
|
28
|
+
import { BlockStore, type CheckpointData, type RemoveCheckpointsResult } from './block_store.js';
|
|
29
29
|
import { ContractClassStore } from './contract_class_store.js';
|
|
30
30
|
import { ContractInstanceStore } from './contract_instance_store.js';
|
|
31
31
|
import { LogStore } from './log_store.js';
|
|
@@ -235,12 +235,14 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
/**
|
|
238
|
-
* Append new blocks to the store's list.
|
|
239
|
-
*
|
|
238
|
+
* Append new proposed blocks to the store's list.
|
|
239
|
+
* These are uncheckpointed blocks that have been proposed by the sequencer but not yet included in a checkpoint on L1.
|
|
240
|
+
* For checkpointed blocks (already published to L1), use addCheckpoints() instead.
|
|
241
|
+
* @param blocks - The proposed L2 blocks to be added to the store.
|
|
240
242
|
* @returns True if the operation is successful.
|
|
241
243
|
*/
|
|
242
|
-
|
|
243
|
-
return this.#blockStore.
|
|
244
|
+
addProposedBlocks(blocks: L2Block[], opts: { force?: boolean; checkpointNumber?: number } = {}): Promise<boolean> {
|
|
245
|
+
return this.#blockStore.addProposedBlocks(blocks, opts);
|
|
244
246
|
}
|
|
245
247
|
|
|
246
248
|
/**
|
|
@@ -261,14 +263,12 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
261
263
|
}
|
|
262
264
|
|
|
263
265
|
/**
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
* @param checkpointsToUnwind - The number of checkpoints we are to unwind
|
|
268
|
-
* @returns True if the operation is successful
|
|
266
|
+
* Removes all checkpoints with checkpoint number > checkpointNumber.
|
|
267
|
+
* Also removes ALL blocks (both checkpointed and uncheckpointed) after the last block of the given checkpoint.
|
|
268
|
+
* @param checkpointNumber - Remove all checkpoints strictly after this one.
|
|
269
269
|
*/
|
|
270
|
-
|
|
271
|
-
return this.#blockStore.
|
|
270
|
+
removeCheckpointsAfter(checkpointNumber: CheckpointNumber): Promise<RemoveCheckpointsResult> {
|
|
271
|
+
return this.#blockStore.removeCheckpointsAfter(checkpointNumber);
|
|
272
272
|
}
|
|
273
273
|
|
|
274
274
|
/**
|
|
@@ -629,10 +629,11 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
629
629
|
|
|
630
630
|
/**
|
|
631
631
|
* Removes all blocks with block number > blockNumber.
|
|
632
|
+
* Does not remove any associated checkpoints.
|
|
632
633
|
* @param blockNumber - The block number to remove after.
|
|
633
634
|
* @returns The removed blocks (for event emission).
|
|
634
635
|
*/
|
|
635
636
|
removeBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]> {
|
|
636
|
-
return this.#blockStore.
|
|
637
|
+
return this.#blockStore.removeBlocksAfter(blockNumber);
|
|
637
638
|
}
|
|
638
639
|
}
|
|
@@ -57,7 +57,7 @@ export class MockPrefilledArchiver extends MockArchiver {
|
|
|
57
57
|
|
|
58
58
|
const fromBlock = this.l2Blocks.length;
|
|
59
59
|
// TODO: Add L2 blocks and checkpoints separately once archiver has the apis for that.
|
|
60
|
-
this.
|
|
60
|
+
this.addProposedBlocks(this.prefilled.slice(fromBlock, fromBlock + numBlocks).flatMap(c => c.blocks));
|
|
61
61
|
return Promise.resolve();
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -43,9 +43,9 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
43
43
|
this.log.verbose(`Created ${numBlocks} blocks in the mock L2 block source`);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
public
|
|
46
|
+
public addProposedBlocks(blocks: L2Block[]) {
|
|
47
47
|
this.l2Blocks.push(...blocks);
|
|
48
|
-
this.log.verbose(`Added ${blocks.length} blocks to the mock L2 block source`);
|
|
48
|
+
this.log.verbose(`Added ${blocks.length} proposed blocks to the mock L2 block source`);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
public removeBlocks(numBlocks: number) {
|