@aztec/archiver 0.0.1-commit.c7c42ec → 0.0.1-commit.d1f2d6c
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 +156 -22
- package/dest/archiver.d.ts +135 -0
- package/dest/archiver.d.ts.map +1 -0
- package/dest/archiver.js +769 -0
- package/dest/{archiver/config.d.ts → config.d.ts} +9 -1
- package/dest/config.d.ts.map +1 -0
- package/dest/{archiver/config.js → config.js} +11 -2
- package/dest/{archiver/errors.d.ts → errors.d.ts} +1 -1
- package/dest/errors.d.ts.map +1 -0
- package/dest/factory.d.ts +7 -7
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +87 -8
- package/dest/index.d.ts +10 -4
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +8 -3
- package/dest/interfaces.d.ts +9 -0
- package/dest/interfaces.d.ts.map +1 -0
- package/dest/interfaces.js +3 -0
- package/dest/{archiver/l1 → l1}/bin/retrieve-calldata.d.ts +1 -1
- package/dest/l1/bin/retrieve-calldata.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/bin/retrieve-calldata.js +2 -2
- package/dest/{archiver/l1 → l1}/calldata_retriever.d.ts +3 -3
- package/dest/l1/calldata_retriever.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/calldata_retriever.js +2 -2
- package/dest/l1/data_retrieval.d.ts +88 -0
- package/dest/l1/data_retrieval.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/data_retrieval.js +35 -54
- package/dest/{archiver/l1 → l1}/debug_tx.d.ts +1 -1
- package/dest/l1/debug_tx.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/spire_proposer.d.ts +1 -1
- package/dest/l1/spire_proposer.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/trace_tx.d.ts +1 -1
- package/dest/l1/trace_tx.d.ts.map +1 -0
- package/dest/l1/types.d.ts +12 -0
- package/dest/l1/types.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/validate_trace.d.ts +1 -1
- package/dest/l1/validate_trace.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/validate_trace.js +1 -1
- package/dest/modules/data_source_base.d.ts +84 -0
- package/dest/modules/data_source_base.d.ts.map +1 -0
- package/dest/modules/data_source_base.js +260 -0
- package/dest/modules/data_store_updater.d.ts +69 -0
- package/dest/modules/data_store_updater.d.ts.map +1 -0
- package/dest/modules/data_store_updater.js +304 -0
- package/dest/modules/instrumentation.d.ts +37 -0
- package/dest/modules/instrumentation.d.ts.map +1 -0
- package/dest/{archiver → modules}/instrumentation.js +15 -63
- package/dest/modules/l1_synchronizer.d.ts +75 -0
- package/dest/modules/l1_synchronizer.d.ts.map +1 -0
- package/dest/modules/l1_synchronizer.js +1113 -0
- package/dest/modules/validation.d.ts +17 -0
- package/dest/modules/validation.d.ts.map +1 -0
- package/dest/{archiver → modules}/validation.js +7 -1
- package/dest/store/block_store.d.ts +188 -0
- package/dest/store/block_store.d.ts.map +1 -0
- package/dest/{archiver/kv_archiver_store → store}/block_store.js +119 -17
- package/dest/store/contract_class_store.d.ts +18 -0
- package/dest/store/contract_class_store.d.ts.map +1 -0
- package/dest/{archiver/kv_archiver_store → store}/contract_class_store.js +1 -1
- package/dest/store/contract_instance_store.d.ts +24 -0
- package/dest/store/contract_instance_store.d.ts.map +1 -0
- package/dest/{archiver/kv_archiver_store → store}/contract_instance_store.js +1 -1
- package/dest/store/kv_archiver_store.d.ts +339 -0
- package/dest/store/kv_archiver_store.d.ts.map +1 -0
- package/dest/{archiver/kv_archiver_store → store}/kv_archiver_store.js +185 -52
- package/dest/store/log_store.d.ts +54 -0
- package/dest/store/log_store.d.ts.map +1 -0
- package/dest/{archiver/kv_archiver_store → store}/log_store.js +89 -54
- package/dest/{archiver/kv_archiver_store → store}/message_store.d.ts +1 -1
- package/dest/store/message_store.d.ts.map +1 -0
- package/dest/{archiver/structs → structs}/data_retrieval.d.ts +1 -1
- package/dest/structs/data_retrieval.d.ts.map +1 -0
- package/dest/structs/inbox_message.d.ts +15 -0
- package/dest/structs/inbox_message.d.ts.map +1 -0
- package/dest/{archiver/structs → structs}/published.d.ts +1 -1
- package/dest/structs/published.d.ts.map +1 -0
- package/dest/test/fake_l1_state.d.ts +190 -0
- package/dest/test/fake_l1_state.d.ts.map +1 -0
- package/dest/test/fake_l1_state.js +383 -0
- package/dest/test/index.d.ts +2 -1
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +1 -0
- package/dest/test/mock_archiver.d.ts +2 -2
- package/dest/test/mock_archiver.d.ts.map +1 -1
- package/dest/test/mock_archiver.js +1 -2
- package/dest/test/mock_l1_to_l2_message_source.d.ts +2 -2
- package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
- package/dest/test/mock_l1_to_l2_message_source.js +12 -3
- package/dest/test/mock_l2_block_source.d.ts +21 -14
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +161 -55
- package/dest/test/mock_structs.d.ts +76 -2
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +133 -2
- package/package.json +15 -17
- package/src/archiver.ts +522 -0
- package/src/{archiver/config.ts → config.ts} +13 -2
- package/src/factory.ts +122 -8
- package/src/index.ts +10 -3
- package/src/interfaces.ts +9 -0
- package/src/{archiver/l1 → l1}/bin/retrieve-calldata.ts +7 -2
- package/src/{archiver/l1 → l1}/calldata_retriever.ts +3 -3
- package/src/{archiver/l1 → l1}/data_retrieval.ts +56 -73
- package/src/{archiver/l1 → l1}/validate_trace.ts +1 -1
- package/src/modules/data_source_base.ts +367 -0
- package/src/modules/data_store_updater.ts +419 -0
- package/src/{archiver → modules}/instrumentation.ts +16 -65
- package/src/modules/l1_synchronizer.ts +931 -0
- package/src/{archiver → modules}/validation.ts +11 -6
- package/src/{archiver/kv_archiver_store → store}/block_store.ts +170 -35
- package/src/{archiver/kv_archiver_store → store}/contract_class_store.ts +1 -1
- package/src/{archiver/kv_archiver_store → store}/contract_instance_store.ts +1 -1
- package/src/{archiver/kv_archiver_store → store}/kv_archiver_store.ts +224 -24
- package/src/{archiver/kv_archiver_store → store}/log_store.ts +145 -86
- package/src/test/fake_l1_state.ts +599 -0
- package/src/test/index.ts +1 -0
- package/src/test/mock_archiver.ts +2 -2
- package/src/test/mock_l1_to_l2_message_source.ts +10 -4
- package/src/test/mock_l2_block_source.ts +171 -65
- package/src/test/mock_structs.ts +247 -2
- package/dest/archiver/archiver.d.ts +0 -304
- package/dest/archiver/archiver.d.ts.map +0 -1
- package/dest/archiver/archiver.js +0 -1645
- package/dest/archiver/archiver_store.d.ts +0 -308
- package/dest/archiver/archiver_store.d.ts.map +0 -1
- package/dest/archiver/archiver_store.js +0 -4
- package/dest/archiver/archiver_store_test_suite.d.ts +0 -8
- package/dest/archiver/archiver_store_test_suite.d.ts.map +0 -1
- package/dest/archiver/archiver_store_test_suite.js +0 -2770
- package/dest/archiver/config.d.ts.map +0 -1
- package/dest/archiver/errors.d.ts.map +0 -1
- package/dest/archiver/index.d.ts +0 -7
- package/dest/archiver/index.d.ts.map +0 -1
- package/dest/archiver/index.js +0 -4
- package/dest/archiver/instrumentation.d.ts +0 -37
- package/dest/archiver/instrumentation.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/block_store.d.ts +0 -157
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +0 -18
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +0 -24
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +0 -158
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/log_store.d.ts +0 -45
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/message_store.d.ts.map +0 -1
- package/dest/archiver/l1/bin/retrieve-calldata.d.ts.map +0 -1
- package/dest/archiver/l1/calldata_retriever.d.ts.map +0 -1
- package/dest/archiver/l1/data_retrieval.d.ts +0 -90
- package/dest/archiver/l1/data_retrieval.d.ts.map +0 -1
- package/dest/archiver/l1/debug_tx.d.ts.map +0 -1
- package/dest/archiver/l1/spire_proposer.d.ts.map +0 -1
- package/dest/archiver/l1/trace_tx.d.ts.map +0 -1
- package/dest/archiver/l1/types.d.ts +0 -12
- package/dest/archiver/l1/types.d.ts.map +0 -1
- package/dest/archiver/l1/validate_trace.d.ts.map +0 -1
- package/dest/archiver/structs/data_retrieval.d.ts.map +0 -1
- package/dest/archiver/structs/inbox_message.d.ts +0 -15
- package/dest/archiver/structs/inbox_message.d.ts.map +0 -1
- package/dest/archiver/structs/published.d.ts.map +0 -1
- package/dest/archiver/validation.d.ts +0 -17
- package/dest/archiver/validation.d.ts.map +0 -1
- package/dest/rpc/index.d.ts +0 -9
- package/dest/rpc/index.d.ts.map +0 -1
- package/dest/rpc/index.js +0 -15
- package/src/archiver/archiver.ts +0 -2157
- package/src/archiver/archiver_store.ts +0 -372
- package/src/archiver/archiver_store_test_suite.ts +0 -2843
- package/src/archiver/index.ts +0 -6
- package/src/rpc/index.ts +0 -16
- /package/dest/{archiver/errors.js → errors.js} +0 -0
- /package/dest/{archiver/l1 → l1}/debug_tx.js +0 -0
- /package/dest/{archiver/l1 → l1}/spire_proposer.js +0 -0
- /package/dest/{archiver/l1 → l1}/trace_tx.js +0 -0
- /package/dest/{archiver/l1 → l1}/types.js +0 -0
- /package/dest/{archiver/kv_archiver_store → store}/message_store.js +0 -0
- /package/dest/{archiver/structs → structs}/data_retrieval.js +0 -0
- /package/dest/{archiver/structs → structs}/inbox_message.js +0 -0
- /package/dest/{archiver/structs → structs}/published.js +0 -0
- /package/src/{archiver/errors.ts → errors.ts} +0 -0
- /package/src/{archiver/l1 → l1}/README.md +0 -0
- /package/src/{archiver/l1 → l1}/debug_tx.ts +0 -0
- /package/src/{archiver/l1 → l1}/spire_proposer.ts +0 -0
- /package/src/{archiver/l1 → l1}/trace_tx.ts +0 -0
- /package/src/{archiver/l1 → l1}/types.ts +0 -0
- /package/src/{archiver/kv_archiver_store → store}/message_store.ts +0 -0
- /package/src/{archiver/structs → structs}/data_retrieval.ts +0 -0
- /package/src/{archiver/structs → structs}/inbox_message.ts +0 -0
- /package/src/{archiver/structs → structs}/published.ts +0 -0
|
@@ -4,15 +4,15 @@ import { compactArray } from '@aztec/foundation/collection';
|
|
|
4
4
|
import type { Logger } from '@aztec/foundation/log';
|
|
5
5
|
import {
|
|
6
6
|
type AttestationInfo,
|
|
7
|
-
type
|
|
8
|
-
type
|
|
7
|
+
type ValidateCheckpointNegativeResult,
|
|
8
|
+
type ValidateCheckpointResult,
|
|
9
9
|
getAttestationInfoFromPayload,
|
|
10
10
|
} from '@aztec/stdlib/block';
|
|
11
11
|
import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
12
12
|
import { type L1RollupConstants, getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
13
13
|
import { ConsensusPayload } from '@aztec/stdlib/p2p';
|
|
14
14
|
|
|
15
|
-
export type {
|
|
15
|
+
export type { ValidateCheckpointResult };
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Extracts attestation information from a published checkpoint.
|
|
@@ -35,7 +35,7 @@ export async function validateCheckpointAttestations(
|
|
|
35
35
|
epochCache: EpochCache,
|
|
36
36
|
constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
37
37
|
logger?: Logger,
|
|
38
|
-
): Promise<
|
|
38
|
+
): Promise<ValidateCheckpointResult> {
|
|
39
39
|
const attestorInfos = getAttestationInfoFromPublishedCheckpoint(publishedCheckpoint);
|
|
40
40
|
const attestors = compactArray(attestorInfos.map(info => ('address' in info ? info.address : undefined)));
|
|
41
41
|
const { checkpoint, attestations } = publishedCheckpoint;
|
|
@@ -61,12 +61,17 @@ export async function validateCheckpointAttestations(
|
|
|
61
61
|
return { valid: true };
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
if (await epochCache.isEscapeHatchOpen(epoch)) {
|
|
65
|
+
logger?.warn(`Escape hatch open for epoch ${epoch} at slot ${slot}, skipping checkpoint validation`);
|
|
66
|
+
return { valid: true };
|
|
67
|
+
}
|
|
68
|
+
|
|
64
69
|
const requiredAttestationCount = Math.floor((committee.length * 2) / 3) + 1;
|
|
65
70
|
|
|
66
|
-
const failedValidationResult = <TReason extends
|
|
71
|
+
const failedValidationResult = <TReason extends ValidateCheckpointNegativeResult['reason']>(reason: TReason) => ({
|
|
67
72
|
valid: false as const,
|
|
68
73
|
reason,
|
|
69
|
-
|
|
74
|
+
checkpoint: checkpoint.toCheckpointInfo(),
|
|
70
75
|
committee,
|
|
71
76
|
seed,
|
|
72
77
|
epoch,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { INITIAL_CHECKPOINT_NUMBER, INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
2
|
-
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
2
|
+
import { BlockNumber, CheckpointNumber, IndexWithinCheckpoint, SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
4
|
import { toArray } from '@aztec/foundation/iterable';
|
|
5
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -12,13 +12,14 @@ import {
|
|
|
12
12
|
Body,
|
|
13
13
|
CheckpointedL2Block,
|
|
14
14
|
CommitteeAttestation,
|
|
15
|
+
L2Block,
|
|
15
16
|
L2BlockHash,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
serializeValidateBlockResult,
|
|
17
|
+
type ValidateCheckpointResult,
|
|
18
|
+
deserializeValidateCheckpointResult,
|
|
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';
|
|
22
23
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
23
24
|
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
24
25
|
import {
|
|
@@ -27,6 +28,7 @@ import {
|
|
|
27
28
|
TxEffect,
|
|
28
29
|
TxHash,
|
|
29
30
|
TxReceipt,
|
|
31
|
+
TxStatus,
|
|
30
32
|
deserializeIndexedTxEffect,
|
|
31
33
|
serializeIndexedTxEffect,
|
|
32
34
|
} from '@aztec/stdlib/tx';
|
|
@@ -76,7 +78,7 @@ export type CheckpointData = {
|
|
|
76
78
|
};
|
|
77
79
|
|
|
78
80
|
/**
|
|
79
|
-
* LMDB
|
|
81
|
+
* LMDB-based block storage for the archiver.
|
|
80
82
|
*/
|
|
81
83
|
export class BlockStore {
|
|
82
84
|
/** Map block number to block data */
|
|
@@ -111,7 +113,10 @@ export class BlockStore {
|
|
|
111
113
|
|
|
112
114
|
#log = createLogger('archiver:block_store');
|
|
113
115
|
|
|
114
|
-
constructor(
|
|
116
|
+
constructor(
|
|
117
|
+
private db: AztecAsyncKVStore,
|
|
118
|
+
private l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
119
|
+
) {
|
|
115
120
|
this.#blocks = db.openMap('archiver_blocks');
|
|
116
121
|
this.#blockTxs = db.openMap('archiver_block_txs');
|
|
117
122
|
this.#txEffects = db.openMap('archiver_tx_effects');
|
|
@@ -124,12 +129,24 @@ export class BlockStore {
|
|
|
124
129
|
this.#checkpoints = db.openMap('archiver_checkpoints');
|
|
125
130
|
}
|
|
126
131
|
|
|
132
|
+
/**
|
|
133
|
+
* Computes the finalized block number based on the proven block number.
|
|
134
|
+
* A block is considered finalized when it's 2 epochs behind the proven block.
|
|
135
|
+
* TODO(#13569): Compute proper finalized block number based on L1 finalized block.
|
|
136
|
+
* TODO(palla/mbps): Even the provisional computation is wrong, since it should subtract checkpoints, not blocks
|
|
137
|
+
* @returns The finalized block number.
|
|
138
|
+
*/
|
|
139
|
+
async getFinalizedL2BlockNumber(): Promise<BlockNumber> {
|
|
140
|
+
const provenBlockNumber = await this.getProvenBlockNumber();
|
|
141
|
+
return BlockNumber(Math.max(provenBlockNumber - this.l1Constants.epochDuration * 2, 0));
|
|
142
|
+
}
|
|
143
|
+
|
|
127
144
|
/**
|
|
128
145
|
* Append new blocks to the store's list. All blocks must be for the 'current' checkpoint
|
|
129
146
|
* @param blocks - The L2 blocks to be added to the store.
|
|
130
147
|
* @returns True if the operation is successful.
|
|
131
148
|
*/
|
|
132
|
-
async addBlocks(blocks:
|
|
149
|
+
async addBlocks(blocks: L2Block[], opts: { force?: boolean } = {}): Promise<boolean> {
|
|
133
150
|
if (blocks.length === 0) {
|
|
134
151
|
return true;
|
|
135
152
|
}
|
|
@@ -182,7 +199,7 @@ export class BlockStore {
|
|
|
182
199
|
}
|
|
183
200
|
|
|
184
201
|
// Iterate over blocks array and insert them, checking that the block numbers and indexes are sequential. Also check they are for the correct checkpoint.
|
|
185
|
-
let previousBlock:
|
|
202
|
+
let previousBlock: L2Block | undefined = undefined;
|
|
186
203
|
for (const block of blocks) {
|
|
187
204
|
if (!opts.force && previousBlock) {
|
|
188
205
|
if (previousBlock.number + 1 !== block.number) {
|
|
@@ -241,7 +258,7 @@ export class BlockStore {
|
|
|
241
258
|
}
|
|
242
259
|
|
|
243
260
|
let previousBlockNumber: BlockNumber | undefined = undefined;
|
|
244
|
-
let previousBlock:
|
|
261
|
+
let previousBlock: L2Block | undefined = undefined;
|
|
245
262
|
|
|
246
263
|
// If we have a previous checkpoint then we need to get the previous block number
|
|
247
264
|
if (previousCheckpointData !== undefined) {
|
|
@@ -322,7 +339,7 @@ export class BlockStore {
|
|
|
322
339
|
});
|
|
323
340
|
}
|
|
324
341
|
|
|
325
|
-
private async addBlockToDatabase(block:
|
|
342
|
+
private async addBlockToDatabase(block: L2Block, checkpointNumber: number, indexWithinCheckpoint: number) {
|
|
326
343
|
const blockHash = L2BlockHash.fromField(await block.hash());
|
|
327
344
|
|
|
328
345
|
await this.#blocks.set(block.number, {
|
|
@@ -350,6 +367,23 @@ export class BlockStore {
|
|
|
350
367
|
await this.#blockArchiveIndex.set(block.archive.root.toString(), block.number);
|
|
351
368
|
}
|
|
352
369
|
|
|
370
|
+
/** Deletes a block and all associated data (tx effects, indices). */
|
|
371
|
+
private async deleteBlock(block: L2Block): Promise<void> {
|
|
372
|
+
// Delete the block from the main blocks map
|
|
373
|
+
await this.#blocks.delete(block.number);
|
|
374
|
+
|
|
375
|
+
// Delete all tx effects for this block
|
|
376
|
+
await Promise.all(block.body.txEffects.map(tx => this.#txEffects.delete(tx.txHash.toString())));
|
|
377
|
+
|
|
378
|
+
// Delete block txs mapping
|
|
379
|
+
const blockHash = (await block.hash()).toString();
|
|
380
|
+
await this.#blockTxs.delete(blockHash);
|
|
381
|
+
|
|
382
|
+
// Clean up indices
|
|
383
|
+
await this.#blockHashIndex.delete(blockHash);
|
|
384
|
+
await this.#blockArchiveIndex.delete(block.archive.root.toString());
|
|
385
|
+
}
|
|
386
|
+
|
|
353
387
|
/**
|
|
354
388
|
* Unwinds checkpoints from the database
|
|
355
389
|
* @param from - The tip of the chain, passed for verification purposes,
|
|
@@ -387,16 +421,11 @@ export class BlockStore {
|
|
|
387
421
|
this.#log.warn(`Cannot remove block ${blockNumber} from the store since we don't have it`);
|
|
388
422
|
continue;
|
|
389
423
|
}
|
|
390
|
-
await this.#blocks.delete(block.number);
|
|
391
|
-
await Promise.all(block.body.txEffects.map(tx => this.#txEffects.delete(tx.txHash.toString())));
|
|
392
|
-
const blockHash = (await block.hash()).toString();
|
|
393
|
-
await this.#blockTxs.delete(blockHash);
|
|
394
424
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
this.#log.debug(`Unwound block ${blockNumber} ${blockHash} for checkpoint ${checkpointNumber}`);
|
|
425
|
+
await this.deleteBlock(block);
|
|
426
|
+
this.#log.debug(
|
|
427
|
+
`Unwound block ${blockNumber} ${(await block.hash()).toString()} for checkpoint ${checkpointNumber}`,
|
|
428
|
+
);
|
|
400
429
|
}
|
|
401
430
|
}
|
|
402
431
|
|
|
@@ -437,7 +466,7 @@ export class BlockStore {
|
|
|
437
466
|
return data;
|
|
438
467
|
}
|
|
439
468
|
|
|
440
|
-
async getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<
|
|
469
|
+
async getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<L2Block[] | undefined> {
|
|
441
470
|
const checkpoint = await this.#checkpoints.getAsync(checkpointNumber);
|
|
442
471
|
if (!checkpoint) {
|
|
443
472
|
return undefined;
|
|
@@ -454,6 +483,61 @@ export class BlockStore {
|
|
|
454
483
|
return converted.filter(isDefined);
|
|
455
484
|
}
|
|
456
485
|
|
|
486
|
+
/**
|
|
487
|
+
* Gets all blocks that have the given slot number.
|
|
488
|
+
* Iterates backwards through blocks for efficiency since we usually query for the last slot.
|
|
489
|
+
* @param slotNumber - The slot number to search for.
|
|
490
|
+
* @returns All blocks with the given slot number, in ascending block number order.
|
|
491
|
+
*/
|
|
492
|
+
async getBlocksForSlot(slotNumber: SlotNumber): Promise<L2Block[]> {
|
|
493
|
+
const blocks: L2Block[] = [];
|
|
494
|
+
|
|
495
|
+
// Iterate backwards through all blocks and filter by slot number
|
|
496
|
+
// This is more efficient since we usually query for the most recent slot
|
|
497
|
+
for await (const [blockNumber, blockStorage] of this.#blocks.entriesAsync({ reverse: true })) {
|
|
498
|
+
const block = await this.getBlockFromBlockStorage(blockNumber, blockStorage);
|
|
499
|
+
const blockSlot = block?.header.globalVariables.slotNumber;
|
|
500
|
+
if (block && blockSlot === slotNumber) {
|
|
501
|
+
blocks.push(block);
|
|
502
|
+
} else if (blockSlot && blockSlot < slotNumber) {
|
|
503
|
+
break; // Blocks are stored in slot ascending order, so we can stop searching
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Reverse to return blocks in ascending order (block number order)
|
|
508
|
+
return blocks.reverse();
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Removes all blocks with block number > blockNumber.
|
|
513
|
+
* @param blockNumber - The block number to remove after.
|
|
514
|
+
* @returns The removed blocks (for event emission).
|
|
515
|
+
*/
|
|
516
|
+
async unwindBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]> {
|
|
517
|
+
return await this.db.transactionAsync(async () => {
|
|
518
|
+
const removedBlocks: L2Block[] = [];
|
|
519
|
+
|
|
520
|
+
// Get the latest block number to determine the range
|
|
521
|
+
const latestBlockNumber = await this.getLatestBlockNumber();
|
|
522
|
+
|
|
523
|
+
// Iterate from blockNumber + 1 to latestBlockNumber
|
|
524
|
+
for (let bn = blockNumber + 1; bn <= latestBlockNumber; bn++) {
|
|
525
|
+
const block = await this.getBlock(BlockNumber(bn));
|
|
526
|
+
|
|
527
|
+
if (block === undefined) {
|
|
528
|
+
this.#log.warn(`Cannot remove block ${bn} from the store since we don't have it`);
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
removedBlocks.push(block);
|
|
533
|
+
await this.deleteBlock(block);
|
|
534
|
+
this.#log.debug(`Removed block ${bn} ${(await block.hash()).toString()}`);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
return removedBlocks;
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
|
|
457
541
|
async getProvenBlockNumber(): Promise<BlockNumber> {
|
|
458
542
|
const provenCheckpointNumber = await this.getProvenCheckpointNumber();
|
|
459
543
|
if (provenCheckpointNumber === INITIAL_CHECKPOINT_NUMBER - 1) {
|
|
@@ -503,6 +587,34 @@ export class BlockStore {
|
|
|
503
587
|
);
|
|
504
588
|
}
|
|
505
589
|
|
|
590
|
+
/**
|
|
591
|
+
* Gets up to `limit` amount of Checkpointed L2 blocks starting from `from`.
|
|
592
|
+
* @param start - Number of the first block to return (inclusive).
|
|
593
|
+
* @param limit - The number of blocks to return.
|
|
594
|
+
* @returns The requested L2 blocks
|
|
595
|
+
*/
|
|
596
|
+
async *getCheckpointedBlocks(start: BlockNumber, limit: number): AsyncIterableIterator<CheckpointedL2Block> {
|
|
597
|
+
const checkpointCache = new Map<CheckpointNumber, CheckpointStorage>();
|
|
598
|
+
for await (const [blockNumber, blockStorage] of this.getBlockStorages(start, limit)) {
|
|
599
|
+
const block = await this.getBlockFromBlockStorage(blockNumber, blockStorage);
|
|
600
|
+
if (block) {
|
|
601
|
+
const checkpoint =
|
|
602
|
+
checkpointCache.get(CheckpointNumber(blockStorage.checkpointNumber)) ??
|
|
603
|
+
(await this.#checkpoints.getAsync(blockStorage.checkpointNumber));
|
|
604
|
+
if (checkpoint) {
|
|
605
|
+
checkpointCache.set(CheckpointNumber(blockStorage.checkpointNumber), checkpoint);
|
|
606
|
+
const checkpointedBlock = new CheckpointedL2Block(
|
|
607
|
+
CheckpointNumber(checkpoint.checkpointNumber),
|
|
608
|
+
block,
|
|
609
|
+
L1PublishedData.fromBuffer(checkpoint.l1),
|
|
610
|
+
checkpoint.attestations.map(buf => CommitteeAttestation.fromBuffer(buf)),
|
|
611
|
+
);
|
|
612
|
+
yield checkpointedBlock;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
506
618
|
async getCheckpointedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
507
619
|
const blockNumber = await this.#blockHashIndex.getAsync(blockHash.toString());
|
|
508
620
|
if (blockNumber === undefined) {
|
|
@@ -510,6 +622,7 @@ export class BlockStore {
|
|
|
510
622
|
}
|
|
511
623
|
return this.getCheckpointedBlock(BlockNumber(blockNumber));
|
|
512
624
|
}
|
|
625
|
+
|
|
513
626
|
async getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
514
627
|
const blockNumber = await this.#blockArchiveIndex.getAsync(archive.toString());
|
|
515
628
|
if (blockNumber === undefined) {
|
|
@@ -524,7 +637,7 @@ export class BlockStore {
|
|
|
524
637
|
* @param limit - The number of blocks to return.
|
|
525
638
|
* @returns The requested L2 blocks
|
|
526
639
|
*/
|
|
527
|
-
async *getBlocks(start: BlockNumber, limit: number): AsyncIterableIterator<
|
|
640
|
+
async *getBlocks(start: BlockNumber, limit: number): AsyncIterableIterator<L2Block> {
|
|
528
641
|
for await (const [blockNumber, blockStorage] of this.getBlockStorages(start, limit)) {
|
|
529
642
|
const block = await this.getBlockFromBlockStorage(blockNumber, blockStorage);
|
|
530
643
|
if (block) {
|
|
@@ -538,7 +651,7 @@ export class BlockStore {
|
|
|
538
651
|
* @param blockNumber - The number of the block to return.
|
|
539
652
|
* @returns The requested L2 block.
|
|
540
653
|
*/
|
|
541
|
-
async getBlock(blockNumber: BlockNumber): Promise<
|
|
654
|
+
async getBlock(blockNumber: BlockNumber): Promise<L2Block | undefined> {
|
|
542
655
|
const blockStorage = await this.#blocks.getAsync(blockNumber);
|
|
543
656
|
if (!blockStorage || !blockStorage.header) {
|
|
544
657
|
return Promise.resolve(undefined);
|
|
@@ -551,7 +664,7 @@ export class BlockStore {
|
|
|
551
664
|
* @param blockHash - The hash of the block to return.
|
|
552
665
|
* @returns The requested L2 block.
|
|
553
666
|
*/
|
|
554
|
-
async getBlockByHash(blockHash: L2BlockHash): Promise<
|
|
667
|
+
async getBlockByHash(blockHash: L2BlockHash): Promise<L2Block | undefined> {
|
|
555
668
|
const blockNumber = await this.#blockHashIndex.getAsync(blockHash.toString());
|
|
556
669
|
if (blockNumber === undefined) {
|
|
557
670
|
return undefined;
|
|
@@ -564,7 +677,7 @@ export class BlockStore {
|
|
|
564
677
|
* @param archive - The archive root of the block to return.
|
|
565
678
|
* @returns The requested L2 block.
|
|
566
679
|
*/
|
|
567
|
-
async getBlockByArchive(archive: Fr): Promise<
|
|
680
|
+
async getBlockByArchive(archive: Fr): Promise<L2Block | undefined> {
|
|
568
681
|
const blockNumber = await this.#blockArchiveIndex.getAsync(archive.toString());
|
|
569
682
|
if (blockNumber === undefined) {
|
|
570
683
|
return undefined;
|
|
@@ -640,10 +753,11 @@ export class BlockStore {
|
|
|
640
753
|
private async getBlockFromBlockStorage(
|
|
641
754
|
blockNumber: number,
|
|
642
755
|
blockStorage: BlockStorage,
|
|
643
|
-
): Promise<
|
|
756
|
+
): Promise<L2Block | undefined> {
|
|
644
757
|
const header = BlockHeader.fromBuffer(blockStorage.header);
|
|
645
758
|
const archive = AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive);
|
|
646
759
|
const blockHash = blockStorage.blockHash;
|
|
760
|
+
header.setHash(Fr.fromBuffer(blockHash));
|
|
647
761
|
const blockHashString = bufferToHex(blockHash);
|
|
648
762
|
const blockTxsBuffer = await this.#blockTxs.getAsync(blockHashString);
|
|
649
763
|
if (blockTxsBuffer === undefined) {
|
|
@@ -663,12 +777,12 @@ export class BlockStore {
|
|
|
663
777
|
txEffects.push(deserializeIndexedTxEffect(txEffect).data);
|
|
664
778
|
}
|
|
665
779
|
const body = new Body(txEffects);
|
|
666
|
-
const block = new
|
|
780
|
+
const block = new L2Block(
|
|
667
781
|
archive,
|
|
668
782
|
header,
|
|
669
783
|
body,
|
|
670
784
|
CheckpointNumber(blockStorage.checkpointNumber!),
|
|
671
|
-
blockStorage.indexWithinCheckpoint,
|
|
785
|
+
IndexWithinCheckpoint(blockStorage.indexWithinCheckpoint),
|
|
672
786
|
);
|
|
673
787
|
|
|
674
788
|
if (block.number !== blockNumber) {
|
|
@@ -705,13 +819,34 @@ export class BlockStore {
|
|
|
705
819
|
return undefined;
|
|
706
820
|
}
|
|
707
821
|
|
|
822
|
+
const blockNumber = BlockNumber(txEffect.l2BlockNumber);
|
|
823
|
+
|
|
824
|
+
// Use existing archiver methods to determine finalization level
|
|
825
|
+
const [provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber] = await Promise.all([
|
|
826
|
+
this.getProvenBlockNumber(),
|
|
827
|
+
this.getCheckpointedL2BlockNumber(),
|
|
828
|
+
this.getFinalizedL2BlockNumber(),
|
|
829
|
+
]);
|
|
830
|
+
|
|
831
|
+
let status: TxStatus;
|
|
832
|
+
if (blockNumber <= finalizedBlockNumber) {
|
|
833
|
+
status = TxStatus.FINALIZED;
|
|
834
|
+
} else if (blockNumber <= provenBlockNumber) {
|
|
835
|
+
status = TxStatus.PROVEN;
|
|
836
|
+
} else if (blockNumber <= checkpointedBlockNumber) {
|
|
837
|
+
status = TxStatus.CHECKPOINTED;
|
|
838
|
+
} else {
|
|
839
|
+
status = TxStatus.PROPOSED;
|
|
840
|
+
}
|
|
841
|
+
|
|
708
842
|
return new TxReceipt(
|
|
709
843
|
txHash,
|
|
710
|
-
|
|
711
|
-
|
|
844
|
+
status,
|
|
845
|
+
TxReceipt.executionResultFromRevertCode(txEffect.data.revertCode),
|
|
846
|
+
undefined,
|
|
712
847
|
txEffect.data.transactionFee.toBigInt(),
|
|
713
848
|
txEffect.l2BlockHash,
|
|
714
|
-
|
|
849
|
+
blockNumber,
|
|
715
850
|
);
|
|
716
851
|
}
|
|
717
852
|
|
|
@@ -799,21 +934,21 @@ export class BlockStore {
|
|
|
799
934
|
* Gets the pending chain validation status.
|
|
800
935
|
* @returns The validation status or undefined if not set.
|
|
801
936
|
*/
|
|
802
|
-
async getPendingChainValidationStatus(): Promise<
|
|
937
|
+
async getPendingChainValidationStatus(): Promise<ValidateCheckpointResult | undefined> {
|
|
803
938
|
const buffer = await this.#pendingChainValidationStatus.getAsync();
|
|
804
939
|
if (!buffer) {
|
|
805
940
|
return undefined;
|
|
806
941
|
}
|
|
807
|
-
return
|
|
942
|
+
return deserializeValidateCheckpointResult(buffer);
|
|
808
943
|
}
|
|
809
944
|
|
|
810
945
|
/**
|
|
811
946
|
* Sets the pending chain validation status.
|
|
812
947
|
* @param status - The validation status to store.
|
|
813
948
|
*/
|
|
814
|
-
async setPendingChainValidationStatus(status:
|
|
949
|
+
async setPendingChainValidationStatus(status: ValidateCheckpointResult | undefined): Promise<void> {
|
|
815
950
|
if (status) {
|
|
816
|
-
const buffer =
|
|
951
|
+
const buffer = serializeValidateCheckpointResult(status);
|
|
817
952
|
await this.#pendingChainValidationStatus.set(buffer);
|
|
818
953
|
} else {
|
|
819
954
|
await this.#pendingChainValidationStatus.delete();
|
|
@@ -12,7 +12,7 @@ import type {
|
|
|
12
12
|
import { Vector } from '@aztec/stdlib/types';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* LMDB
|
|
15
|
+
* LMDB-based contract class storage for the archiver.
|
|
16
16
|
*/
|
|
17
17
|
export class ContractClassStore {
|
|
18
18
|
#contractClasses: AztecAsyncMap<string, Buffer>;
|
|
@@ -12,7 +12,7 @@ import type { UInt64 } from '@aztec/stdlib/types';
|
|
|
12
12
|
type ContractInstanceUpdateKey = [string, string] | [string, string, number];
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* LMDB
|
|
15
|
+
* LMDB-based contract instance storage for the archiver.
|
|
16
16
|
*/
|
|
17
17
|
export class ContractInstanceStore {
|
|
18
18
|
#contractInstances: AztecAsyncMap<string, Buffer>;
|