@aztec/archiver 0.0.1-commit.b1c78909e → 0.0.1-commit.b2a5d0dd1
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 +12 -6
- package/dest/archiver.d.ts +7 -5
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +39 -15
- package/dest/config.d.ts +5 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +15 -3
- package/dest/errors.d.ts +44 -2
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +58 -2
- package/dest/factory.d.ts +2 -2
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +18 -14
- package/dest/index.d.ts +3 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -1
- package/dest/l1/calldata_retriever.d.ts +1 -1
- package/dest/l1/calldata_retriever.d.ts.map +1 -1
- package/dest/l1/calldata_retriever.js +2 -1
- package/dest/l1/data_retrieval.d.ts +19 -10
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +25 -32
- package/dest/l1/validate_historical_logs.d.ts +23 -0
- package/dest/l1/validate_historical_logs.d.ts.map +1 -0
- package/dest/l1/validate_historical_logs.js +108 -0
- package/dest/modules/data_source_base.d.ts +6 -4
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +11 -5
- package/dest/modules/data_store_updater.d.ts +15 -10
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +69 -68
- package/dest/modules/instrumentation.d.ts +7 -2
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +22 -6
- package/dest/modules/l1_synchronizer.d.ts +6 -2
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +244 -146
- package/dest/modules/validation.d.ts +1 -1
- package/dest/modules/validation.d.ts.map +1 -1
- package/dest/modules/validation.js +2 -2
- package/dest/store/block_store.d.ts +49 -6
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +277 -67
- package/dest/store/contract_class_store.d.ts +2 -3
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +7 -67
- package/dest/store/contract_instance_store.d.ts +1 -1
- package/dest/store/contract_instance_store.d.ts.map +1 -1
- package/dest/store/contract_instance_store.js +6 -2
- package/dest/store/kv_archiver_store.d.ts +39 -18
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +45 -20
- package/dest/store/l2_tips_cache.d.ts +2 -1
- package/dest/store/l2_tips_cache.d.ts.map +1 -1
- package/dest/store/l2_tips_cache.js +27 -7
- package/dest/store/log_store.d.ts +6 -3
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +95 -20
- package/dest/store/message_store.d.ts +5 -1
- package/dest/store/message_store.d.ts.map +1 -1
- package/dest/store/message_store.js +20 -8
- package/dest/test/fake_l1_state.d.ts +14 -3
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +63 -10
- package/dest/test/mock_l1_to_l2_message_source.d.ts +1 -1
- package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
- package/dest/test/mock_l1_to_l2_message_source.js +2 -1
- package/dest/test/mock_l2_block_source.d.ts +7 -2
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +30 -5
- package/dest/test/noop_l1_archiver.d.ts +1 -1
- package/dest/test/noop_l1_archiver.d.ts.map +1 -1
- package/dest/test/noop_l1_archiver.js +4 -2
- package/package.json +13 -13
- package/src/archiver.ts +57 -18
- package/src/config.ts +22 -2
- package/src/errors.ts +94 -2
- package/src/factory.ts +18 -10
- package/src/index.ts +2 -1
- package/src/l1/calldata_retriever.ts +2 -1
- package/src/l1/data_retrieval.ts +36 -45
- package/src/l1/validate_historical_logs.ts +140 -0
- package/src/modules/data_source_base.ts +24 -5
- package/src/modules/data_store_updater.ts +94 -97
- package/src/modules/instrumentation.ts +27 -7
- package/src/modules/l1_synchronizer.ts +314 -177
- package/src/modules/validation.ts +2 -2
- package/src/store/block_store.ts +364 -76
- package/src/store/contract_class_store.ts +8 -106
- package/src/store/contract_instance_store.ts +8 -5
- package/src/store/kv_archiver_store.ts +77 -34
- package/src/store/l2_tips_cache.ts +58 -13
- package/src/store/log_store.ts +128 -32
- package/src/store/message_store.ts +26 -9
- package/src/structs/inbox_message.ts +1 -1
- package/src/test/fake_l1_state.ts +87 -15
- package/src/test/mock_l1_to_l2_message_source.ts +1 -0
- package/src/test/mock_l2_block_source.ts +44 -3
- package/src/test/noop_l1_archiver.ts +3 -1
|
@@ -2,8 +2,9 @@ import { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec/foundation/bra
|
|
|
2
2
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
3
3
|
import type { AztecAsyncKVStore } from '@aztec/kv-store';
|
|
4
4
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
|
-
import { type BlockData, BlockHash, CheckpointedL2Block, L2Block, type ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
6
|
-
import { type CheckpointData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
5
|
+
import { type BlockData, BlockHash, CheckpointedL2Block, CommitteeAttestation, L2Block, type ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
6
|
+
import { type CheckpointData, type CommonCheckpointData, L1PublishedData, type ProposedCheckpointData, type ProposedCheckpointInput, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
7
|
+
import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
7
8
|
import { BlockHeader, type IndexedTxEffect, TxHash, TxReceipt } from '@aztec/stdlib/tx';
|
|
8
9
|
export { TxReceipt, type TxEffect, type TxHash } from '@aztec/stdlib/tx';
|
|
9
10
|
export type RemoveCheckpointsResult = {
|
|
@@ -33,13 +34,21 @@ export declare class BlockStore {
|
|
|
33
34
|
force?: boolean;
|
|
34
35
|
}): Promise<boolean>;
|
|
35
36
|
/**
|
|
36
|
-
* Append new
|
|
37
|
+
* Append new checkpoints to the store's list.
|
|
37
38
|
* @param checkpoints - The L2 checkpoints to be added to the store.
|
|
38
39
|
* @returns True if the operation is successful.
|
|
39
40
|
*/
|
|
40
41
|
addCheckpoints(checkpoints: PublishedCheckpoint[], opts?: {
|
|
41
42
|
force?: boolean;
|
|
42
43
|
}): Promise<boolean>;
|
|
44
|
+
private skipOrUpdateAlreadyStoredCheckpoints;
|
|
45
|
+
private getPreviousCheckpointBlock;
|
|
46
|
+
/**
|
|
47
|
+
* Validates that blocks are sequential, have correct indexes, and chain via archive roots.
|
|
48
|
+
* This is the same validation used for both confirmed checkpoints (addCheckpoints) and
|
|
49
|
+
* proposed checkpoints (setProposedCheckpoint).
|
|
50
|
+
*/
|
|
51
|
+
private validateCheckpointBlocks;
|
|
43
52
|
private addBlockToDatabase;
|
|
44
53
|
private deleteBlock;
|
|
45
54
|
/**
|
|
@@ -69,8 +78,39 @@ export declare class BlockStore {
|
|
|
69
78
|
*/
|
|
70
79
|
removeBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]>;
|
|
71
80
|
getProvenBlockNumber(): Promise<BlockNumber>;
|
|
72
|
-
getLatestBlockNumber(): Promise<BlockNumber>;
|
|
73
81
|
getLatestCheckpointNumber(): Promise<CheckpointNumber>;
|
|
82
|
+
hasProposedCheckpoint(): Promise<boolean>;
|
|
83
|
+
/** Deletes the proposed checkpoint from storage. */
|
|
84
|
+
deleteProposedCheckpoint(): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Promotes the proposed checkpoint singleton to a confirmed checkpoint entry.
|
|
87
|
+
* This persists the checkpoint to the store, clears the proposed singleton, and updates the L1 sync point.
|
|
88
|
+
* Should only be called after the checkpoint has been validated.
|
|
89
|
+
* @param expectedArchiveRoot - The archive root to match against the proposed checkpoint, to guard against races.
|
|
90
|
+
*/
|
|
91
|
+
promoteProposedToCheckpointed(l1: L1PublishedData, attestations: CommitteeAttestation[], expectedArchiveRoot: Fr): Promise<void>;
|
|
92
|
+
/** Clears the proposed checkpoint if the given confirmed checkpoint number supersedes it. */
|
|
93
|
+
clearProposedCheckpointIfSuperseded(confirmedCheckpointNumber: CheckpointNumber): Promise<void>;
|
|
94
|
+
/** Returns the proposed checkpoint data, or undefined if no proposed checkpoint exists. No fallback to confirmed. */
|
|
95
|
+
getProposedCheckpointOnly(): Promise<ProposedCheckpointData | undefined>;
|
|
96
|
+
/**
|
|
97
|
+
* Gets the checkpoint at the proposed tip
|
|
98
|
+
* - pending checkpoint if it exists
|
|
99
|
+
* - fallsback to latest confirmed checkpoint otherwise
|
|
100
|
+
* @returns CommonCheckpointData
|
|
101
|
+
*/
|
|
102
|
+
getProposedCheckpoint(): Promise<CommonCheckpointData | undefined>;
|
|
103
|
+
private convertToProposedCheckpointData;
|
|
104
|
+
/**
|
|
105
|
+
* Attempts to get the proposedCheckpoint's number, if there is not one, then fallback to the latest confirmed checkpoint number.
|
|
106
|
+
* @returns CheckpointNumber
|
|
107
|
+
*/
|
|
108
|
+
getProposedCheckpointNumber(): Promise<CheckpointNumber>;
|
|
109
|
+
/**
|
|
110
|
+
* Attempts to get the proposedCheckpoint's block number, if there is not one, then fallback to the checkpointed block number
|
|
111
|
+
* @returns BlockNumber
|
|
112
|
+
*/
|
|
113
|
+
getProposedCheckpointL2BlockNumber(): Promise<BlockNumber>;
|
|
74
114
|
getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined>;
|
|
75
115
|
/**
|
|
76
116
|
* Gets up to `limit` amount of Checkpointed L2 blocks starting from `from`.
|
|
@@ -151,7 +191,7 @@ export declare class BlockStore {
|
|
|
151
191
|
* @param txHash - The hash of a tx we try to get the receipt for.
|
|
152
192
|
* @returns The requested tx receipt (or undefined if not found).
|
|
153
193
|
*/
|
|
154
|
-
getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined>;
|
|
194
|
+
getSettledTxReceipt(txHash: TxHash, l1Constants?: Pick<L1RollupConstants, 'epochDuration'>): Promise<TxReceipt | undefined>;
|
|
155
195
|
/**
|
|
156
196
|
* Looks up which block included the requested tx effect.
|
|
157
197
|
* @param txHash - The txHash of the tx.
|
|
@@ -176,6 +216,9 @@ export declare class BlockStore {
|
|
|
176
216
|
*/
|
|
177
217
|
getSynchedL1BlockNumber(): Promise<bigint | undefined>;
|
|
178
218
|
setSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<boolean>;
|
|
219
|
+
/** Sets the proposed checkpoint (not yet L1-confirmed). Only accepts confirmed + 1.
|
|
220
|
+
* Computes archive and checkpointOutHash from the stored blocks. */
|
|
221
|
+
setProposedCheckpoint(proposed: ProposedCheckpointInput): Promise<void>;
|
|
179
222
|
getProvenCheckpointNumber(): Promise<CheckpointNumber>;
|
|
180
223
|
setProvenCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<boolean>;
|
|
181
224
|
getFinalizedCheckpointNumber(): Promise<CheckpointNumber>;
|
|
@@ -191,4 +234,4 @@ export declare class BlockStore {
|
|
|
191
234
|
*/
|
|
192
235
|
setPendingChainValidationStatus(status: ValidateCheckpointResult | undefined): Promise<void>;
|
|
193
236
|
}
|
|
194
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
237
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxvY2tfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9ibG9ja19zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUF5QixVQUFVLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNuSCxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFNcEQsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQTZDLE1BQU0saUJBQWlCLENBQUM7QUFDcEcsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDaEUsT0FBTyxFQUNMLEtBQUssU0FBUyxFQUNkLFNBQVMsRUFFVCxtQkFBbUIsRUFDbkIsb0JBQW9CLEVBQ3BCLE9BQU8sRUFDUCxLQUFLLHdCQUF3QixFQUc5QixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFFTCxLQUFLLGNBQWMsRUFDbkIsS0FBSyxvQkFBb0IsRUFDekIsZUFBZSxFQUNmLEtBQUssc0JBQXNCLEVBQzNCLEtBQUssdUJBQXVCLEVBQzVCLG1CQUFtQixFQUNwQixNQUFNLDBCQUEwQixDQUFDO0FBQ2xDLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUFrQixNQUFNLDZCQUE2QixDQUFDO0FBR3JGLE9BQU8sRUFDTCxXQUFXLEVBQ1gsS0FBSyxlQUFlLEVBRXBCLE1BQU0sRUFDTixTQUFTLEVBSVYsTUFBTSxrQkFBa0IsQ0FBQztBQW1CMUIsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLFFBQVEsRUFBRSxLQUFLLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBaUN6RSxNQUFNLE1BQU0sdUJBQXVCLEdBQUc7SUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLEdBQUcsU0FBUyxDQUFBO0NBQUUsQ0FBQztBQUUvRTs7R0FFRztBQUNILHFCQUFhLFVBQVU7O0lBMENULE9BQU8sQ0FBQyxFQUFF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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block_store.d.ts","sourceRoot":"","sources":["../../src/store/block_store.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAyB,UAAU,EAAE,MAAM,iCAAiC,CAAC;AACnH,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAMpD,OAAO,KAAK,EAAE,iBAAiB,EAA6C,MAAM,iBAAiB,CAAC;AACpG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,KAAK,SAAS,EACd,SAAS,EAET,mBAAmB,
|
|
1
|
+
{"version":3,"file":"block_store.d.ts","sourceRoot":"","sources":["../../src/store/block_store.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,12 +6,13 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
6
6
|
import { BufferReader } from '@aztec/foundation/serialize';
|
|
7
7
|
import { bufferToHex } from '@aztec/foundation/string';
|
|
8
8
|
import { isDefined } from '@aztec/foundation/types';
|
|
9
|
-
import { Body, CheckpointedL2Block, CommitteeAttestation, L2Block, deserializeValidateCheckpointResult, serializeValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
10
|
-
import { L1PublishedData } from '@aztec/stdlib/checkpoint';
|
|
9
|
+
import { BlockHash, Body, CheckpointedL2Block, CommitteeAttestation, L2Block, deserializeValidateCheckpointResult, serializeValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
10
|
+
import { Checkpoint, L1PublishedData } from '@aztec/stdlib/checkpoint';
|
|
11
|
+
import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
11
12
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
12
13
|
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
13
14
|
import { BlockHeader, TxHash, TxReceipt, TxStatus, deserializeIndexedTxEffect, serializeIndexedTxEffect } from '@aztec/stdlib/tx';
|
|
14
|
-
import { BlockAlreadyCheckpointedError, BlockArchiveNotConsistentError, BlockIndexNotSequentialError, BlockNotFoundError, BlockNumberNotSequentialError, CannotOverwriteCheckpointedBlockError, CheckpointNotFoundError, CheckpointNumberNotSequentialError, InitialCheckpointNumberNotSequentialError } from '../errors.js';
|
|
15
|
+
import { BlockAlreadyCheckpointedError, BlockArchiveNotConsistentError, BlockIndexNotSequentialError, BlockNotFoundError, BlockNumberNotSequentialError, CannotOverwriteCheckpointedBlockError, CheckpointNotFoundError, CheckpointNumberNotSequentialError, InitialCheckpointNumberNotSequentialError, NoProposedCheckpointToPromoteError, ProposedCheckpointArchiveRootMismatchError, ProposedCheckpointNotSequentialError, ProposedCheckpointPromotionNotSequentialError, ProposedCheckpointStaleError } from '../errors.js';
|
|
15
16
|
export { TxReceipt } from '@aztec/stdlib/tx';
|
|
16
17
|
/**
|
|
17
18
|
* LMDB-based block storage for the archiver.
|
|
@@ -29,6 +30,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
29
30
|
/** Index mapping a contract's address (as a string) to its location in a block */ #contractIndex;
|
|
30
31
|
/** Index mapping block hash to block number */ #blockHashIndex;
|
|
31
32
|
/** Index mapping block archive to block number */ #blockArchiveIndex;
|
|
33
|
+
/** Singleton: assumes max 1-deep pipeline. For deeper pipelining, replace with a map keyed by checkpoint number. */ #proposedCheckpoint;
|
|
32
34
|
#log;
|
|
33
35
|
constructor(db){
|
|
34
36
|
this.db = db;
|
|
@@ -45,6 +47,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
45
47
|
this.#pendingChainValidationStatus = db.openSingleton('archiver_pending_chain_validation_status');
|
|
46
48
|
this.#checkpoints = db.openMap('archiver_checkpoints');
|
|
47
49
|
this.#slotToCheckpoint = db.openMap('archiver_slot_to_checkpoint');
|
|
50
|
+
this.#proposedCheckpoint = db.openSingleton('proposed_checkpoint_data');
|
|
48
51
|
}
|
|
49
52
|
/**
|
|
50
53
|
* Returns the finalized L2 block number. An L2 block is finalized when it was proven
|
|
@@ -74,7 +77,8 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
74
77
|
const blockIndex = block.indexWithinCheckpoint;
|
|
75
78
|
const blockLastArchive = block.header.lastArchive.root;
|
|
76
79
|
// Extract the latest block and checkpoint numbers
|
|
77
|
-
const previousBlockNumber = await this.
|
|
80
|
+
const previousBlockNumber = await this.getLatestL2BlockNumber();
|
|
81
|
+
const proposedCheckpointNumber = await this.getProposedCheckpointNumber();
|
|
78
82
|
const previousCheckpointNumber = await this.getLatestCheckpointNumber();
|
|
79
83
|
// Verify we're not overwriting checkpointed blocks
|
|
80
84
|
const lastCheckpointedBlockNumber = await this.getCheckpointedL2BlockNumber();
|
|
@@ -90,9 +94,18 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
90
94
|
if (!opts.force && previousBlockNumber !== blockNumber - 1) {
|
|
91
95
|
throw new BlockNumberNotSequentialError(blockNumber, previousBlockNumber);
|
|
92
96
|
}
|
|
93
|
-
// The same check as above but for checkpoints
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
// The same check as above but for checkpoints. Accept the block if either the confirmed
|
|
98
|
+
// checkpoint or the pending (locally validated but not yet confirmed) checkpoint matches.
|
|
99
|
+
const expectedCheckpointNumber = blockCheckpointNumber - 1;
|
|
100
|
+
if (!opts.force && previousCheckpointNumber !== expectedCheckpointNumber && proposedCheckpointNumber !== expectedCheckpointNumber) {
|
|
101
|
+
const [reported, source] = proposedCheckpointNumber > previousCheckpointNumber ? [
|
|
102
|
+
proposedCheckpointNumber,
|
|
103
|
+
'proposed'
|
|
104
|
+
] : [
|
|
105
|
+
previousCheckpointNumber,
|
|
106
|
+
'confirmed'
|
|
107
|
+
];
|
|
108
|
+
throw new CheckpointNumberNotSequentialError(blockCheckpointNumber, reported, source);
|
|
96
109
|
}
|
|
97
110
|
// Extract the previous block if there is one and see if it is for the same checkpoint or not
|
|
98
111
|
const previousBlockResult = await this.getBlock(previousBlockNumber);
|
|
@@ -117,7 +130,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
117
130
|
});
|
|
118
131
|
}
|
|
119
132
|
/**
|
|
120
|
-
* Append new
|
|
133
|
+
* Append new checkpoints to the store's list.
|
|
121
134
|
* @param checkpoints - The L2 checkpoints to be added to the store.
|
|
122
135
|
* @returns True if the operation is successful.
|
|
123
136
|
*/ async addCheckpoints(checkpoints, opts = {}) {
|
|
@@ -125,32 +138,26 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
125
138
|
return true;
|
|
126
139
|
}
|
|
127
140
|
return await this.db.transactionAsync(async ()=>{
|
|
128
|
-
// Check that the checkpoint immediately before the first block to be added is present in the store.
|
|
129
141
|
const firstCheckpointNumber = checkpoints[0].checkpoint.number;
|
|
130
142
|
const previousCheckpointNumber = await this.getLatestCheckpointNumber();
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
previousCheckpointData = await this.getCheckpointData(previousCheckpointNumber);
|
|
139
|
-
if (previousCheckpointData === undefined) {
|
|
140
|
-
throw new CheckpointNotFoundError(previousCheckpointNumber);
|
|
143
|
+
// Handle already-stored checkpoints at the start of the batch.
|
|
144
|
+
// This can happen after an L1 reorg re-includes a checkpoint in a different L1 block.
|
|
145
|
+
// We accept them if archives match (same content) and update their L1 metadata.
|
|
146
|
+
if (!opts.force && firstCheckpointNumber <= previousCheckpointNumber) {
|
|
147
|
+
checkpoints = await this.skipOrUpdateAlreadyStoredCheckpoints(checkpoints, previousCheckpointNumber);
|
|
148
|
+
if (checkpoints.length === 0) {
|
|
149
|
+
return true;
|
|
141
150
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if (previousCheckpointData !== undefined) {
|
|
147
|
-
previousBlockNumber = BlockNumber(previousCheckpointData.startBlock + previousCheckpointData.blockCount - 1);
|
|
148
|
-
previousBlock = await this.getBlock(previousBlockNumber);
|
|
149
|
-
if (previousBlock === undefined) {
|
|
150
|
-
// We should be able to get the required previous block
|
|
151
|
-
throw new BlockNotFoundError(previousBlockNumber);
|
|
151
|
+
// Re-check sequentiality after skipping
|
|
152
|
+
const newFirstNumber = checkpoints[0].checkpoint.number;
|
|
153
|
+
if (previousCheckpointNumber !== newFirstNumber - 1) {
|
|
154
|
+
throw new InitialCheckpointNumberNotSequentialError(newFirstNumber, previousCheckpointNumber);
|
|
152
155
|
}
|
|
156
|
+
} else if (previousCheckpointNumber !== firstCheckpointNumber - 1 && !opts.force) {
|
|
157
|
+
throw new InitialCheckpointNumberNotSequentialError(firstCheckpointNumber, previousCheckpointNumber);
|
|
153
158
|
}
|
|
159
|
+
// Get the last block of the previous checkpoint for archive chaining
|
|
160
|
+
let previousBlock = await this.getPreviousCheckpointBlock(checkpoints[0].checkpoint.number);
|
|
154
161
|
// Iterate over checkpoints array and insert them, checking that the block numbers are sequential.
|
|
155
162
|
let previousCheckpoint = undefined;
|
|
156
163
|
for (const checkpoint of checkpoints){
|
|
@@ -158,33 +165,13 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
158
165
|
throw new CheckpointNumberNotSequentialError(checkpoint.checkpoint.number, previousCheckpoint.checkpoint.number);
|
|
159
166
|
}
|
|
160
167
|
previousCheckpoint = checkpoint;
|
|
161
|
-
//
|
|
168
|
+
// Validate block sequencing, indexes, and archive chaining
|
|
169
|
+
this.validateCheckpointBlocks(checkpoint.checkpoint.blocks, previousBlock);
|
|
170
|
+
// Store every block in the database (may already exist, but L1 data is authoritative)
|
|
162
171
|
for(let i = 0; i < checkpoint.checkpoint.blocks.length; i++){
|
|
163
|
-
|
|
164
|
-
if (previousBlock) {
|
|
165
|
-
// The blocks should have a sequential block number
|
|
166
|
-
if (previousBlock.number !== block.number - 1) {
|
|
167
|
-
throw new BlockNumberNotSequentialError(block.number, previousBlock.number);
|
|
168
|
-
}
|
|
169
|
-
// If the blocks are for the same checkpoint then they should have sequential indexes
|
|
170
|
-
if (previousBlock.checkpointNumber === block.checkpointNumber && previousBlock.indexWithinCheckpoint !== block.indexWithinCheckpoint - 1) {
|
|
171
|
-
throw new BlockIndexNotSequentialError(block.indexWithinCheckpoint, previousBlock.indexWithinCheckpoint);
|
|
172
|
-
}
|
|
173
|
-
if (!previousBlock.archive.root.equals(block.header.lastArchive.root)) {
|
|
174
|
-
throw new BlockArchiveNotConsistentError(block.number, previousBlock.number, block.header.lastArchive.root, previousBlock.archive.root);
|
|
175
|
-
}
|
|
176
|
-
} else {
|
|
177
|
-
// No previous block, must be block 1 at checkpoint index 0
|
|
178
|
-
if (block.indexWithinCheckpoint !== 0) {
|
|
179
|
-
throw new BlockIndexNotSequentialError(block.indexWithinCheckpoint, undefined);
|
|
180
|
-
}
|
|
181
|
-
if (block.number !== INITIAL_L2_BLOCK_NUM) {
|
|
182
|
-
throw new BlockNumberNotSequentialError(block.number, undefined);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
previousBlock = block;
|
|
186
|
-
await this.addBlockToDatabase(block, checkpoint.checkpoint.number, i);
|
|
172
|
+
await this.addBlockToDatabase(checkpoint.checkpoint.blocks[i], checkpoint.checkpoint.number, i);
|
|
187
173
|
}
|
|
174
|
+
previousBlock = checkpoint.checkpoint.blocks.at(-1);
|
|
188
175
|
// Store the checkpoint in the database
|
|
189
176
|
await this.#checkpoints.set(checkpoint.checkpoint.number, {
|
|
190
177
|
header: checkpoint.checkpoint.header.toBuffer(),
|
|
@@ -199,10 +186,95 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
199
186
|
// Update slot-to-checkpoint index
|
|
200
187
|
await this.#slotToCheckpoint.set(checkpoint.checkpoint.header.slotNumber, checkpoint.checkpoint.number);
|
|
201
188
|
}
|
|
189
|
+
// Clear the proposed checkpoint if any of the confirmed checkpoints match or supersede it
|
|
190
|
+
const lastConfirmedCheckpointNumber = checkpoints[checkpoints.length - 1].checkpoint.number;
|
|
191
|
+
await this.clearProposedCheckpointIfSuperseded(lastConfirmedCheckpointNumber);
|
|
202
192
|
await this.#lastSynchedL1Block.set(checkpoints[checkpoints.length - 1].l1.blockNumber);
|
|
203
193
|
return true;
|
|
204
194
|
});
|
|
205
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* Handles checkpoints at the start of a batch that are already stored (e.g. due to L1 reorg).
|
|
198
|
+
* Verifies the archive root matches, updates L1 metadata, and returns only the new checkpoints.
|
|
199
|
+
*/ async skipOrUpdateAlreadyStoredCheckpoints(checkpoints, latestStored) {
|
|
200
|
+
let i = 0;
|
|
201
|
+
for(; i < checkpoints.length && checkpoints[i].checkpoint.number <= latestStored; i++){
|
|
202
|
+
const incoming = checkpoints[i];
|
|
203
|
+
const stored = await this.getCheckpointData(incoming.checkpoint.number);
|
|
204
|
+
if (!stored) {
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
// Verify the checkpoint content matches (archive root)
|
|
208
|
+
if (!stored.archive.root.equals(incoming.checkpoint.archive.root)) {
|
|
209
|
+
throw new Error(`Checkpoint ${incoming.checkpoint.number} already exists in store but with a different archive root. ` + `Stored: ${stored.archive.root}, incoming: ${incoming.checkpoint.archive.root}`);
|
|
210
|
+
}
|
|
211
|
+
// Update L1 metadata and attestations for the already-stored checkpoint
|
|
212
|
+
this.#log.warn(`Checkpoint ${incoming.checkpoint.number} already stored, updating L1 info ` + `(L1 block ${stored.l1.blockNumber} -> ${incoming.l1.blockNumber})`);
|
|
213
|
+
await this.#checkpoints.set(incoming.checkpoint.number, {
|
|
214
|
+
header: incoming.checkpoint.header.toBuffer(),
|
|
215
|
+
archive: incoming.checkpoint.archive.toBuffer(),
|
|
216
|
+
checkpointOutHash: incoming.checkpoint.getCheckpointOutHash().toBuffer(),
|
|
217
|
+
l1: incoming.l1.toBuffer(),
|
|
218
|
+
attestations: incoming.attestations.map((a)=>a.toBuffer()),
|
|
219
|
+
checkpointNumber: incoming.checkpoint.number,
|
|
220
|
+
startBlock: incoming.checkpoint.blocks[0].number,
|
|
221
|
+
blockCount: incoming.checkpoint.blocks.length
|
|
222
|
+
});
|
|
223
|
+
// Update the sync point to reflect the new L1 block
|
|
224
|
+
await this.#lastSynchedL1Block.set(incoming.l1.blockNumber);
|
|
225
|
+
}
|
|
226
|
+
return checkpoints.slice(i);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Gets the last block of the checkpoint before the given one.
|
|
230
|
+
* Returns undefined if there is no previous checkpoint (i.e. genesis).
|
|
231
|
+
*/ async getPreviousCheckpointBlock(checkpointNumber) {
|
|
232
|
+
const previousCheckpointNumber = CheckpointNumber(checkpointNumber - 1);
|
|
233
|
+
if (previousCheckpointNumber === INITIAL_CHECKPOINT_NUMBER - 1) {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
const previousCheckpointData = await this.getCheckpointData(previousCheckpointNumber);
|
|
237
|
+
if (previousCheckpointData === undefined) {
|
|
238
|
+
throw new CheckpointNotFoundError(previousCheckpointNumber);
|
|
239
|
+
}
|
|
240
|
+
const previousBlockNumber = BlockNumber(previousCheckpointData.startBlock + previousCheckpointData.blockCount - 1);
|
|
241
|
+
const previousBlock = await this.getBlock(previousBlockNumber);
|
|
242
|
+
if (previousBlock === undefined) {
|
|
243
|
+
throw new BlockNotFoundError(previousBlockNumber);
|
|
244
|
+
}
|
|
245
|
+
return previousBlock;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Validates that blocks are sequential, have correct indexes, and chain via archive roots.
|
|
249
|
+
* This is the same validation used for both confirmed checkpoints (addCheckpoints) and
|
|
250
|
+
* proposed checkpoints (setProposedCheckpoint).
|
|
251
|
+
*/ validateCheckpointBlocks(blocks, previousBlock) {
|
|
252
|
+
for (const block of blocks){
|
|
253
|
+
if (previousBlock) {
|
|
254
|
+
if (previousBlock.number !== block.number - 1) {
|
|
255
|
+
throw new BlockNumberNotSequentialError(block.number, previousBlock.number);
|
|
256
|
+
}
|
|
257
|
+
if (previousBlock.checkpointNumber === block.checkpointNumber) {
|
|
258
|
+
if (previousBlock.indexWithinCheckpoint !== block.indexWithinCheckpoint - 1) {
|
|
259
|
+
throw new BlockIndexNotSequentialError(block.indexWithinCheckpoint, previousBlock.indexWithinCheckpoint);
|
|
260
|
+
}
|
|
261
|
+
} else if (block.indexWithinCheckpoint !== 0) {
|
|
262
|
+
throw new BlockIndexNotSequentialError(block.indexWithinCheckpoint, previousBlock.indexWithinCheckpoint);
|
|
263
|
+
}
|
|
264
|
+
if (!previousBlock.archive.root.equals(block.header.lastArchive.root)) {
|
|
265
|
+
throw new BlockArchiveNotConsistentError(block.number, previousBlock.number, block.header.lastArchive.root, previousBlock.archive.root);
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
if (block.indexWithinCheckpoint !== 0) {
|
|
269
|
+
throw new BlockIndexNotSequentialError(block.indexWithinCheckpoint, undefined);
|
|
270
|
+
}
|
|
271
|
+
if (block.number !== INITIAL_L2_BLOCK_NUM) {
|
|
272
|
+
throw new BlockNumberNotSequentialError(block.number, undefined);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
previousBlock = block;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
206
278
|
async addBlockToDatabase(block, checkpointNumber, indexWithinCheckpoint) {
|
|
207
279
|
const blockHash = await block.hash();
|
|
208
280
|
await this.#blocks.set(block.number, {
|
|
@@ -280,6 +352,11 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
280
352
|
await this.#checkpoints.delete(c);
|
|
281
353
|
this.#log.debug(`Removed checkpoint ${c}`);
|
|
282
354
|
}
|
|
355
|
+
// Clear any proposed checkpoint that was orphaned by the removal (its base chain no longer exists)
|
|
356
|
+
const proposedCheckpointNumber = await this.getProposedCheckpointNumber();
|
|
357
|
+
if (proposedCheckpointNumber > checkpointNumber) {
|
|
358
|
+
await this.#proposedCheckpoint.delete();
|
|
359
|
+
}
|
|
283
360
|
return {
|
|
284
361
|
blocksRemoved
|
|
285
362
|
};
|
|
@@ -372,7 +449,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
372
449
|
return await this.db.transactionAsync(async ()=>{
|
|
373
450
|
const removedBlocks = [];
|
|
374
451
|
// Get the latest block number to determine the range
|
|
375
|
-
const latestBlockNumber = await this.
|
|
452
|
+
const latestBlockNumber = await this.getLatestL2BlockNumber();
|
|
376
453
|
// Iterate from blockNumber + 1 to latestBlockNumber
|
|
377
454
|
for(let bn = blockNumber + 1; bn <= latestBlockNumber; bn++){
|
|
378
455
|
const block = await this.getBlock(BlockNumber(bn));
|
|
@@ -399,13 +476,6 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
399
476
|
return BlockNumber(checkpointStorage.startBlock + checkpointStorage.blockCount - 1);
|
|
400
477
|
}
|
|
401
478
|
}
|
|
402
|
-
async getLatestBlockNumber() {
|
|
403
|
-
const [latestBlocknumber] = await toArray(this.#blocks.keysAsync({
|
|
404
|
-
reverse: true,
|
|
405
|
-
limit: 1
|
|
406
|
-
}));
|
|
407
|
-
return typeof latestBlocknumber === 'number' ? BlockNumber(latestBlocknumber) : BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
408
|
-
}
|
|
409
479
|
async getLatestCheckpointNumber() {
|
|
410
480
|
const [latestCheckpointNumber] = await toArray(this.#checkpoints.keysAsync({
|
|
411
481
|
reverse: true,
|
|
@@ -416,6 +486,108 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
416
486
|
}
|
|
417
487
|
return CheckpointNumber(latestCheckpointNumber);
|
|
418
488
|
}
|
|
489
|
+
async hasProposedCheckpoint() {
|
|
490
|
+
const proposed = await this.#proposedCheckpoint.getAsync();
|
|
491
|
+
return proposed !== undefined;
|
|
492
|
+
}
|
|
493
|
+
/** Deletes the proposed checkpoint from storage. */ async deleteProposedCheckpoint() {
|
|
494
|
+
await this.#proposedCheckpoint.delete();
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Promotes the proposed checkpoint singleton to a confirmed checkpoint entry.
|
|
498
|
+
* This persists the checkpoint to the store, clears the proposed singleton, and updates the L1 sync point.
|
|
499
|
+
* Should only be called after the checkpoint has been validated.
|
|
500
|
+
* @param expectedArchiveRoot - The archive root to match against the proposed checkpoint, to guard against races.
|
|
501
|
+
*/ async promoteProposedToCheckpointed(l1, attestations, expectedArchiveRoot) {
|
|
502
|
+
return await this.db.transactionAsync(async ()=>{
|
|
503
|
+
const proposed = await this.getProposedCheckpointOnly();
|
|
504
|
+
if (!proposed) {
|
|
505
|
+
throw new NoProposedCheckpointToPromoteError();
|
|
506
|
+
}
|
|
507
|
+
if (!proposed.archive.root.equals(expectedArchiveRoot)) {
|
|
508
|
+
throw new ProposedCheckpointArchiveRootMismatchError(expectedArchiveRoot, proposed.archive.root);
|
|
509
|
+
}
|
|
510
|
+
// Verify sequentiality: promoted checkpoint must follow the latest confirmed one
|
|
511
|
+
const latestCheckpointNumber = await this.getLatestCheckpointNumber();
|
|
512
|
+
if (latestCheckpointNumber !== proposed.checkpointNumber - 1) {
|
|
513
|
+
throw new ProposedCheckpointPromotionNotSequentialError(proposed.checkpointNumber, latestCheckpointNumber);
|
|
514
|
+
}
|
|
515
|
+
// Write the checkpoint entry
|
|
516
|
+
await this.#checkpoints.set(proposed.checkpointNumber, {
|
|
517
|
+
header: proposed.header.toBuffer(),
|
|
518
|
+
archive: proposed.archive.toBuffer(),
|
|
519
|
+
checkpointOutHash: proposed.checkpointOutHash.toBuffer(),
|
|
520
|
+
l1: l1.toBuffer(),
|
|
521
|
+
attestations: attestations.map((attestation)=>attestation.toBuffer()),
|
|
522
|
+
checkpointNumber: proposed.checkpointNumber,
|
|
523
|
+
startBlock: proposed.startBlock,
|
|
524
|
+
blockCount: proposed.blockCount
|
|
525
|
+
});
|
|
526
|
+
// Update the slot-to-checkpoint index
|
|
527
|
+
await this.#slotToCheckpoint.set(proposed.header.slotNumber, proposed.checkpointNumber);
|
|
528
|
+
// Clear the proposed checkpoint singleton
|
|
529
|
+
await this.#proposedCheckpoint.delete();
|
|
530
|
+
// Update the last synced L1 block
|
|
531
|
+
await this.#lastSynchedL1Block.set(l1.blockNumber);
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
/** Clears the proposed checkpoint if the given confirmed checkpoint number supersedes it. */ async clearProposedCheckpointIfSuperseded(confirmedCheckpointNumber) {
|
|
535
|
+
const proposedCheckpointNumber = await this.getProposedCheckpointNumber();
|
|
536
|
+
if (proposedCheckpointNumber <= confirmedCheckpointNumber) {
|
|
537
|
+
await this.#proposedCheckpoint.delete();
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
/** Returns the proposed checkpoint data, or undefined if no proposed checkpoint exists. No fallback to confirmed. */ async getProposedCheckpointOnly() {
|
|
541
|
+
const stored = await this.#proposedCheckpoint.getAsync();
|
|
542
|
+
if (!stored) {
|
|
543
|
+
return undefined;
|
|
544
|
+
}
|
|
545
|
+
return this.convertToProposedCheckpointData(stored);
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Gets the checkpoint at the proposed tip
|
|
549
|
+
* - pending checkpoint if it exists
|
|
550
|
+
* - fallsback to latest confirmed checkpoint otherwise
|
|
551
|
+
* @returns CommonCheckpointData
|
|
552
|
+
*/ async getProposedCheckpoint() {
|
|
553
|
+
const stored = await this.#proposedCheckpoint.getAsync();
|
|
554
|
+
if (!stored) {
|
|
555
|
+
return this.getCheckpointData(await this.getLatestCheckpointNumber());
|
|
556
|
+
}
|
|
557
|
+
return this.convertToProposedCheckpointData(stored);
|
|
558
|
+
}
|
|
559
|
+
convertToProposedCheckpointData(stored) {
|
|
560
|
+
return {
|
|
561
|
+
checkpointNumber: CheckpointNumber(stored.checkpointNumber),
|
|
562
|
+
header: CheckpointHeader.fromBuffer(stored.header),
|
|
563
|
+
archive: AppendOnlyTreeSnapshot.fromBuffer(stored.archive),
|
|
564
|
+
checkpointOutHash: Fr.fromBuffer(stored.checkpointOutHash),
|
|
565
|
+
startBlock: BlockNumber(stored.startBlock),
|
|
566
|
+
blockCount: stored.blockCount,
|
|
567
|
+
totalManaUsed: BigInt(stored.totalManaUsed),
|
|
568
|
+
feeAssetPriceModifier: BigInt(stored.feeAssetPriceModifier)
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Attempts to get the proposedCheckpoint's number, if there is not one, then fallback to the latest confirmed checkpoint number.
|
|
573
|
+
* @returns CheckpointNumber
|
|
574
|
+
*/ async getProposedCheckpointNumber() {
|
|
575
|
+
const proposed = await this.getProposedCheckpoint();
|
|
576
|
+
if (!proposed) {
|
|
577
|
+
return await this.getLatestCheckpointNumber();
|
|
578
|
+
}
|
|
579
|
+
return CheckpointNumber(proposed.checkpointNumber);
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Attempts to get the proposedCheckpoint's block number, if there is not one, then fallback to the checkpointed block number
|
|
583
|
+
* @returns BlockNumber
|
|
584
|
+
*/ async getProposedCheckpointL2BlockNumber() {
|
|
585
|
+
const proposed = await this.getProposedCheckpoint();
|
|
586
|
+
if (!proposed) {
|
|
587
|
+
return await this.getCheckpointedL2BlockNumber();
|
|
588
|
+
}
|
|
589
|
+
return BlockNumber(proposed.startBlock + proposed.blockCount - 1);
|
|
590
|
+
}
|
|
419
591
|
async getCheckpointedBlock(number) {
|
|
420
592
|
const blockStorage = await this.#blocks.getAsync(number);
|
|
421
593
|
if (!blockStorage) {
|
|
@@ -593,7 +765,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
593
765
|
return {
|
|
594
766
|
header: BlockHeader.fromBuffer(blockStorage.header),
|
|
595
767
|
archive: AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive),
|
|
596
|
-
blockHash:
|
|
768
|
+
blockHash: BlockHash.fromBuffer(blockStorage.blockHash),
|
|
597
769
|
checkpointNumber: CheckpointNumber(blockStorage.checkpointNumber),
|
|
598
770
|
indexWithinCheckpoint: IndexWithinCheckpoint(blockStorage.indexWithinCheckpoint)
|
|
599
771
|
};
|
|
@@ -640,17 +812,18 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
640
812
|
* Gets a receipt of a settled tx.
|
|
641
813
|
* @param txHash - The hash of a tx we try to get the receipt for.
|
|
642
814
|
* @returns The requested tx receipt (or undefined if not found).
|
|
643
|
-
*/ async getSettledTxReceipt(txHash) {
|
|
815
|
+
*/ async getSettledTxReceipt(txHash, l1Constants) {
|
|
644
816
|
const txEffect = await this.getTxEffect(txHash);
|
|
645
817
|
if (!txEffect) {
|
|
646
818
|
return undefined;
|
|
647
819
|
}
|
|
648
820
|
const blockNumber = BlockNumber(txEffect.l2BlockNumber);
|
|
649
821
|
// Use existing archiver methods to determine finalization level
|
|
650
|
-
const [provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber] = await Promise.all([
|
|
822
|
+
const [provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber, blockData] = await Promise.all([
|
|
651
823
|
this.getProvenBlockNumber(),
|
|
652
824
|
this.getCheckpointedL2BlockNumber(),
|
|
653
|
-
this.getFinalizedL2BlockNumber()
|
|
825
|
+
this.getFinalizedL2BlockNumber(),
|
|
826
|
+
this.getBlockData(blockNumber)
|
|
654
827
|
]);
|
|
655
828
|
let status;
|
|
656
829
|
if (blockNumber <= finalizedBlockNumber) {
|
|
@@ -662,7 +835,8 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
662
835
|
} else {
|
|
663
836
|
status = TxStatus.PROPOSED;
|
|
664
837
|
}
|
|
665
|
-
|
|
838
|
+
const epochNumber = blockData && l1Constants ? getEpochAtSlot(blockData.header.globalVariables.slotNumber, l1Constants) : undefined;
|
|
839
|
+
return new TxReceipt(txHash, status, TxReceipt.executionResultFromRevertCode(txEffect.data.revertCode), undefined, txEffect.data.transactionFee.toBigInt(), txEffect.l2BlockHash, blockNumber, epochNumber);
|
|
666
840
|
}
|
|
667
841
|
/**
|
|
668
842
|
* Looks up which block included the requested tx effect.
|
|
@@ -713,6 +887,42 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
713
887
|
setSynchedL1BlockNumber(l1BlockNumber) {
|
|
714
888
|
return this.#lastSynchedL1Block.set(l1BlockNumber);
|
|
715
889
|
}
|
|
890
|
+
/** Sets the proposed checkpoint (not yet L1-confirmed). Only accepts confirmed + 1.
|
|
891
|
+
* Computes archive and checkpointOutHash from the stored blocks. */ async setProposedCheckpoint(proposed) {
|
|
892
|
+
return await this.db.transactionAsync(async ()=>{
|
|
893
|
+
const current = await this.getProposedCheckpointNumber();
|
|
894
|
+
if (proposed.checkpointNumber <= current) {
|
|
895
|
+
throw new ProposedCheckpointStaleError(proposed.checkpointNumber, current);
|
|
896
|
+
}
|
|
897
|
+
const confirmed = await this.getLatestCheckpointNumber();
|
|
898
|
+
if (proposed.checkpointNumber !== confirmed + 1) {
|
|
899
|
+
throw new ProposedCheckpointNotSequentialError(proposed.checkpointNumber, confirmed);
|
|
900
|
+
}
|
|
901
|
+
// Ensure the previous checkpoint + blocks exist
|
|
902
|
+
const previousBlock = await this.getPreviousCheckpointBlock(proposed.checkpointNumber);
|
|
903
|
+
const blocks = [];
|
|
904
|
+
for(let i = 0; i < proposed.blockCount; i++){
|
|
905
|
+
const block = await this.getBlock(BlockNumber(proposed.startBlock + i));
|
|
906
|
+
if (!block) {
|
|
907
|
+
throw new BlockNotFoundError(proposed.startBlock + i);
|
|
908
|
+
}
|
|
909
|
+
blocks.push(block);
|
|
910
|
+
}
|
|
911
|
+
this.validateCheckpointBlocks(blocks, previousBlock);
|
|
912
|
+
const archive = blocks[blocks.length - 1].archive;
|
|
913
|
+
const checkpointOutHash = Checkpoint.getCheckpointOutHash(blocks);
|
|
914
|
+
await this.#proposedCheckpoint.set({
|
|
915
|
+
header: proposed.header.toBuffer(),
|
|
916
|
+
archive: archive.toBuffer(),
|
|
917
|
+
checkpointOutHash: checkpointOutHash.toBuffer(),
|
|
918
|
+
checkpointNumber: proposed.checkpointNumber,
|
|
919
|
+
startBlock: proposed.startBlock,
|
|
920
|
+
blockCount: proposed.blockCount,
|
|
921
|
+
totalManaUsed: proposed.totalManaUsed.toString(),
|
|
922
|
+
feeAssetPriceModifier: proposed.feeAssetPriceModifier.toString()
|
|
923
|
+
});
|
|
924
|
+
});
|
|
925
|
+
}
|
|
716
926
|
async getProvenCheckpointNumber() {
|
|
717
927
|
const [latestCheckpointNumber, provenCheckpointNumber] = await Promise.all([
|
|
718
928
|
this.getLatestCheckpointNumber(),
|