@aztec/archiver 0.0.1-commit.96bb3f7 → 0.0.1-commit.96dac018d
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 +139 -0
- package/dest/archiver.d.ts.map +1 -0
- package/dest/archiver.js +699 -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} +9 -0
- package/dest/errors.d.ts +41 -0
- package/dest/errors.d.ts.map +1 -0
- package/dest/{archiver/errors.js → errors.js} +8 -0
- package/dest/factory.d.ts +9 -7
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +91 -11
- package/dest/index.d.ts +11 -4
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +9 -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 +35 -32
- package/dest/l1/calldata_retriever.d.ts +135 -0
- package/dest/l1/calldata_retriever.d.ts.map +1 -0
- package/dest/l1/calldata_retriever.js +402 -0
- package/dest/l1/data_retrieval.d.ts +85 -0
- package/dest/l1/data_retrieval.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/data_retrieval.js +43 -66
- 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 +5 -5
- package/dest/l1/spire_proposer.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/spire_proposer.js +9 -17
- 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 +6 -3
- package/dest/l1/validate_trace.d.ts.map +1 -0
- package/dest/{archiver/l1 → l1}/validate_trace.js +13 -9
- package/dest/modules/data_source_base.d.ts +89 -0
- package/dest/modules/data_source_base.d.ts.map +1 -0
- package/dest/modules/data_source_base.js +216 -0
- package/dest/modules/data_store_updater.d.ts +80 -0
- package/dest/modules/data_store_updater.d.ts.map +1 -0
- package/dest/modules/data_store_updater.js +323 -0
- package/dest/modules/instrumentation.d.ts +50 -0
- package/dest/modules/instrumentation.d.ts.map +1 -0
- package/dest/{archiver → modules}/instrumentation.js +36 -12
- package/dest/modules/l1_synchronizer.d.ts +71 -0
- package/dest/modules/l1_synchronizer.d.ts.map +1 -0
- package/dest/modules/l1_synchronizer.js +1117 -0
- package/dest/{archiver → modules}/validation.d.ts +1 -1
- package/dest/modules/validation.d.ts.map +1 -0
- package/dest/{archiver → modules}/validation.js +6 -0
- package/dest/store/block_store.d.ts +196 -0
- package/dest/store/block_store.d.ts.map +1 -0
- package/dest/{archiver/kv_archiver_store → store}/block_store.js +207 -60
- 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 +12 -8
- 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 +354 -0
- package/dest/store/kv_archiver_store.d.ts.map +1 -0
- package/dest/store/kv_archiver_store.js +464 -0
- package/dest/store/l2_tips_cache.d.ts +19 -0
- package/dest/store/l2_tips_cache.d.ts.map +1 -0
- package/dest/store/l2_tips_cache.js +89 -0
- package/dest/store/log_store.d.ts +54 -0
- package/dest/store/log_store.d.ts.map +1 -0
- package/dest/{archiver/kv_archiver_store → store}/log_store.js +146 -91
- 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 +195 -0
- package/dest/test/fake_l1_state.d.ts.map +1 -0
- package/dest/test/fake_l1_state.js +421 -0
- package/dest/test/index.d.ts +2 -1
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/index.js +4 -1
- 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 +3 -3
- package/dest/test/mock_l2_block_source.d.ts +35 -17
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +177 -74
- package/dest/test/mock_structs.d.ts +78 -3
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +140 -7
- package/dest/test/noop_l1_archiver.d.ts +23 -0
- package/dest/test/noop_l1_archiver.d.ts.map +1 -0
- package/dest/test/noop_l1_archiver.js +68 -0
- package/package.json +16 -17
- package/src/archiver.ts +443 -0
- package/src/{archiver/config.ts → config.ts} +11 -0
- package/src/{archiver/errors.ts → errors.ts} +12 -0
- package/src/factory.ts +139 -11
- package/src/index.ts +11 -3
- package/src/interfaces.ts +9 -0
- package/src/l1/README.md +55 -0
- package/src/{archiver/l1 → l1}/bin/retrieve-calldata.ts +45 -33
- package/src/l1/calldata_retriever.ts +511 -0
- package/src/{archiver/l1 → l1}/data_retrieval.ts +61 -88
- package/src/{archiver/l1 → l1}/spire_proposer.ts +7 -15
- package/src/{archiver/l1 → l1}/validate_trace.ts +24 -6
- package/src/modules/data_source_base.ts +328 -0
- package/src/modules/data_store_updater.ts +448 -0
- package/src/{archiver → modules}/instrumentation.ts +46 -14
- package/src/modules/l1_synchronizer.ts +933 -0
- package/src/{archiver → modules}/validation.ts +5 -0
- package/src/{archiver/kv_archiver_store → store}/block_store.ts +258 -93
- package/src/{archiver/kv_archiver_store → store}/contract_class_store.ts +12 -8
- package/src/{archiver/kv_archiver_store → store}/contract_instance_store.ts +1 -1
- package/src/{archiver/kv_archiver_store → store}/kv_archiver_store.ts +267 -38
- package/src/store/l2_tips_cache.ts +89 -0
- package/src/{archiver/kv_archiver_store → store}/log_store.ts +242 -121
- package/src/test/fake_l1_state.ts +657 -0
- package/src/test/index.ts +4 -0
- package/src/test/mock_archiver.ts +4 -3
- package/src/test/mock_l2_block_source.ts +218 -90
- package/src/test/mock_structs.ts +269 -8
- package/src/test/noop_l1_archiver.ts +109 -0
- package/dest/archiver/archiver.d.ts +0 -307
- package/dest/archiver/archiver.d.ts.map +0 -1
- package/dest/archiver/archiver.js +0 -2102
- package/dest/archiver/archiver_store.d.ts +0 -315
- 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 +0 -36
- 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 -164
- 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 -159
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +0 -316
- 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 +0 -112
- package/dest/archiver/l1/calldata_retriever.d.ts.map +0 -1
- package/dest/archiver/l1/calldata_retriever.js +0 -471
- 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.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 -2265
- package/src/archiver/archiver_store.ts +0 -380
- package/src/archiver/archiver_store_test_suite.ts +0 -2842
- package/src/archiver/index.ts +0 -6
- package/src/archiver/l1/README.md +0 -98
- package/src/archiver/l1/calldata_retriever.ts +0 -641
- package/src/rpc/index.ts +0 -16
- /package/dest/{archiver/l1 → l1}/debug_tx.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/l1 → l1}/debug_tx.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
|
@@ -61,6 +61,11 @@ 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
71
|
const failedValidationResult = <TReason extends ValidateCheckpointNegativeResult['reason']>(reason: TReason) => ({
|
|
@@ -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';
|
|
@@ -9,16 +9,18 @@ import { isDefined } from '@aztec/foundation/types';
|
|
|
9
9
|
import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncSingleton, Range } from '@aztec/kv-store';
|
|
10
10
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
11
11
|
import {
|
|
12
|
+
type BlockData,
|
|
13
|
+
BlockHash,
|
|
12
14
|
Body,
|
|
13
15
|
CheckpointedL2Block,
|
|
14
16
|
CommitteeAttestation,
|
|
15
|
-
|
|
16
|
-
L2BlockNew,
|
|
17
|
+
L2Block,
|
|
17
18
|
type ValidateCheckpointResult,
|
|
18
19
|
deserializeValidateCheckpointResult,
|
|
19
20
|
serializeValidateCheckpointResult,
|
|
20
21
|
} from '@aztec/stdlib/block';
|
|
21
|
-
import { L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
22
|
+
import { type CheckpointData, L1PublishedData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
23
|
+
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
22
24
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
23
25
|
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
24
26
|
import {
|
|
@@ -27,6 +29,7 @@ import {
|
|
|
27
29
|
TxEffect,
|
|
28
30
|
TxHash,
|
|
29
31
|
TxReceipt,
|
|
32
|
+
TxStatus,
|
|
30
33
|
deserializeIndexedTxEffect,
|
|
31
34
|
serializeIndexedTxEffect,
|
|
32
35
|
} from '@aztec/stdlib/tx';
|
|
@@ -36,6 +39,7 @@ import {
|
|
|
36
39
|
BlockIndexNotSequentialError,
|
|
37
40
|
BlockNotFoundError,
|
|
38
41
|
BlockNumberNotSequentialError,
|
|
42
|
+
CannotOverwriteCheckpointedBlockError,
|
|
39
43
|
CheckpointNotFoundError,
|
|
40
44
|
CheckpointNumberNotConsistentError,
|
|
41
45
|
CheckpointNumberNotSequentialError,
|
|
@@ -58,25 +62,18 @@ type BlockStorage = {
|
|
|
58
62
|
type CheckpointStorage = {
|
|
59
63
|
header: Buffer;
|
|
60
64
|
archive: Buffer;
|
|
65
|
+
checkpointOutHash: Buffer;
|
|
61
66
|
checkpointNumber: number;
|
|
62
67
|
startBlock: number;
|
|
63
|
-
|
|
68
|
+
blockCount: number;
|
|
64
69
|
l1: Buffer;
|
|
65
70
|
attestations: Buffer[];
|
|
66
71
|
};
|
|
67
72
|
|
|
68
|
-
export type
|
|
69
|
-
checkpointNumber: CheckpointNumber;
|
|
70
|
-
header: CheckpointHeader;
|
|
71
|
-
archive: AppendOnlyTreeSnapshot;
|
|
72
|
-
startBlock: number;
|
|
73
|
-
numBlocks: number;
|
|
74
|
-
l1: L1PublishedData;
|
|
75
|
-
attestations: Buffer[];
|
|
76
|
-
};
|
|
73
|
+
export type RemoveCheckpointsResult = { blocksRemoved: L2Block[] | undefined };
|
|
77
74
|
|
|
78
75
|
/**
|
|
79
|
-
* LMDB
|
|
76
|
+
* LMDB-based block storage for the archiver.
|
|
80
77
|
*/
|
|
81
78
|
export class BlockStore {
|
|
82
79
|
/** Map block number to block data */
|
|
@@ -85,6 +82,9 @@ export class BlockStore {
|
|
|
85
82
|
/** Map checkpoint number to checkpoint data */
|
|
86
83
|
#checkpoints: AztecAsyncMap<number, CheckpointStorage>;
|
|
87
84
|
|
|
85
|
+
/** Map slot number to checkpoint number, for looking up checkpoints by slot range. */
|
|
86
|
+
#slotToCheckpoint: AztecAsyncMap<number, number>;
|
|
87
|
+
|
|
88
88
|
/** Map block hash to list of tx hashes */
|
|
89
89
|
#blockTxs: AztecAsyncMap<string, Buffer>;
|
|
90
90
|
|
|
@@ -111,7 +111,10 @@ export class BlockStore {
|
|
|
111
111
|
|
|
112
112
|
#log = createLogger('archiver:block_store');
|
|
113
113
|
|
|
114
|
-
constructor(
|
|
114
|
+
constructor(
|
|
115
|
+
private db: AztecAsyncKVStore,
|
|
116
|
+
private l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
117
|
+
) {
|
|
115
118
|
this.#blocks = db.openMap('archiver_blocks');
|
|
116
119
|
this.#blockTxs = db.openMap('archiver_block_txs');
|
|
117
120
|
this.#txEffects = db.openMap('archiver_tx_effects');
|
|
@@ -122,14 +125,29 @@ export class BlockStore {
|
|
|
122
125
|
this.#lastProvenCheckpoint = db.openSingleton('archiver_last_proven_l2_checkpoint');
|
|
123
126
|
this.#pendingChainValidationStatus = db.openSingleton('archiver_pending_chain_validation_status');
|
|
124
127
|
this.#checkpoints = db.openMap('archiver_checkpoints');
|
|
128
|
+
this.#slotToCheckpoint = db.openMap('archiver_slot_to_checkpoint');
|
|
125
129
|
}
|
|
126
130
|
|
|
127
131
|
/**
|
|
128
|
-
*
|
|
129
|
-
*
|
|
132
|
+
* Computes the finalized block number based on the proven block number.
|
|
133
|
+
* A block is considered finalized when it's 2 epochs behind the proven block.
|
|
134
|
+
* TODO(#13569): Compute proper finalized block number based on L1 finalized block.
|
|
135
|
+
* TODO(palla/mbps): Even the provisional computation is wrong, since it should subtract checkpoints, not blocks
|
|
136
|
+
* @returns The finalized block number.
|
|
137
|
+
*/
|
|
138
|
+
async getFinalizedL2BlockNumber(): Promise<BlockNumber> {
|
|
139
|
+
const provenBlockNumber = await this.getProvenBlockNumber();
|
|
140
|
+
return BlockNumber(Math.max(provenBlockNumber - this.l1Constants.epochDuration * 2, 0));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Append new proposed blocks to the store's list. All blocks must be for the 'current' checkpoint.
|
|
145
|
+
* These are uncheckpointed blocks that have been proposed by the sequencer but not yet included in a checkpoint on L1.
|
|
146
|
+
* For checkpointed blocks (already published to L1), use addCheckpoints() instead.
|
|
147
|
+
* @param blocks - The proposed L2 blocks to be added to the store.
|
|
130
148
|
* @returns True if the operation is successful.
|
|
131
149
|
*/
|
|
132
|
-
async
|
|
150
|
+
async addProposedBlocks(blocks: L2Block[], opts: { force?: boolean } = {}): Promise<boolean> {
|
|
133
151
|
if (blocks.length === 0) {
|
|
134
152
|
return true;
|
|
135
153
|
}
|
|
@@ -145,6 +163,12 @@ export class BlockStore {
|
|
|
145
163
|
const previousBlockNumber = await this.getLatestBlockNumber();
|
|
146
164
|
const previousCheckpointNumber = await this.getLatestCheckpointNumber();
|
|
147
165
|
|
|
166
|
+
// Verify we're not overwriting checkpointed blocks
|
|
167
|
+
const lastCheckpointedBlockNumber = await this.getCheckpointedL2BlockNumber();
|
|
168
|
+
if (!opts.force && firstBlockNumber <= lastCheckpointedBlockNumber) {
|
|
169
|
+
throw new CannotOverwriteCheckpointedBlockError(firstBlockNumber, lastCheckpointedBlockNumber);
|
|
170
|
+
}
|
|
171
|
+
|
|
148
172
|
// Check that the first block number is the expected one
|
|
149
173
|
if (!opts.force && previousBlockNumber !== firstBlockNumber - 1) {
|
|
150
174
|
throw new InitialBlockNumberNotSequentialError(firstBlockNumber, previousBlockNumber);
|
|
@@ -182,7 +206,7 @@ export class BlockStore {
|
|
|
182
206
|
}
|
|
183
207
|
|
|
184
208
|
// 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:
|
|
209
|
+
let previousBlock: L2Block | undefined = undefined;
|
|
186
210
|
for (const block of blocks) {
|
|
187
211
|
if (!opts.force && previousBlock) {
|
|
188
212
|
if (previousBlock.number + 1 !== block.number) {
|
|
@@ -241,11 +265,11 @@ export class BlockStore {
|
|
|
241
265
|
}
|
|
242
266
|
|
|
243
267
|
let previousBlockNumber: BlockNumber | undefined = undefined;
|
|
244
|
-
let previousBlock:
|
|
268
|
+
let previousBlock: L2Block | undefined = undefined;
|
|
245
269
|
|
|
246
270
|
// If we have a previous checkpoint then we need to get the previous block number
|
|
247
271
|
if (previousCheckpointData !== undefined) {
|
|
248
|
-
previousBlockNumber = BlockNumber(previousCheckpointData.startBlock + previousCheckpointData.
|
|
272
|
+
previousBlockNumber = BlockNumber(previousCheckpointData.startBlock + previousCheckpointData.blockCount - 1);
|
|
249
273
|
previousBlock = await this.getBlock(previousBlockNumber);
|
|
250
274
|
if (previousBlock === undefined) {
|
|
251
275
|
// We should be able to get the required previous block
|
|
@@ -309,12 +333,16 @@ export class BlockStore {
|
|
|
309
333
|
await this.#checkpoints.set(checkpoint.checkpoint.number, {
|
|
310
334
|
header: checkpoint.checkpoint.header.toBuffer(),
|
|
311
335
|
archive: checkpoint.checkpoint.archive.toBuffer(),
|
|
336
|
+
checkpointOutHash: checkpoint.checkpoint.getCheckpointOutHash().toBuffer(),
|
|
312
337
|
l1: checkpoint.l1.toBuffer(),
|
|
313
338
|
attestations: checkpoint.attestations.map(attestation => attestation.toBuffer()),
|
|
314
339
|
checkpointNumber: checkpoint.checkpoint.number,
|
|
315
340
|
startBlock: checkpoint.checkpoint.blocks[0].number,
|
|
316
|
-
|
|
341
|
+
blockCount: checkpoint.checkpoint.blocks.length,
|
|
317
342
|
});
|
|
343
|
+
|
|
344
|
+
// Update slot-to-checkpoint index
|
|
345
|
+
await this.#slotToCheckpoint.set(checkpoint.checkpoint.header.slotNumber, checkpoint.checkpoint.number);
|
|
318
346
|
}
|
|
319
347
|
|
|
320
348
|
await this.#lastSynchedL1Block.set(checkpoints[checkpoints.length - 1].l1.blockNumber);
|
|
@@ -322,8 +350,8 @@ export class BlockStore {
|
|
|
322
350
|
});
|
|
323
351
|
}
|
|
324
352
|
|
|
325
|
-
private async addBlockToDatabase(block:
|
|
326
|
-
const blockHash =
|
|
353
|
+
private async addBlockToDatabase(block: L2Block, checkpointNumber: number, indexWithinCheckpoint: number) {
|
|
354
|
+
const blockHash = await block.hash();
|
|
327
355
|
|
|
328
356
|
await this.#blocks.set(block.number, {
|
|
329
357
|
header: block.header.toBuffer(),
|
|
@@ -350,57 +378,71 @@ export class BlockStore {
|
|
|
350
378
|
await this.#blockArchiveIndex.set(block.archive.root.toString(), block.number);
|
|
351
379
|
}
|
|
352
380
|
|
|
381
|
+
/** Deletes a block and all associated data (tx effects, indices). */
|
|
382
|
+
private async deleteBlock(block: L2Block): Promise<void> {
|
|
383
|
+
// Delete the block from the main blocks map
|
|
384
|
+
await this.#blocks.delete(block.number);
|
|
385
|
+
|
|
386
|
+
// Delete all tx effects for this block
|
|
387
|
+
await Promise.all(block.body.txEffects.map(tx => this.#txEffects.delete(tx.txHash.toString())));
|
|
388
|
+
|
|
389
|
+
// Delete block txs mapping
|
|
390
|
+
const blockHash = (await block.hash()).toString();
|
|
391
|
+
await this.#blockTxs.delete(blockHash);
|
|
392
|
+
|
|
393
|
+
// Clean up indices
|
|
394
|
+
await this.#blockHashIndex.delete(blockHash);
|
|
395
|
+
await this.#blockArchiveIndex.delete(block.archive.root.toString());
|
|
396
|
+
}
|
|
397
|
+
|
|
353
398
|
/**
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
* @param checkpointsToUnwind - The number of checkpoints we are to unwind
|
|
358
|
-
* @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.
|
|
359
402
|
*/
|
|
360
|
-
async
|
|
403
|
+
async removeCheckpointsAfter(checkpointNumber: CheckpointNumber): Promise<RemoveCheckpointsResult> {
|
|
361
404
|
return await this.db.transactionAsync(async () => {
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
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 };
|
|
365
410
|
}
|
|
366
411
|
|
|
412
|
+
// If the proven checkpoint is beyond the target, update it
|
|
367
413
|
const proven = await this.getProvenCheckpointNumber();
|
|
368
|
-
if (
|
|
369
|
-
|
|
414
|
+
if (proven > checkpointNumber) {
|
|
415
|
+
this.#log.warn(`Updating proven checkpoint ${proven} to last valid checkpoint ${checkpointNumber}`);
|
|
416
|
+
await this.setProvenCheckpointNumber(checkpointNumber);
|
|
370
417
|
}
|
|
371
418
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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`);
|
|
379
427
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
for (let blockNumber = checkpoint.startBlock; blockNumber <= maxBlock; blockNumber++) {
|
|
384
|
-
const block = await this.getBlock(BlockNumber(blockNumber));
|
|
385
|
-
|
|
386
|
-
if (block === undefined) {
|
|
387
|
-
this.#log.warn(`Cannot remove block ${blockNumber} from the store since we don't have it`);
|
|
388
|
-
continue;
|
|
389
|
-
}
|
|
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);
|
|
428
|
+
lastBlockToKeep = BlockNumber(targetCheckpoint.startBlock + targetCheckpoint.blockCount - 1);
|
|
429
|
+
}
|
|
394
430
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
await this.#blockArchiveIndex.delete(block.archive.root.toString());
|
|
431
|
+
// Remove all blocks after lastBlockToKeep (both checkpointed and uncheckpointed)
|
|
432
|
+
const blocksRemoved = await this.removeBlocksAfter(lastBlockToKeep);
|
|
398
433
|
|
|
399
|
-
|
|
434
|
+
// Remove all checkpoints after the target
|
|
435
|
+
for (let c = latestCheckpointNumber; c > checkpointNumber; c = CheckpointNumber(c - 1)) {
|
|
436
|
+
const checkpointStorage = await this.#checkpoints.getAsync(c);
|
|
437
|
+
if (checkpointStorage) {
|
|
438
|
+
const slotNumber = CheckpointHeader.fromBuffer(checkpointStorage.header).slotNumber;
|
|
439
|
+
await this.#slotToCheckpoint.delete(slotNumber);
|
|
400
440
|
}
|
|
441
|
+
await this.#checkpoints.delete(c);
|
|
442
|
+
this.#log.debug(`Removed checkpoint ${c}`);
|
|
401
443
|
}
|
|
402
444
|
|
|
403
|
-
return
|
|
445
|
+
return { blocksRemoved };
|
|
404
446
|
});
|
|
405
447
|
}
|
|
406
448
|
|
|
@@ -424,20 +466,35 @@ export class BlockStore {
|
|
|
424
466
|
return checkpoints;
|
|
425
467
|
}
|
|
426
468
|
|
|
427
|
-
|
|
428
|
-
|
|
469
|
+
/** Returns checkpoint data for all checkpoints whose slot falls within the given range (inclusive). */
|
|
470
|
+
async getCheckpointDataForSlotRange(startSlot: SlotNumber, endSlot: SlotNumber): Promise<CheckpointData[]> {
|
|
471
|
+
const result: CheckpointData[] = [];
|
|
472
|
+
for await (const [, checkpointNumber] of this.#slotToCheckpoint.entriesAsync({
|
|
473
|
+
start: startSlot,
|
|
474
|
+
end: endSlot + 1,
|
|
475
|
+
})) {
|
|
476
|
+
const checkpointStorage = await this.#checkpoints.getAsync(checkpointNumber);
|
|
477
|
+
if (checkpointStorage) {
|
|
478
|
+
result.push(this.checkpointDataFromCheckpointStorage(checkpointStorage));
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return result;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
private checkpointDataFromCheckpointStorage(checkpointStorage: CheckpointStorage): CheckpointData {
|
|
485
|
+
return {
|
|
429
486
|
header: CheckpointHeader.fromBuffer(checkpointStorage.header),
|
|
430
487
|
archive: AppendOnlyTreeSnapshot.fromBuffer(checkpointStorage.archive),
|
|
488
|
+
checkpointOutHash: Fr.fromBuffer(checkpointStorage.checkpointOutHash),
|
|
431
489
|
checkpointNumber: CheckpointNumber(checkpointStorage.checkpointNumber),
|
|
432
|
-
startBlock: checkpointStorage.startBlock,
|
|
433
|
-
|
|
490
|
+
startBlock: BlockNumber(checkpointStorage.startBlock),
|
|
491
|
+
blockCount: checkpointStorage.blockCount,
|
|
434
492
|
l1: L1PublishedData.fromBuffer(checkpointStorage.l1),
|
|
435
|
-
attestations: checkpointStorage.attestations,
|
|
493
|
+
attestations: checkpointStorage.attestations.map(buf => CommitteeAttestation.fromBuffer(buf)),
|
|
436
494
|
};
|
|
437
|
-
return data;
|
|
438
495
|
}
|
|
439
496
|
|
|
440
|
-
async getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<
|
|
497
|
+
async getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<L2Block[] | undefined> {
|
|
441
498
|
const checkpoint = await this.#checkpoints.getAsync(checkpointNumber);
|
|
442
499
|
if (!checkpoint) {
|
|
443
500
|
return undefined;
|
|
@@ -446,7 +503,7 @@ export class BlockStore {
|
|
|
446
503
|
const blocksForCheckpoint = await toArray(
|
|
447
504
|
this.#blocks.entriesAsync({
|
|
448
505
|
start: checkpoint.startBlock,
|
|
449
|
-
end: checkpoint.startBlock + checkpoint.
|
|
506
|
+
end: checkpoint.startBlock + checkpoint.blockCount,
|
|
450
507
|
}),
|
|
451
508
|
);
|
|
452
509
|
|
|
@@ -454,6 +511,62 @@ export class BlockStore {
|
|
|
454
511
|
return converted.filter(isDefined);
|
|
455
512
|
}
|
|
456
513
|
|
|
514
|
+
/**
|
|
515
|
+
* Gets all blocks that have the given slot number.
|
|
516
|
+
* Iterates backwards through blocks for efficiency since we usually query for the last slot.
|
|
517
|
+
* @param slotNumber - The slot number to search for.
|
|
518
|
+
* @returns All blocks with the given slot number, in ascending block number order.
|
|
519
|
+
*/
|
|
520
|
+
async getBlocksForSlot(slotNumber: SlotNumber): Promise<L2Block[]> {
|
|
521
|
+
const blocks: L2Block[] = [];
|
|
522
|
+
|
|
523
|
+
// Iterate backwards through all blocks and filter by slot number
|
|
524
|
+
// This is more efficient since we usually query for the most recent slot
|
|
525
|
+
for await (const [blockNumber, blockStorage] of this.#blocks.entriesAsync({ reverse: true })) {
|
|
526
|
+
const block = await this.getBlockFromBlockStorage(blockNumber, blockStorage);
|
|
527
|
+
const blockSlot = block?.header.globalVariables.slotNumber;
|
|
528
|
+
if (block && blockSlot === slotNumber) {
|
|
529
|
+
blocks.push(block);
|
|
530
|
+
} else if (blockSlot && blockSlot < slotNumber) {
|
|
531
|
+
break; // Blocks are stored in slot ascending order, so we can stop searching
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Reverse to return blocks in ascending order (block number order)
|
|
536
|
+
return blocks.reverse();
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/**
|
|
540
|
+
* Removes all blocks with block number > blockNumber.
|
|
541
|
+
* Does not remove any associated checkpoints.
|
|
542
|
+
* @param blockNumber - The block number to remove after.
|
|
543
|
+
* @returns The removed blocks (for event emission).
|
|
544
|
+
*/
|
|
545
|
+
async removeBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]> {
|
|
546
|
+
return await this.db.transactionAsync(async () => {
|
|
547
|
+
const removedBlocks: L2Block[] = [];
|
|
548
|
+
|
|
549
|
+
// Get the latest block number to determine the range
|
|
550
|
+
const latestBlockNumber = await this.getLatestBlockNumber();
|
|
551
|
+
|
|
552
|
+
// Iterate from blockNumber + 1 to latestBlockNumber
|
|
553
|
+
for (let bn = blockNumber + 1; bn <= latestBlockNumber; bn++) {
|
|
554
|
+
const block = await this.getBlock(BlockNumber(bn));
|
|
555
|
+
|
|
556
|
+
if (block === undefined) {
|
|
557
|
+
this.#log.warn(`Cannot remove block ${bn} from the store since we don't have it`);
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
removedBlocks.push(block);
|
|
562
|
+
await this.deleteBlock(block);
|
|
563
|
+
this.#log.debug(`Removed block ${bn} ${(await block.hash()).toString()}`);
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return removedBlocks;
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
|
|
457
570
|
async getProvenBlockNumber(): Promise<BlockNumber> {
|
|
458
571
|
const provenCheckpointNumber = await this.getProvenCheckpointNumber();
|
|
459
572
|
if (provenCheckpointNumber === INITIAL_CHECKPOINT_NUMBER - 1) {
|
|
@@ -463,7 +576,7 @@ export class BlockStore {
|
|
|
463
576
|
if (!checkpointStorage) {
|
|
464
577
|
throw new CheckpointNotFoundError(provenCheckpointNumber);
|
|
465
578
|
} else {
|
|
466
|
-
return BlockNumber(checkpointStorage.startBlock + checkpointStorage.
|
|
579
|
+
return BlockNumber(checkpointStorage.startBlock + checkpointStorage.blockCount - 1);
|
|
467
580
|
}
|
|
468
581
|
}
|
|
469
582
|
|
|
@@ -531,13 +644,14 @@ export class BlockStore {
|
|
|
531
644
|
}
|
|
532
645
|
}
|
|
533
646
|
|
|
534
|
-
async getCheckpointedBlockByHash(blockHash:
|
|
647
|
+
async getCheckpointedBlockByHash(blockHash: BlockHash): Promise<CheckpointedL2Block | undefined> {
|
|
535
648
|
const blockNumber = await this.#blockHashIndex.getAsync(blockHash.toString());
|
|
536
649
|
if (blockNumber === undefined) {
|
|
537
650
|
return undefined;
|
|
538
651
|
}
|
|
539
652
|
return this.getCheckpointedBlock(BlockNumber(blockNumber));
|
|
540
653
|
}
|
|
654
|
+
|
|
541
655
|
async getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
542
656
|
const blockNumber = await this.#blockArchiveIndex.getAsync(archive.toString());
|
|
543
657
|
if (blockNumber === undefined) {
|
|
@@ -552,7 +666,7 @@ export class BlockStore {
|
|
|
552
666
|
* @param limit - The number of blocks to return.
|
|
553
667
|
* @returns The requested L2 blocks
|
|
554
668
|
*/
|
|
555
|
-
async *getBlocks(start: BlockNumber, limit: number): AsyncIterableIterator<
|
|
669
|
+
async *getBlocks(start: BlockNumber, limit: number): AsyncIterableIterator<L2Block> {
|
|
556
670
|
for await (const [blockNumber, blockStorage] of this.getBlockStorages(start, limit)) {
|
|
557
671
|
const block = await this.getBlockFromBlockStorage(blockNumber, blockStorage);
|
|
558
672
|
if (block) {
|
|
@@ -561,12 +675,38 @@ export class BlockStore {
|
|
|
561
675
|
}
|
|
562
676
|
}
|
|
563
677
|
|
|
678
|
+
/**
|
|
679
|
+
* Gets block metadata (without tx data) by block number.
|
|
680
|
+
* @param blockNumber - The number of the block to return.
|
|
681
|
+
* @returns The requested block data.
|
|
682
|
+
*/
|
|
683
|
+
async getBlockData(blockNumber: BlockNumber): Promise<BlockData | undefined> {
|
|
684
|
+
const blockStorage = await this.#blocks.getAsync(blockNumber);
|
|
685
|
+
if (!blockStorage || !blockStorage.header) {
|
|
686
|
+
return undefined;
|
|
687
|
+
}
|
|
688
|
+
return this.getBlockDataFromBlockStorage(blockStorage);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Gets block metadata (without tx data) by archive root.
|
|
693
|
+
* @param archive - The archive root of the block to return.
|
|
694
|
+
* @returns The requested block data.
|
|
695
|
+
*/
|
|
696
|
+
async getBlockDataByArchive(archive: Fr): Promise<BlockData | undefined> {
|
|
697
|
+
const blockNumber = await this.#blockArchiveIndex.getAsync(archive.toString());
|
|
698
|
+
if (blockNumber === undefined) {
|
|
699
|
+
return undefined;
|
|
700
|
+
}
|
|
701
|
+
return this.getBlockData(BlockNumber(blockNumber));
|
|
702
|
+
}
|
|
703
|
+
|
|
564
704
|
/**
|
|
565
705
|
* Gets an L2 block.
|
|
566
706
|
* @param blockNumber - The number of the block to return.
|
|
567
707
|
* @returns The requested L2 block.
|
|
568
708
|
*/
|
|
569
|
-
async getBlock(blockNumber: BlockNumber): Promise<
|
|
709
|
+
async getBlock(blockNumber: BlockNumber): Promise<L2Block | undefined> {
|
|
570
710
|
const blockStorage = await this.#blocks.getAsync(blockNumber);
|
|
571
711
|
if (!blockStorage || !blockStorage.header) {
|
|
572
712
|
return Promise.resolve(undefined);
|
|
@@ -579,7 +719,7 @@ export class BlockStore {
|
|
|
579
719
|
* @param blockHash - The hash of the block to return.
|
|
580
720
|
* @returns The requested L2 block.
|
|
581
721
|
*/
|
|
582
|
-
async getBlockByHash(blockHash:
|
|
722
|
+
async getBlockByHash(blockHash: BlockHash): Promise<L2Block | undefined> {
|
|
583
723
|
const blockNumber = await this.#blockHashIndex.getAsync(blockHash.toString());
|
|
584
724
|
if (blockNumber === undefined) {
|
|
585
725
|
return undefined;
|
|
@@ -592,7 +732,7 @@ export class BlockStore {
|
|
|
592
732
|
* @param archive - The archive root of the block to return.
|
|
593
733
|
* @returns The requested L2 block.
|
|
594
734
|
*/
|
|
595
|
-
async getBlockByArchive(archive: Fr): Promise<
|
|
735
|
+
async getBlockByArchive(archive: Fr): Promise<L2Block | undefined> {
|
|
596
736
|
const blockNumber = await this.#blockArchiveIndex.getAsync(archive.toString());
|
|
597
737
|
if (blockNumber === undefined) {
|
|
598
738
|
return undefined;
|
|
@@ -605,7 +745,7 @@ export class BlockStore {
|
|
|
605
745
|
* @param blockHash - The hash of the block to return.
|
|
606
746
|
* @returns The requested block header.
|
|
607
747
|
*/
|
|
608
|
-
async getBlockHeaderByHash(blockHash:
|
|
748
|
+
async getBlockHeaderByHash(blockHash: BlockHash): Promise<BlockHeader | undefined> {
|
|
609
749
|
const blockNumber = await this.#blockHashIndex.getAsync(blockHash.toString());
|
|
610
750
|
if (blockNumber === undefined) {
|
|
611
751
|
return undefined;
|
|
@@ -665,14 +805,24 @@ export class BlockStore {
|
|
|
665
805
|
}
|
|
666
806
|
}
|
|
667
807
|
|
|
808
|
+
private getBlockDataFromBlockStorage(blockStorage: BlockStorage): BlockData {
|
|
809
|
+
return {
|
|
810
|
+
header: BlockHeader.fromBuffer(blockStorage.header),
|
|
811
|
+
archive: AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive),
|
|
812
|
+
blockHash: Fr.fromBuffer(blockStorage.blockHash),
|
|
813
|
+
checkpointNumber: CheckpointNumber(blockStorage.checkpointNumber),
|
|
814
|
+
indexWithinCheckpoint: IndexWithinCheckpoint(blockStorage.indexWithinCheckpoint),
|
|
815
|
+
};
|
|
816
|
+
}
|
|
817
|
+
|
|
668
818
|
private async getBlockFromBlockStorage(
|
|
669
819
|
blockNumber: number,
|
|
670
820
|
blockStorage: BlockStorage,
|
|
671
|
-
): Promise<
|
|
672
|
-
const header =
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
const blockHashString = bufferToHex(blockHash);
|
|
821
|
+
): Promise<L2Block | undefined> {
|
|
822
|
+
const { header, archive, blockHash, checkpointNumber, indexWithinCheckpoint } =
|
|
823
|
+
this.getBlockDataFromBlockStorage(blockStorage);
|
|
824
|
+
header.setHash(blockHash);
|
|
825
|
+
const blockHashString = bufferToHex(blockStorage.blockHash);
|
|
676
826
|
const blockTxsBuffer = await this.#blockTxs.getAsync(blockHashString);
|
|
677
827
|
if (blockTxsBuffer === undefined) {
|
|
678
828
|
this.#log.warn(`Could not find body for block ${header.globalVariables.blockNumber} ${blockHash}`);
|
|
@@ -691,13 +841,7 @@ export class BlockStore {
|
|
|
691
841
|
txEffects.push(deserializeIndexedTxEffect(txEffect).data);
|
|
692
842
|
}
|
|
693
843
|
const body = new Body(txEffects);
|
|
694
|
-
const block = new
|
|
695
|
-
archive,
|
|
696
|
-
header,
|
|
697
|
-
body,
|
|
698
|
-
CheckpointNumber(blockStorage.checkpointNumber!),
|
|
699
|
-
blockStorage.indexWithinCheckpoint,
|
|
700
|
-
);
|
|
844
|
+
const block = new L2Block(archive, header, body, checkpointNumber, indexWithinCheckpoint);
|
|
701
845
|
|
|
702
846
|
if (block.number !== blockNumber) {
|
|
703
847
|
throw new Error(
|
|
@@ -733,13 +877,34 @@ export class BlockStore {
|
|
|
733
877
|
return undefined;
|
|
734
878
|
}
|
|
735
879
|
|
|
880
|
+
const blockNumber = BlockNumber(txEffect.l2BlockNumber);
|
|
881
|
+
|
|
882
|
+
// Use existing archiver methods to determine finalization level
|
|
883
|
+
const [provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber] = await Promise.all([
|
|
884
|
+
this.getProvenBlockNumber(),
|
|
885
|
+
this.getCheckpointedL2BlockNumber(),
|
|
886
|
+
this.getFinalizedL2BlockNumber(),
|
|
887
|
+
]);
|
|
888
|
+
|
|
889
|
+
let status: TxStatus;
|
|
890
|
+
if (blockNumber <= finalizedBlockNumber) {
|
|
891
|
+
status = TxStatus.FINALIZED;
|
|
892
|
+
} else if (blockNumber <= provenBlockNumber) {
|
|
893
|
+
status = TxStatus.PROVEN;
|
|
894
|
+
} else if (blockNumber <= checkpointedBlockNumber) {
|
|
895
|
+
status = TxStatus.CHECKPOINTED;
|
|
896
|
+
} else {
|
|
897
|
+
status = TxStatus.PROPOSED;
|
|
898
|
+
}
|
|
899
|
+
|
|
736
900
|
return new TxReceipt(
|
|
737
901
|
txHash,
|
|
738
|
-
|
|
739
|
-
|
|
902
|
+
status,
|
|
903
|
+
TxReceipt.executionResultFromRevertCode(txEffect.data.revertCode),
|
|
904
|
+
undefined,
|
|
740
905
|
txEffect.data.transactionFee.toBigInt(),
|
|
741
906
|
txEffect.l2BlockHash,
|
|
742
|
-
|
|
907
|
+
blockNumber,
|
|
743
908
|
);
|
|
744
909
|
}
|
|
745
910
|
|
|
@@ -776,7 +941,7 @@ export class BlockStore {
|
|
|
776
941
|
if (!checkpoint) {
|
|
777
942
|
return BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
778
943
|
}
|
|
779
|
-
return BlockNumber(checkpoint.startBlock + checkpoint.
|
|
944
|
+
return BlockNumber(checkpoint.startBlock + checkpoint.blockCount - 1);
|
|
780
945
|
}
|
|
781
946
|
|
|
782
947
|
async getLatestL2BlockNumber(): Promise<BlockNumber> {
|
|
@@ -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>;
|
|
@@ -28,18 +28,22 @@ export class ContractClassStore {
|
|
|
28
28
|
bytecodeCommitment: Fr,
|
|
29
29
|
blockNumber: number,
|
|
30
30
|
): Promise<void> {
|
|
31
|
-
await this
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
await this.db.transactionAsync(async () => {
|
|
32
|
+
await this.#contractClasses.setIfNotExists(
|
|
33
|
+
contractClass.id.toString(),
|
|
34
|
+
serializeContractClassPublic({ ...contractClass, l2BlockNumber: blockNumber }),
|
|
35
|
+
);
|
|
36
|
+
await this.#bytecodeCommitments.setIfNotExists(contractClass.id.toString(), bytecodeCommitment.toBuffer());
|
|
37
|
+
});
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
async deleteContractClasses(contractClass: ContractClassPublic, blockNumber: number): Promise<void> {
|
|
39
41
|
const restoredContractClass = await this.#contractClasses.getAsync(contractClass.id.toString());
|
|
40
42
|
if (restoredContractClass && deserializeContractClassPublic(restoredContractClass).l2BlockNumber >= blockNumber) {
|
|
41
|
-
await this
|
|
42
|
-
|
|
43
|
+
await this.db.transactionAsync(async () => {
|
|
44
|
+
await this.#contractClasses.delete(contractClass.id.toString());
|
|
45
|
+
await this.#bytecodeCommitments.delete(contractClass.id.toString());
|
|
46
|
+
});
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
|
|
@@ -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>;
|