@aztec/archiver 0.0.1-commit.2ed92850 → 0.0.1-commit.3469e52
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/README.md +0 -9
- package/dest/archiver.d.ts +4 -4
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +20 -19
- package/dest/errors.d.ts +1 -6
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +0 -8
- package/dest/factory.d.ts +2 -3
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +3 -5
- package/dest/l1/bin/retrieve-calldata.js +2 -2
- package/dest/l1/data_retrieval.d.ts +1 -1
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +2 -2
- package/dest/modules/data_source_base.d.ts +17 -16
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +52 -21
- package/dest/modules/data_store_updater.d.ts +19 -23
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +49 -47
- package/dest/modules/instrumentation.d.ts +3 -3
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +7 -7
- package/dest/store/block_store.d.ts +19 -33
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +39 -80
- package/dest/store/kv_archiver_store.d.ts +22 -26
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +14 -18
- package/dest/store/log_store.d.ts +4 -4
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/test/fake_l1_state.d.ts +4 -4
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/mock_archiver.js +1 -1
- package/dest/test/mock_l2_block_source.d.ts +18 -18
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +40 -39
- package/dest/test/mock_structs.js +4 -4
- package/package.json +13 -13
- package/src/archiver.ts +26 -24
- package/src/errors.ts +0 -12
- package/src/factory.ts +2 -4
- package/src/l1/bin/retrieve-calldata.ts +2 -7
- package/src/l1/data_retrieval.ts +3 -3
- package/src/modules/data_source_base.ts +76 -25
- package/src/modules/data_store_updater.ts +55 -59
- package/src/modules/instrumentation.ts +2 -2
- package/src/modules/l1_synchronizer.ts +9 -9
- package/src/store/block_store.ts +56 -103
- package/src/store/kv_archiver_store.ts +24 -32
- package/src/store/log_store.ts +8 -8
- package/src/test/fake_l1_state.ts +2 -2
- package/src/test/mock_archiver.ts +1 -1
- package/src/test/mock_l2_block_source.ts +60 -50
- package/src/test/mock_structs.ts +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
-
import type {
|
|
2
|
+
import type { L2BlockNew } from '@aztec/stdlib/block';
|
|
3
3
|
import {
|
|
4
4
|
Attributes,
|
|
5
5
|
type Gauge,
|
|
@@ -97,7 +97,7 @@ export class ArchiverInstrumentation {
|
|
|
97
97
|
return this.telemetry.isEnabled();
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
public processNewBlocks(syncTimePerBlock: number, blocks:
|
|
100
|
+
public processNewBlocks(syncTimePerBlock: number, blocks: L2BlockNew[]) {
|
|
101
101
|
this.syncDurationPerBlock.record(Math.ceil(syncTimePerBlock));
|
|
102
102
|
this.blockHeight.record(Math.max(...blocks.map(b => b.number)));
|
|
103
103
|
this.syncBlockCount.add(blocks.length);
|
|
@@ -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.removeBlocksAfter(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.unwindCheckpoints(localPendingCheckpointNumber, checkpointsToUnwind);
|
|
335
335
|
this.log.warn(
|
|
336
|
-
`
|
|
337
|
-
`due to predicted reorg at L1 block ${currentL1BlockNumber}. ` +
|
|
336
|
+
`Unwound ${count(checkpointsToUnwind, 'checkpoint')} from checkpoint ${localPendingCheckpointNumber} ` +
|
|
337
|
+
`to ${provenCheckpointNumber} 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 checkpointsToUnwind = localPendingCheckpointNumber - tipAfterUnwind;
|
|
679
|
+
await this.updater.unwindCheckpoints(localPendingCheckpointNumber, checkpointsToUnwind);
|
|
680
680
|
|
|
681
681
|
this.log.warn(
|
|
682
|
-
`
|
|
682
|
+
`Unwound ${count(checkpointsToUnwind, 'checkpoint')} from checkpoint ${localPendingCheckpointNumber} ` +
|
|
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.setCheckpointData', () =>
|
|
810
|
+
this.updater.setNewCheckpointData(validCheckpoints, updatedValidationResult),
|
|
811
811
|
),
|
|
812
812
|
);
|
|
813
813
|
this.instrumentation.processNewBlocks(
|
package/src/store/block_store.ts
CHANGED
|
@@ -12,14 +12,13 @@ import {
|
|
|
12
12
|
Body,
|
|
13
13
|
CheckpointedL2Block,
|
|
14
14
|
CommitteeAttestation,
|
|
15
|
-
L2Block,
|
|
16
15
|
L2BlockHash,
|
|
16
|
+
L2BlockNew,
|
|
17
17
|
type ValidateCheckpointResult,
|
|
18
18
|
deserializeValidateCheckpointResult,
|
|
19
19
|
serializeValidateCheckpointResult,
|
|
20
20
|
} from '@aztec/stdlib/block';
|
|
21
21
|
import { L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
22
|
-
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
23
22
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
24
23
|
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
25
24
|
import {
|
|
@@ -28,7 +27,6 @@ import {
|
|
|
28
27
|
TxEffect,
|
|
29
28
|
TxHash,
|
|
30
29
|
TxReceipt,
|
|
31
|
-
TxStatus,
|
|
32
30
|
deserializeIndexedTxEffect,
|
|
33
31
|
serializeIndexedTxEffect,
|
|
34
32
|
} from '@aztec/stdlib/tx';
|
|
@@ -38,7 +36,6 @@ import {
|
|
|
38
36
|
BlockIndexNotSequentialError,
|
|
39
37
|
BlockNotFoundError,
|
|
40
38
|
BlockNumberNotSequentialError,
|
|
41
|
-
CannotOverwriteCheckpointedBlockError,
|
|
42
39
|
CheckpointNotFoundError,
|
|
43
40
|
CheckpointNumberNotConsistentError,
|
|
44
41
|
CheckpointNumberNotSequentialError,
|
|
@@ -78,8 +75,6 @@ export type CheckpointData = {
|
|
|
78
75
|
attestations: Buffer[];
|
|
79
76
|
};
|
|
80
77
|
|
|
81
|
-
export type RemoveCheckpointsResult = { blocksRemoved: L2Block[] | undefined };
|
|
82
|
-
|
|
83
78
|
/**
|
|
84
79
|
* LMDB-based block storage for the archiver.
|
|
85
80
|
*/
|
|
@@ -116,10 +111,7 @@ export class BlockStore {
|
|
|
116
111
|
|
|
117
112
|
#log = createLogger('archiver:block_store');
|
|
118
113
|
|
|
119
|
-
constructor(
|
|
120
|
-
private db: AztecAsyncKVStore,
|
|
121
|
-
private l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
122
|
-
) {
|
|
114
|
+
constructor(private db: AztecAsyncKVStore) {
|
|
123
115
|
this.#blocks = db.openMap('archiver_blocks');
|
|
124
116
|
this.#blockTxs = db.openMap('archiver_block_txs');
|
|
125
117
|
this.#txEffects = db.openMap('archiver_tx_effects');
|
|
@@ -133,25 +125,11 @@ export class BlockStore {
|
|
|
133
125
|
}
|
|
134
126
|
|
|
135
127
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* TODO(#13569): Compute proper finalized block number based on L1 finalized block.
|
|
139
|
-
* TODO(palla/mbps): Even the provisional computation is wrong, since it should subtract checkpoints, not blocks
|
|
140
|
-
* @returns The finalized block number.
|
|
141
|
-
*/
|
|
142
|
-
async getFinalizedL2BlockNumber(): Promise<BlockNumber> {
|
|
143
|
-
const provenBlockNumber = await this.getProvenBlockNumber();
|
|
144
|
-
return BlockNumber(Math.max(provenBlockNumber - this.l1Constants.epochDuration * 2, 0));
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
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.
|
|
128
|
+
* Append new blocks to the store's list. All blocks must be for the 'current' checkpoint
|
|
129
|
+
* @param blocks - The L2 blocks to be added to the store.
|
|
152
130
|
* @returns True if the operation is successful.
|
|
153
131
|
*/
|
|
154
|
-
async
|
|
132
|
+
async addBlocks(blocks: L2BlockNew[], opts: { force?: boolean } = {}): Promise<boolean> {
|
|
155
133
|
if (blocks.length === 0) {
|
|
156
134
|
return true;
|
|
157
135
|
}
|
|
@@ -167,12 +145,6 @@ export class BlockStore {
|
|
|
167
145
|
const previousBlockNumber = await this.getLatestBlockNumber();
|
|
168
146
|
const previousCheckpointNumber = await this.getLatestCheckpointNumber();
|
|
169
147
|
|
|
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
|
-
|
|
176
148
|
// Check that the first block number is the expected one
|
|
177
149
|
if (!opts.force && previousBlockNumber !== firstBlockNumber - 1) {
|
|
178
150
|
throw new InitialBlockNumberNotSequentialError(firstBlockNumber, previousBlockNumber);
|
|
@@ -210,7 +182,7 @@ export class BlockStore {
|
|
|
210
182
|
}
|
|
211
183
|
|
|
212
184
|
// Iterate over blocks array and insert them, checking that the block numbers and indexes are sequential. Also check they are for the correct checkpoint.
|
|
213
|
-
let previousBlock:
|
|
185
|
+
let previousBlock: L2BlockNew | undefined = undefined;
|
|
214
186
|
for (const block of blocks) {
|
|
215
187
|
if (!opts.force && previousBlock) {
|
|
216
188
|
if (previousBlock.number + 1 !== block.number) {
|
|
@@ -269,7 +241,7 @@ export class BlockStore {
|
|
|
269
241
|
}
|
|
270
242
|
|
|
271
243
|
let previousBlockNumber: BlockNumber | undefined = undefined;
|
|
272
|
-
let previousBlock:
|
|
244
|
+
let previousBlock: L2BlockNew | undefined = undefined;
|
|
273
245
|
|
|
274
246
|
// If we have a previous checkpoint then we need to get the previous block number
|
|
275
247
|
if (previousCheckpointData !== undefined) {
|
|
@@ -350,7 +322,7 @@ export class BlockStore {
|
|
|
350
322
|
});
|
|
351
323
|
}
|
|
352
324
|
|
|
353
|
-
private async addBlockToDatabase(block:
|
|
325
|
+
private async addBlockToDatabase(block: L2BlockNew, checkpointNumber: number, indexWithinCheckpoint: number) {
|
|
354
326
|
const blockHash = L2BlockHash.fromField(await block.hash());
|
|
355
327
|
|
|
356
328
|
await this.#blocks.set(block.number, {
|
|
@@ -379,7 +351,7 @@ export class BlockStore {
|
|
|
379
351
|
}
|
|
380
352
|
|
|
381
353
|
/** Deletes a block and all associated data (tx effects, indices). */
|
|
382
|
-
private async deleteBlock(block:
|
|
354
|
+
private async deleteBlock(block: L2BlockNew): Promise<void> {
|
|
383
355
|
// Delete the block from the main blocks map
|
|
384
356
|
await this.#blocks.delete(block.number);
|
|
385
357
|
|
|
@@ -396,48 +368,51 @@ export class BlockStore {
|
|
|
396
368
|
}
|
|
397
369
|
|
|
398
370
|
/**
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
371
|
+
* Unwinds checkpoints from the database
|
|
372
|
+
* @param from - The tip of the chain, passed for verification purposes,
|
|
373
|
+
* ensuring that we don't end up deleting something we did not intend
|
|
374
|
+
* @param checkpointsToUnwind - The number of checkpoints we are to unwind
|
|
375
|
+
* @returns True if the operation is successful
|
|
402
376
|
*/
|
|
403
|
-
async
|
|
377
|
+
async unwindCheckpoints(from: CheckpointNumber, checkpointsToUnwind: number) {
|
|
404
378
|
return await this.db.transactionAsync(async () => {
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
this.#log.warn(`No checkpoints to remove after ${checkpointNumber} (latest is ${latestCheckpointNumber})`);
|
|
409
|
-
return { blocksRemoved: undefined };
|
|
379
|
+
const last = await this.getLatestCheckpointNumber();
|
|
380
|
+
if (from !== last) {
|
|
381
|
+
throw new Error(`Can only unwind checkpoints from the tip (requested ${from} but current tip is ${last})`);
|
|
410
382
|
}
|
|
411
383
|
|
|
412
|
-
// If the proven checkpoint is beyond the target, update it
|
|
413
384
|
const proven = await this.getProvenCheckpointNumber();
|
|
414
|
-
if (
|
|
415
|
-
this
|
|
416
|
-
await this.setProvenCheckpointNumber(checkpointNumber);
|
|
385
|
+
if (from - checkpointsToUnwind < proven) {
|
|
386
|
+
await this.setProvenCheckpointNumber(CheckpointNumber(from - checkpointsToUnwind));
|
|
417
387
|
}
|
|
418
388
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
throw new Error(`Target checkpoint ${checkpointNumber} not found in store`);
|
|
389
|
+
for (let i = 0; i < checkpointsToUnwind; i++) {
|
|
390
|
+
const checkpointNumber = from - i;
|
|
391
|
+
const checkpoint = await this.#checkpoints.getAsync(checkpointNumber);
|
|
392
|
+
|
|
393
|
+
if (checkpoint === undefined) {
|
|
394
|
+
this.#log.warn(`Cannot remove checkpoint ${checkpointNumber} from the store since we don't have it`);
|
|
395
|
+
continue;
|
|
427
396
|
}
|
|
428
|
-
|
|
429
|
-
|
|
397
|
+
await this.#checkpoints.delete(checkpointNumber);
|
|
398
|
+
const maxBlock = checkpoint.startBlock + checkpoint.numBlocks - 1;
|
|
430
399
|
|
|
431
|
-
|
|
432
|
-
|
|
400
|
+
for (let blockNumber = checkpoint.startBlock; blockNumber <= maxBlock; blockNumber++) {
|
|
401
|
+
const block = await this.getBlock(BlockNumber(blockNumber));
|
|
433
402
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
403
|
+
if (block === undefined) {
|
|
404
|
+
this.#log.warn(`Cannot remove block ${blockNumber} from the store since we don't have it`);
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
await this.deleteBlock(block);
|
|
409
|
+
this.#log.debug(
|
|
410
|
+
`Unwound block ${blockNumber} ${(await block.hash()).toString()} for checkpoint ${checkpointNumber}`,
|
|
411
|
+
);
|
|
412
|
+
}
|
|
438
413
|
}
|
|
439
414
|
|
|
440
|
-
return
|
|
415
|
+
return true;
|
|
441
416
|
});
|
|
442
417
|
}
|
|
443
418
|
|
|
@@ -474,7 +449,7 @@ export class BlockStore {
|
|
|
474
449
|
return data;
|
|
475
450
|
}
|
|
476
451
|
|
|
477
|
-
async getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<
|
|
452
|
+
async getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<L2BlockNew[] | undefined> {
|
|
478
453
|
const checkpoint = await this.#checkpoints.getAsync(checkpointNumber);
|
|
479
454
|
if (!checkpoint) {
|
|
480
455
|
return undefined;
|
|
@@ -497,8 +472,8 @@ export class BlockStore {
|
|
|
497
472
|
* @param slotNumber - The slot number to search for.
|
|
498
473
|
* @returns All blocks with the given slot number, in ascending block number order.
|
|
499
474
|
*/
|
|
500
|
-
async getBlocksForSlot(slotNumber: SlotNumber): Promise<
|
|
501
|
-
const blocks:
|
|
475
|
+
async getBlocksForSlot(slotNumber: SlotNumber): Promise<L2BlockNew[]> {
|
|
476
|
+
const blocks: L2BlockNew[] = [];
|
|
502
477
|
|
|
503
478
|
// Iterate backwards through all blocks and filter by slot number
|
|
504
479
|
// This is more efficient since we usually query for the most recent slot
|
|
@@ -518,13 +493,12 @@ export class BlockStore {
|
|
|
518
493
|
|
|
519
494
|
/**
|
|
520
495
|
* Removes all blocks with block number > blockNumber.
|
|
521
|
-
* Does not remove any associated checkpoints.
|
|
522
496
|
* @param blockNumber - The block number to remove after.
|
|
523
497
|
* @returns The removed blocks (for event emission).
|
|
524
498
|
*/
|
|
525
|
-
async
|
|
499
|
+
async unwindBlocksAfter(blockNumber: BlockNumber): Promise<L2BlockNew[]> {
|
|
526
500
|
return await this.db.transactionAsync(async () => {
|
|
527
|
-
const removedBlocks:
|
|
501
|
+
const removedBlocks: L2BlockNew[] = [];
|
|
528
502
|
|
|
529
503
|
// Get the latest block number to determine the range
|
|
530
504
|
const latestBlockNumber = await this.getLatestBlockNumber();
|
|
@@ -646,7 +620,7 @@ export class BlockStore {
|
|
|
646
620
|
* @param limit - The number of blocks to return.
|
|
647
621
|
* @returns The requested L2 blocks
|
|
648
622
|
*/
|
|
649
|
-
async *getBlocks(start: BlockNumber, limit: number): AsyncIterableIterator<
|
|
623
|
+
async *getBlocks(start: BlockNumber, limit: number): AsyncIterableIterator<L2BlockNew> {
|
|
650
624
|
for await (const [blockNumber, blockStorage] of this.getBlockStorages(start, limit)) {
|
|
651
625
|
const block = await this.getBlockFromBlockStorage(blockNumber, blockStorage);
|
|
652
626
|
if (block) {
|
|
@@ -660,7 +634,7 @@ export class BlockStore {
|
|
|
660
634
|
* @param blockNumber - The number of the block to return.
|
|
661
635
|
* @returns The requested L2 block.
|
|
662
636
|
*/
|
|
663
|
-
async getBlock(blockNumber: BlockNumber): Promise<
|
|
637
|
+
async getBlock(blockNumber: BlockNumber): Promise<L2BlockNew | undefined> {
|
|
664
638
|
const blockStorage = await this.#blocks.getAsync(blockNumber);
|
|
665
639
|
if (!blockStorage || !blockStorage.header) {
|
|
666
640
|
return Promise.resolve(undefined);
|
|
@@ -673,7 +647,7 @@ export class BlockStore {
|
|
|
673
647
|
* @param blockHash - The hash of the block to return.
|
|
674
648
|
* @returns The requested L2 block.
|
|
675
649
|
*/
|
|
676
|
-
async getBlockByHash(blockHash: L2BlockHash): Promise<
|
|
650
|
+
async getBlockByHash(blockHash: L2BlockHash): Promise<L2BlockNew | undefined> {
|
|
677
651
|
const blockNumber = await this.#blockHashIndex.getAsync(blockHash.toString());
|
|
678
652
|
if (blockNumber === undefined) {
|
|
679
653
|
return undefined;
|
|
@@ -686,7 +660,7 @@ export class BlockStore {
|
|
|
686
660
|
* @param archive - The archive root of the block to return.
|
|
687
661
|
* @returns The requested L2 block.
|
|
688
662
|
*/
|
|
689
|
-
async getBlockByArchive(archive: Fr): Promise<
|
|
663
|
+
async getBlockByArchive(archive: Fr): Promise<L2BlockNew | undefined> {
|
|
690
664
|
const blockNumber = await this.#blockArchiveIndex.getAsync(archive.toString());
|
|
691
665
|
if (blockNumber === undefined) {
|
|
692
666
|
return undefined;
|
|
@@ -762,7 +736,7 @@ export class BlockStore {
|
|
|
762
736
|
private async getBlockFromBlockStorage(
|
|
763
737
|
blockNumber: number,
|
|
764
738
|
blockStorage: BlockStorage,
|
|
765
|
-
): Promise<
|
|
739
|
+
): Promise<L2BlockNew | undefined> {
|
|
766
740
|
const header = BlockHeader.fromBuffer(blockStorage.header);
|
|
767
741
|
const archive = AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive);
|
|
768
742
|
const blockHash = blockStorage.blockHash;
|
|
@@ -786,7 +760,7 @@ export class BlockStore {
|
|
|
786
760
|
txEffects.push(deserializeIndexedTxEffect(txEffect).data);
|
|
787
761
|
}
|
|
788
762
|
const body = new Body(txEffects);
|
|
789
|
-
const block = new
|
|
763
|
+
const block = new L2BlockNew(
|
|
790
764
|
archive,
|
|
791
765
|
header,
|
|
792
766
|
body,
|
|
@@ -828,34 +802,13 @@ export class BlockStore {
|
|
|
828
802
|
return undefined;
|
|
829
803
|
}
|
|
830
804
|
|
|
831
|
-
const blockNumber = BlockNumber(txEffect.l2BlockNumber);
|
|
832
|
-
|
|
833
|
-
// Use existing archiver methods to determine finalization level
|
|
834
|
-
const [provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber] = await Promise.all([
|
|
835
|
-
this.getProvenBlockNumber(),
|
|
836
|
-
this.getCheckpointedL2BlockNumber(),
|
|
837
|
-
this.getFinalizedL2BlockNumber(),
|
|
838
|
-
]);
|
|
839
|
-
|
|
840
|
-
let status: TxStatus;
|
|
841
|
-
if (blockNumber <= finalizedBlockNumber) {
|
|
842
|
-
status = TxStatus.FINALIZED;
|
|
843
|
-
} else if (blockNumber <= provenBlockNumber) {
|
|
844
|
-
status = TxStatus.PROVEN;
|
|
845
|
-
} else if (blockNumber <= checkpointedBlockNumber) {
|
|
846
|
-
status = TxStatus.CHECKPOINTED;
|
|
847
|
-
} else {
|
|
848
|
-
status = TxStatus.PROPOSED;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
805
|
return new TxReceipt(
|
|
852
806
|
txHash,
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
undefined,
|
|
807
|
+
TxReceipt.statusFromRevertCode(txEffect.data.revertCode),
|
|
808
|
+
'',
|
|
856
809
|
txEffect.data.transactionFee.toBigInt(),
|
|
857
810
|
txEffect.l2BlockHash,
|
|
858
|
-
|
|
811
|
+
BlockNumber(txEffect.l2BlockNumber),
|
|
859
812
|
);
|
|
860
813
|
}
|
|
861
814
|
|
|
@@ -6,7 +6,7 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
6
6
|
import type { AztecAsyncKVStore, CustomRange, StoreSize } from '@aztec/kv-store';
|
|
7
7
|
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
8
8
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
9
|
-
import { CheckpointedL2Block,
|
|
9
|
+
import { CheckpointedL2Block, L2BlockHash, L2BlockNew, type ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
10
10
|
import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
11
11
|
import type {
|
|
12
12
|
ContractClassPublic,
|
|
@@ -16,7 +16,6 @@ import type {
|
|
|
16
16
|
ExecutablePrivateFunctionWithMembershipProof,
|
|
17
17
|
UtilityFunctionWithMembershipProof,
|
|
18
18
|
} from '@aztec/stdlib/contract';
|
|
19
|
-
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
20
19
|
import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
|
|
21
20
|
import type { LogFilter, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
|
|
22
21
|
import type { BlockHeader, TxHash, TxReceipt } from '@aztec/stdlib/tx';
|
|
@@ -25,7 +24,7 @@ import type { UInt64 } from '@aztec/stdlib/types';
|
|
|
25
24
|
import { join } from 'path';
|
|
26
25
|
|
|
27
26
|
import type { InboxMessage } from '../structs/inbox_message.js';
|
|
28
|
-
import { BlockStore, type CheckpointData
|
|
27
|
+
import { BlockStore, type CheckpointData } from './block_store.js';
|
|
29
28
|
import { ContractClassStore } from './contract_class_store.js';
|
|
30
29
|
import { ContractInstanceStore } from './contract_instance_store.js';
|
|
31
30
|
import { LogStore } from './log_store.js';
|
|
@@ -65,9 +64,8 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
65
64
|
constructor(
|
|
66
65
|
private db: AztecAsyncKVStore,
|
|
67
66
|
logsMaxPageSize: number = 1000,
|
|
68
|
-
l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
69
67
|
) {
|
|
70
|
-
this.#blockStore = new BlockStore(db
|
|
68
|
+
this.#blockStore = new BlockStore(db);
|
|
71
69
|
this.#logStore = new LogStore(db, this.#blockStore, logsMaxPageSize);
|
|
72
70
|
this.#messageStore = new MessageStore(db);
|
|
73
71
|
this.#contractClassStore = new ContractClassStore(db);
|
|
@@ -103,11 +101,6 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
103
101
|
return this.db.close();
|
|
104
102
|
}
|
|
105
103
|
|
|
106
|
-
/** Computes the finalized block number based on the proven block number. */
|
|
107
|
-
getFinalizedL2BlockNumber(): Promise<BlockNumber> {
|
|
108
|
-
return this.#blockStore.getFinalizedL2BlockNumber();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
104
|
/** Looks up a public function name given a selector. */
|
|
112
105
|
getDebugFunctionName(_address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
|
|
113
106
|
return Promise.resolve(this.functionNames.get(selector.toString()));
|
|
@@ -235,14 +228,12 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
235
228
|
}
|
|
236
229
|
|
|
237
230
|
/**
|
|
238
|
-
* Append new
|
|
239
|
-
*
|
|
240
|
-
* For checkpointed blocks (already published to L1), use addCheckpoints() instead.
|
|
241
|
-
* @param blocks - The proposed L2 blocks to be added to the store.
|
|
231
|
+
* Append new blocks to the store's list.
|
|
232
|
+
* @param blocks - The L2 blocks to be added to the store and the last processed L1 block.
|
|
242
233
|
* @returns True if the operation is successful.
|
|
243
234
|
*/
|
|
244
|
-
|
|
245
|
-
return this.#blockStore.
|
|
235
|
+
addBlocks(blocks: L2BlockNew[], opts: { force?: boolean; checkpointNumber?: number } = {}): Promise<boolean> {
|
|
236
|
+
return this.#blockStore.addBlocks(blocks, opts);
|
|
246
237
|
}
|
|
247
238
|
|
|
248
239
|
/**
|
|
@@ -263,12 +254,14 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
263
254
|
}
|
|
264
255
|
|
|
265
256
|
/**
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
257
|
+
* Unwinds checkpoints from the database
|
|
258
|
+
* @param from - The tip of the chain, passed for verification purposes,
|
|
259
|
+
* ensuring that we don't end up deleting something we did not intend
|
|
260
|
+
* @param checkpointsToUnwind - The number of checkpoints we are to unwind
|
|
261
|
+
* @returns True if the operation is successful
|
|
269
262
|
*/
|
|
270
|
-
|
|
271
|
-
return this.#blockStore.
|
|
263
|
+
unwindCheckpoints(from: CheckpointNumber, checkpointsToUnwind: number): Promise<boolean> {
|
|
264
|
+
return this.#blockStore.unwindCheckpoints(from, checkpointsToUnwind);
|
|
272
265
|
}
|
|
273
266
|
|
|
274
267
|
/**
|
|
@@ -305,21 +298,21 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
305
298
|
* Returns the block for the given number, or undefined if not exists.
|
|
306
299
|
* @param number - The block number to return.
|
|
307
300
|
*/
|
|
308
|
-
getBlock(number: BlockNumber): Promise<
|
|
301
|
+
getBlock(number: BlockNumber): Promise<L2BlockNew | undefined> {
|
|
309
302
|
return this.#blockStore.getBlock(number);
|
|
310
303
|
}
|
|
311
304
|
/**
|
|
312
305
|
* Returns the block for the given hash, or undefined if not exists.
|
|
313
306
|
* @param blockHash - The block hash to return.
|
|
314
307
|
*/
|
|
315
|
-
getBlockByHash(blockHash: Fr): Promise<
|
|
308
|
+
getBlockByHash(blockHash: Fr): Promise<L2BlockNew | undefined> {
|
|
316
309
|
return this.#blockStore.getBlockByHash(L2BlockHash.fromField(blockHash));
|
|
317
310
|
}
|
|
318
311
|
/**
|
|
319
312
|
* Returns the block for the given archive root, or undefined if not exists.
|
|
320
313
|
* @param archive - The archive root to return.
|
|
321
314
|
*/
|
|
322
|
-
getBlockByArchive(archive: Fr): Promise<
|
|
315
|
+
getBlockByArchive(archive: Fr): Promise<L2BlockNew | undefined> {
|
|
323
316
|
return this.#blockStore.getBlockByArchive(archive);
|
|
324
317
|
}
|
|
325
318
|
|
|
@@ -329,7 +322,7 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
329
322
|
* @param limit - The number of blocks to return.
|
|
330
323
|
* @returns The requested L2 blocks.
|
|
331
324
|
*/
|
|
332
|
-
getBlocks(from: BlockNumber, limit: number): Promise<
|
|
325
|
+
getBlocks(from: BlockNumber, limit: number): Promise<L2BlockNew[]> {
|
|
333
326
|
return toArray(this.#blockStore.getBlocks(from, limit));
|
|
334
327
|
}
|
|
335
328
|
|
|
@@ -392,11 +385,11 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
392
385
|
* @param blocks - The blocks for which to add the logs.
|
|
393
386
|
* @returns True if the operation is successful.
|
|
394
387
|
*/
|
|
395
|
-
addLogs(blocks:
|
|
388
|
+
addLogs(blocks: L2BlockNew[]): Promise<boolean> {
|
|
396
389
|
return this.#logStore.addLogs(blocks);
|
|
397
390
|
}
|
|
398
391
|
|
|
399
|
-
deleteLogs(blocks:
|
|
392
|
+
deleteLogs(blocks: L2BlockNew[]): Promise<boolean> {
|
|
400
393
|
return this.#logStore.deleteLogs(blocks);
|
|
401
394
|
}
|
|
402
395
|
|
|
@@ -605,7 +598,7 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
605
598
|
* @param checkpointNumber Retrieves all blocks for the given checkpoint
|
|
606
599
|
* @returns The collection of blocks for the requested checkpoint if available (undefined otherwise)
|
|
607
600
|
*/
|
|
608
|
-
getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<
|
|
601
|
+
getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<L2BlockNew[] | undefined> {
|
|
609
602
|
return this.#blockStore.getBlocksForCheckpoint(checkpointNumber);
|
|
610
603
|
}
|
|
611
604
|
|
|
@@ -623,17 +616,16 @@ export class KVArchiverDataStore implements ContractDataSource {
|
|
|
623
616
|
* @param slotNumber - The slot number to search for.
|
|
624
617
|
* @returns All blocks with the given slot number.
|
|
625
618
|
*/
|
|
626
|
-
getBlocksForSlot(slotNumber: SlotNumber): Promise<
|
|
619
|
+
getBlocksForSlot(slotNumber: SlotNumber): Promise<L2BlockNew[]> {
|
|
627
620
|
return this.#blockStore.getBlocksForSlot(slotNumber);
|
|
628
621
|
}
|
|
629
622
|
|
|
630
623
|
/**
|
|
631
624
|
* Removes all blocks with block number > blockNumber.
|
|
632
|
-
* Does not remove any associated checkpoints.
|
|
633
625
|
* @param blockNumber - The block number to remove after.
|
|
634
626
|
* @returns The removed blocks (for event emission).
|
|
635
627
|
*/
|
|
636
|
-
removeBlocksAfter(blockNumber: BlockNumber): Promise<
|
|
637
|
-
return this.#blockStore.
|
|
628
|
+
removeBlocksAfter(blockNumber: BlockNumber): Promise<L2BlockNew[]> {
|
|
629
|
+
return this.#blockStore.unwindBlocksAfter(blockNumber);
|
|
638
630
|
}
|
|
639
631
|
}
|
package/src/store/log_store.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
6
6
|
import { BufferReader, numToUInt32BE } from '@aztec/foundation/serialize';
|
|
7
7
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
8
8
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
9
|
-
import {
|
|
9
|
+
import { L2BlockHash, L2BlockNew } from '@aztec/stdlib/block';
|
|
10
10
|
import { MAX_LOGS_PER_TAG } from '@aztec/stdlib/interfaces/api-limit';
|
|
11
11
|
import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
|
|
12
12
|
import {
|
|
@@ -59,7 +59,7 @@ export class LogStore {
|
|
|
59
59
|
* @param block - The L2 block to extract logs from.
|
|
60
60
|
* @returns An object containing the private and public tagged logs for the block.
|
|
61
61
|
*/
|
|
62
|
-
#extractTaggedLogsFromBlock(block:
|
|
62
|
+
#extractTaggedLogsFromBlock(block: L2BlockNew) {
|
|
63
63
|
// SiloedTag (as string) -> array of log buffers.
|
|
64
64
|
const privateTaggedLogs = new Map<string, Buffer[]>();
|
|
65
65
|
// "{contractAddress}_{tag}" (as string) -> array of log buffers.
|
|
@@ -120,7 +120,7 @@ export class LogStore {
|
|
|
120
120
|
* @returns A map from tag (as string) to an array of serialized private logs belonging to that tag, and a map from
|
|
121
121
|
* "{contractAddress}_{tag}" (as string) to an array of serialized public logs belonging to that key.
|
|
122
122
|
*/
|
|
123
|
-
#extractTaggedLogs(blocks:
|
|
123
|
+
#extractTaggedLogs(blocks: L2BlockNew[]): {
|
|
124
124
|
privateTaggedLogs: Map<string, Buffer[]>;
|
|
125
125
|
publicTaggedLogs: Map<string, Buffer[]>;
|
|
126
126
|
} {
|
|
@@ -146,7 +146,7 @@ export class LogStore {
|
|
|
146
146
|
return { privateTaggedLogs, publicTaggedLogs };
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
async #addPrivateLogs(blocks:
|
|
149
|
+
async #addPrivateLogs(blocks: L2BlockNew[]): Promise<void> {
|
|
150
150
|
const newBlocks = await filterAsync(
|
|
151
151
|
blocks,
|
|
152
152
|
async block => !(await this.#privateLogKeysByBlock.hasAsync(block.number)),
|
|
@@ -181,7 +181,7 @@ export class LogStore {
|
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
async #addPublicLogs(blocks:
|
|
184
|
+
async #addPublicLogs(blocks: L2BlockNew[]): Promise<void> {
|
|
185
185
|
const newBlocks = await filterAsync(
|
|
186
186
|
blocks,
|
|
187
187
|
async block => !(await this.#publicLogKeysByBlock.hasAsync(block.number)),
|
|
@@ -229,7 +229,7 @@ export class LogStore {
|
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
async #addContractClassLogs(blocks:
|
|
232
|
+
async #addContractClassLogs(blocks: L2BlockNew[]): Promise<void> {
|
|
233
233
|
const newBlocks = await filterAsync(
|
|
234
234
|
blocks,
|
|
235
235
|
async block => !(await this.#contractClassLogsByBlock.hasAsync(block.number)),
|
|
@@ -260,7 +260,7 @@ export class LogStore {
|
|
|
260
260
|
* @param blocks - The blocks for which to add the logs.
|
|
261
261
|
* @returns True if the operation is successful.
|
|
262
262
|
*/
|
|
263
|
-
addLogs(blocks:
|
|
263
|
+
addLogs(blocks: L2BlockNew[]): Promise<boolean> {
|
|
264
264
|
return this.db.transactionAsync(async () => {
|
|
265
265
|
await Promise.all([
|
|
266
266
|
this.#addPrivateLogs(blocks),
|
|
@@ -285,7 +285,7 @@ export class LogStore {
|
|
|
285
285
|
return L2BlockHash.fromField(blockHash);
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
-
deleteLogs(blocks:
|
|
288
|
+
deleteLogs(blocks: L2BlockNew[]): Promise<boolean> {
|
|
289
289
|
return this.db.transactionAsync(async () => {
|
|
290
290
|
await Promise.all(
|
|
291
291
|
blocks.map(async block => {
|
|
@@ -10,7 +10,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
10
10
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
11
11
|
import { createLogger } from '@aztec/foundation/log';
|
|
12
12
|
import { RollupAbi } from '@aztec/l1-artifacts';
|
|
13
|
-
import { CommitteeAttestation, CommitteeAttestationsAndSigners,
|
|
13
|
+
import { CommitteeAttestation, CommitteeAttestationsAndSigners, L2BlockNew } from '@aztec/stdlib/block';
|
|
14
14
|
import { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
15
15
|
import { getSlotAtTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
16
16
|
import { InboxLeaf } from '@aztec/stdlib/messaging';
|
|
@@ -51,7 +51,7 @@ type AddCheckpointOptions = {
|
|
|
51
51
|
/** Number of L2 blocks in the checkpoint. Default: 1 */
|
|
52
52
|
numBlocks?: number;
|
|
53
53
|
/** Or the actual blocks for the checkpoint */
|
|
54
|
-
blocks?:
|
|
54
|
+
blocks?: L2BlockNew[];
|
|
55
55
|
/** Number of transactions per block. Default: 4 */
|
|
56
56
|
txsPerBlock?: number;
|
|
57
57
|
/** Max number of effects per tx (for generating large blobs). Default: undefined */
|