@aztec/archiver 0.0.1-commit.d431d1c → 0.0.1-commit.db765a8
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 +9 -0
- package/dest/archiver.d.ts +10 -6
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +50 -111
- package/dest/errors.d.ts +6 -1
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +8 -0
- package/dest/factory.d.ts +5 -2
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +16 -13
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- package/dest/l1/bin/retrieve-calldata.js +35 -32
- package/dest/l1/calldata_retriever.d.ts +73 -50
- package/dest/l1/calldata_retriever.d.ts.map +1 -1
- package/dest/l1/calldata_retriever.js +190 -259
- package/dest/l1/data_retrieval.d.ts +9 -9
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/l1/data_retrieval.js +24 -22
- package/dest/l1/spire_proposer.d.ts +5 -5
- package/dest/l1/spire_proposer.d.ts.map +1 -1
- package/dest/l1/spire_proposer.js +9 -17
- package/dest/l1/validate_trace.d.ts +6 -3
- package/dest/l1/validate_trace.d.ts.map +1 -1
- package/dest/l1/validate_trace.js +13 -9
- package/dest/modules/data_source_base.d.ts +23 -19
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +44 -119
- package/dest/modules/data_store_updater.d.ts +31 -20
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +79 -60
- package/dest/modules/instrumentation.d.ts +17 -4
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +36 -12
- package/dest/modules/l1_synchronizer.d.ts +4 -8
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +23 -19
- package/dest/store/block_store.d.ts +50 -32
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +147 -54
- package/dest/store/contract_class_store.d.ts +1 -1
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +11 -7
- package/dest/store/kv_archiver_store.d.ts +43 -25
- package/dest/store/kv_archiver_store.d.ts.map +1 -1
- package/dest/store/kv_archiver_store.js +38 -17
- 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 +4 -4
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +57 -37
- package/dest/test/fake_l1_state.d.ts +9 -4
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +56 -18
- package/dest/test/index.js +3 -1
- package/dest/test/mock_archiver.d.ts +1 -1
- package/dest/test/mock_archiver.d.ts.map +1 -1
- package/dest/test/mock_archiver.js +3 -2
- package/dest/test/mock_l2_block_source.d.ts +36 -21
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +151 -109
- package/dest/test/mock_structs.d.ts +3 -2
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +11 -9
- 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 +14 -13
- package/src/archiver.ts +71 -136
- package/src/errors.ts +12 -0
- package/src/factory.ts +30 -14
- package/src/index.ts +1 -0
- package/src/l1/README.md +25 -68
- package/src/l1/bin/retrieve-calldata.ts +45 -33
- package/src/l1/calldata_retriever.ts +249 -379
- package/src/l1/data_retrieval.ts +27 -29
- package/src/l1/spire_proposer.ts +7 -15
- package/src/l1/validate_trace.ts +24 -6
- package/src/modules/data_source_base.ts +73 -163
- package/src/modules/data_store_updater.ts +92 -63
- package/src/modules/instrumentation.ts +46 -14
- package/src/modules/l1_synchronizer.ts +26 -24
- package/src/store/block_store.ts +188 -92
- package/src/store/contract_class_store.ts +11 -7
- package/src/store/kv_archiver_store.ts +69 -29
- package/src/store/l2_tips_cache.ts +89 -0
- package/src/store/log_store.ts +105 -43
- package/src/test/fake_l1_state.ts +77 -19
- package/src/test/index.ts +3 -0
- package/src/test/mock_archiver.ts +3 -2
- package/src/test/mock_l2_block_source.ts +196 -126
- package/src/test/mock_structs.ts +26 -10
- package/src/test/noop_l1_archiver.ts +109 -0
|
@@ -6,19 +6,21 @@ 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,
|
|
9
|
+
import { Body, CheckpointedL2Block, CommitteeAttestation, L2Block, deserializeValidateCheckpointResult, serializeValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
10
10
|
import { L1PublishedData } from '@aztec/stdlib/checkpoint';
|
|
11
11
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
12
12
|
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
13
|
-
import { BlockHeader, TxHash, TxReceipt, deserializeIndexedTxEffect, serializeIndexedTxEffect } from '@aztec/stdlib/tx';
|
|
14
|
-
import { BlockArchiveNotConsistentError, BlockIndexNotSequentialError, BlockNotFoundError, BlockNumberNotSequentialError, CheckpointNotFoundError, CheckpointNumberNotConsistentError, CheckpointNumberNotSequentialError, InitialBlockNumberNotSequentialError, InitialCheckpointNumberNotSequentialError } from '../errors.js';
|
|
13
|
+
import { BlockHeader, TxHash, TxReceipt, TxStatus, deserializeIndexedTxEffect, serializeIndexedTxEffect } from '@aztec/stdlib/tx';
|
|
14
|
+
import { BlockArchiveNotConsistentError, BlockIndexNotSequentialError, BlockNotFoundError, BlockNumberNotSequentialError, CannotOverwriteCheckpointedBlockError, CheckpointNotFoundError, CheckpointNumberNotConsistentError, CheckpointNumberNotSequentialError, InitialBlockNumberNotSequentialError, InitialCheckpointNumberNotSequentialError } from '../errors.js';
|
|
15
15
|
export { TxReceipt } from '@aztec/stdlib/tx';
|
|
16
16
|
/**
|
|
17
17
|
* LMDB-based block storage for the archiver.
|
|
18
18
|
*/ export class BlockStore {
|
|
19
19
|
db;
|
|
20
|
+
l1Constants;
|
|
20
21
|
/** Map block number to block data */ #blocks;
|
|
21
22
|
/** Map checkpoint number to checkpoint data */ #checkpoints;
|
|
23
|
+
/** Map slot number to checkpoint number, for looking up checkpoints by slot range. */ #slotToCheckpoint;
|
|
22
24
|
/** Map block hash to list of tx hashes */ #blockTxs;
|
|
23
25
|
/** Tx hash to serialized IndexedTxEffect */ #txEffects;
|
|
24
26
|
/** Stores L1 block number in which the last processed L2 block was included */ #lastSynchedL1Block;
|
|
@@ -28,8 +30,9 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
28
30
|
/** Index mapping block hash to block number */ #blockHashIndex;
|
|
29
31
|
/** Index mapping block archive to block number */ #blockArchiveIndex;
|
|
30
32
|
#log;
|
|
31
|
-
constructor(db){
|
|
33
|
+
constructor(db, l1Constants){
|
|
32
34
|
this.db = db;
|
|
35
|
+
this.l1Constants = l1Constants;
|
|
33
36
|
this.#log = createLogger('archiver:block_store');
|
|
34
37
|
this.#blocks = db.openMap('archiver_blocks');
|
|
35
38
|
this.#blockTxs = db.openMap('archiver_block_txs');
|
|
@@ -41,12 +44,25 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
41
44
|
this.#lastProvenCheckpoint = db.openSingleton('archiver_last_proven_l2_checkpoint');
|
|
42
45
|
this.#pendingChainValidationStatus = db.openSingleton('archiver_pending_chain_validation_status');
|
|
43
46
|
this.#checkpoints = db.openMap('archiver_checkpoints');
|
|
47
|
+
this.#slotToCheckpoint = db.openMap('archiver_slot_to_checkpoint');
|
|
44
48
|
}
|
|
45
49
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
50
|
+
* Computes the finalized block number based on the proven block number.
|
|
51
|
+
* A block is considered finalized when it's 2 epochs behind the proven block.
|
|
52
|
+
* TODO(#13569): Compute proper finalized block number based on L1 finalized block.
|
|
53
|
+
* TODO(palla/mbps): Even the provisional computation is wrong, since it should subtract checkpoints, not blocks
|
|
54
|
+
* @returns The finalized block number.
|
|
55
|
+
*/ async getFinalizedL2BlockNumber() {
|
|
56
|
+
const provenBlockNumber = await this.getProvenBlockNumber();
|
|
57
|
+
return BlockNumber(Math.max(provenBlockNumber - this.l1Constants.epochDuration * 2, 0));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Append new proposed blocks to the store's list. All blocks must be for the 'current' checkpoint.
|
|
61
|
+
* These are uncheckpointed blocks that have been proposed by the sequencer but not yet included in a checkpoint on L1.
|
|
62
|
+
* For checkpointed blocks (already published to L1), use addCheckpoints() instead.
|
|
63
|
+
* @param blocks - The proposed L2 blocks to be added to the store.
|
|
48
64
|
* @returns True if the operation is successful.
|
|
49
|
-
*/ async
|
|
65
|
+
*/ async addProposedBlocks(blocks, opts = {}) {
|
|
50
66
|
if (blocks.length === 0) {
|
|
51
67
|
return true;
|
|
52
68
|
}
|
|
@@ -59,6 +75,11 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
59
75
|
// Extract the latest block and checkpoint numbers
|
|
60
76
|
const previousBlockNumber = await this.getLatestBlockNumber();
|
|
61
77
|
const previousCheckpointNumber = await this.getLatestCheckpointNumber();
|
|
78
|
+
// Verify we're not overwriting checkpointed blocks
|
|
79
|
+
const lastCheckpointedBlockNumber = await this.getCheckpointedL2BlockNumber();
|
|
80
|
+
if (!opts.force && firstBlockNumber <= lastCheckpointedBlockNumber) {
|
|
81
|
+
throw new CannotOverwriteCheckpointedBlockError(firstBlockNumber, lastCheckpointedBlockNumber);
|
|
82
|
+
}
|
|
62
83
|
// Check that the first block number is the expected one
|
|
63
84
|
if (!opts.force && previousBlockNumber !== firstBlockNumber - 1) {
|
|
64
85
|
throw new InitialBlockNumberNotSequentialError(firstBlockNumber, previousBlockNumber);
|
|
@@ -136,7 +157,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
136
157
|
let previousBlock = undefined;
|
|
137
158
|
// If we have a previous checkpoint then we need to get the previous block number
|
|
138
159
|
if (previousCheckpointData !== undefined) {
|
|
139
|
-
previousBlockNumber = BlockNumber(previousCheckpointData.startBlock + previousCheckpointData.
|
|
160
|
+
previousBlockNumber = BlockNumber(previousCheckpointData.startBlock + previousCheckpointData.blockCount - 1);
|
|
140
161
|
previousBlock = await this.getBlock(previousBlockNumber);
|
|
141
162
|
if (previousBlock === undefined) {
|
|
142
163
|
// We should be able to get the required previous block
|
|
@@ -181,19 +202,22 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
181
202
|
await this.#checkpoints.set(checkpoint.checkpoint.number, {
|
|
182
203
|
header: checkpoint.checkpoint.header.toBuffer(),
|
|
183
204
|
archive: checkpoint.checkpoint.archive.toBuffer(),
|
|
205
|
+
checkpointOutHash: checkpoint.checkpoint.getCheckpointOutHash().toBuffer(),
|
|
184
206
|
l1: checkpoint.l1.toBuffer(),
|
|
185
207
|
attestations: checkpoint.attestations.map((attestation)=>attestation.toBuffer()),
|
|
186
208
|
checkpointNumber: checkpoint.checkpoint.number,
|
|
187
209
|
startBlock: checkpoint.checkpoint.blocks[0].number,
|
|
188
|
-
|
|
210
|
+
blockCount: checkpoint.checkpoint.blocks.length
|
|
189
211
|
});
|
|
212
|
+
// Update slot-to-checkpoint index
|
|
213
|
+
await this.#slotToCheckpoint.set(checkpoint.checkpoint.header.slotNumber, checkpoint.checkpoint.number);
|
|
190
214
|
}
|
|
191
215
|
await this.#lastSynchedL1Block.set(checkpoints[checkpoints.length - 1].l1.blockNumber);
|
|
192
216
|
return true;
|
|
193
217
|
});
|
|
194
218
|
}
|
|
195
219
|
async addBlockToDatabase(block, checkpointNumber, indexWithinCheckpoint) {
|
|
196
|
-
const blockHash =
|
|
220
|
+
const blockHash = await block.hash();
|
|
197
221
|
await this.#blocks.set(block.number, {
|
|
198
222
|
header: block.header.toBuffer(),
|
|
199
223
|
blockHash: blockHash.toBuffer(),
|
|
@@ -228,41 +252,50 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
228
252
|
await this.#blockArchiveIndex.delete(block.archive.root.toString());
|
|
229
253
|
}
|
|
230
254
|
/**
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
|
|
235
|
-
* @returns True if the operation is successful
|
|
236
|
-
*/ async unwindCheckpoints(from, checkpointsToUnwind) {
|
|
255
|
+
* Removes all checkpoints with checkpoint number > checkpointNumber.
|
|
256
|
+
* Also removes ALL blocks (both checkpointed and uncheckpointed) after the last block of the given checkpoint.
|
|
257
|
+
* @param checkpointNumber - Remove all checkpoints strictly after this one.
|
|
258
|
+
*/ async removeCheckpointsAfter(checkpointNumber) {
|
|
237
259
|
return await this.db.transactionAsync(async ()=>{
|
|
238
|
-
const
|
|
239
|
-
if (
|
|
240
|
-
|
|
260
|
+
const latestCheckpointNumber = await this.getLatestCheckpointNumber();
|
|
261
|
+
if (checkpointNumber >= latestCheckpointNumber) {
|
|
262
|
+
this.#log.warn(`No checkpoints to remove after ${checkpointNumber} (latest is ${latestCheckpointNumber})`);
|
|
263
|
+
return {
|
|
264
|
+
blocksRemoved: undefined
|
|
265
|
+
};
|
|
241
266
|
}
|
|
267
|
+
// If the proven checkpoint is beyond the target, update it
|
|
242
268
|
const proven = await this.getProvenCheckpointNumber();
|
|
243
|
-
if (
|
|
244
|
-
|
|
269
|
+
if (proven > checkpointNumber) {
|
|
270
|
+
this.#log.warn(`Updating proven checkpoint ${proven} to last valid checkpoint ${checkpointNumber}`);
|
|
271
|
+
await this.setProvenCheckpointNumber(checkpointNumber);
|
|
245
272
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
273
|
+
// Find the last block number to keep (last block of the given checkpoint, or 0 if no checkpoint)
|
|
274
|
+
let lastBlockToKeep;
|
|
275
|
+
if (checkpointNumber <= 0) {
|
|
276
|
+
lastBlockToKeep = BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
277
|
+
} else {
|
|
278
|
+
const targetCheckpoint = await this.#checkpoints.getAsync(checkpointNumber);
|
|
279
|
+
if (!targetCheckpoint) {
|
|
280
|
+
throw new Error(`Target checkpoint ${checkpointNumber} not found in store`);
|
|
252
281
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
this.#
|
|
282
|
+
lastBlockToKeep = BlockNumber(targetCheckpoint.startBlock + targetCheckpoint.blockCount - 1);
|
|
283
|
+
}
|
|
284
|
+
// Remove all blocks after lastBlockToKeep (both checkpointed and uncheckpointed)
|
|
285
|
+
const blocksRemoved = await this.removeBlocksAfter(lastBlockToKeep);
|
|
286
|
+
// Remove all checkpoints after the target
|
|
287
|
+
for(let c = latestCheckpointNumber; c > checkpointNumber; c = CheckpointNumber(c - 1)){
|
|
288
|
+
const checkpointStorage = await this.#checkpoints.getAsync(c);
|
|
289
|
+
if (checkpointStorage) {
|
|
290
|
+
const slotNumber = CheckpointHeader.fromBuffer(checkpointStorage.header).slotNumber;
|
|
291
|
+
await this.#slotToCheckpoint.delete(slotNumber);
|
|
263
292
|
}
|
|
293
|
+
await this.#checkpoints.delete(c);
|
|
294
|
+
this.#log.debug(`Removed checkpoint ${c}`);
|
|
264
295
|
}
|
|
265
|
-
return
|
|
296
|
+
return {
|
|
297
|
+
blocksRemoved
|
|
298
|
+
};
|
|
266
299
|
});
|
|
267
300
|
}
|
|
268
301
|
async getCheckpointData(checkpointNumber) {
|
|
@@ -283,17 +316,30 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
283
316
|
}
|
|
284
317
|
return checkpoints;
|
|
285
318
|
}
|
|
319
|
+
/** Returns checkpoint data for all checkpoints whose slot falls within the given range (inclusive). */ async getCheckpointDataForSlotRange(startSlot, endSlot) {
|
|
320
|
+
const result = [];
|
|
321
|
+
for await (const [, checkpointNumber] of this.#slotToCheckpoint.entriesAsync({
|
|
322
|
+
start: startSlot,
|
|
323
|
+
end: endSlot + 1
|
|
324
|
+
})){
|
|
325
|
+
const checkpointStorage = await this.#checkpoints.getAsync(checkpointNumber);
|
|
326
|
+
if (checkpointStorage) {
|
|
327
|
+
result.push(this.checkpointDataFromCheckpointStorage(checkpointStorage));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return result;
|
|
331
|
+
}
|
|
286
332
|
checkpointDataFromCheckpointStorage(checkpointStorage) {
|
|
287
|
-
|
|
333
|
+
return {
|
|
288
334
|
header: CheckpointHeader.fromBuffer(checkpointStorage.header),
|
|
289
335
|
archive: AppendOnlyTreeSnapshot.fromBuffer(checkpointStorage.archive),
|
|
336
|
+
checkpointOutHash: Fr.fromBuffer(checkpointStorage.checkpointOutHash),
|
|
290
337
|
checkpointNumber: CheckpointNumber(checkpointStorage.checkpointNumber),
|
|
291
|
-
startBlock: checkpointStorage.startBlock,
|
|
292
|
-
|
|
338
|
+
startBlock: BlockNumber(checkpointStorage.startBlock),
|
|
339
|
+
blockCount: checkpointStorage.blockCount,
|
|
293
340
|
l1: L1PublishedData.fromBuffer(checkpointStorage.l1),
|
|
294
|
-
attestations: checkpointStorage.attestations
|
|
341
|
+
attestations: checkpointStorage.attestations.map((buf)=>CommitteeAttestation.fromBuffer(buf))
|
|
295
342
|
};
|
|
296
|
-
return data;
|
|
297
343
|
}
|
|
298
344
|
async getBlocksForCheckpoint(checkpointNumber) {
|
|
299
345
|
const checkpoint = await this.#checkpoints.getAsync(checkpointNumber);
|
|
@@ -302,7 +348,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
302
348
|
}
|
|
303
349
|
const blocksForCheckpoint = await toArray(this.#blocks.entriesAsync({
|
|
304
350
|
start: checkpoint.startBlock,
|
|
305
|
-
end: checkpoint.startBlock + checkpoint.
|
|
351
|
+
end: checkpoint.startBlock + checkpoint.blockCount
|
|
306
352
|
}));
|
|
307
353
|
const converted = await Promise.all(blocksForCheckpoint.map((x)=>this.getBlockFromBlockStorage(x[0], x[1])));
|
|
308
354
|
return converted.filter(isDefined);
|
|
@@ -332,9 +378,10 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
332
378
|
}
|
|
333
379
|
/**
|
|
334
380
|
* Removes all blocks with block number > blockNumber.
|
|
381
|
+
* Does not remove any associated checkpoints.
|
|
335
382
|
* @param blockNumber - The block number to remove after.
|
|
336
383
|
* @returns The removed blocks (for event emission).
|
|
337
|
-
*/ async
|
|
384
|
+
*/ async removeBlocksAfter(blockNumber) {
|
|
338
385
|
return await this.db.transactionAsync(async ()=>{
|
|
339
386
|
const removedBlocks = [];
|
|
340
387
|
// Get the latest block number to determine the range
|
|
@@ -362,7 +409,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
362
409
|
if (!checkpointStorage) {
|
|
363
410
|
throw new CheckpointNotFoundError(provenCheckpointNumber);
|
|
364
411
|
} else {
|
|
365
|
-
return BlockNumber(checkpointStorage.startBlock + checkpointStorage.
|
|
412
|
+
return BlockNumber(checkpointStorage.startBlock + checkpointStorage.blockCount - 1);
|
|
366
413
|
}
|
|
367
414
|
}
|
|
368
415
|
async getLatestBlockNumber() {
|
|
@@ -444,6 +491,28 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
444
491
|
}
|
|
445
492
|
}
|
|
446
493
|
/**
|
|
494
|
+
* Gets block metadata (without tx data) by block number.
|
|
495
|
+
* @param blockNumber - The number of the block to return.
|
|
496
|
+
* @returns The requested block data.
|
|
497
|
+
*/ async getBlockData(blockNumber) {
|
|
498
|
+
const blockStorage = await this.#blocks.getAsync(blockNumber);
|
|
499
|
+
if (!blockStorage || !blockStorage.header) {
|
|
500
|
+
return undefined;
|
|
501
|
+
}
|
|
502
|
+
return this.getBlockDataFromBlockStorage(blockStorage);
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Gets block metadata (without tx data) by archive root.
|
|
506
|
+
* @param archive - The archive root of the block to return.
|
|
507
|
+
* @returns The requested block data.
|
|
508
|
+
*/ async getBlockDataByArchive(archive) {
|
|
509
|
+
const blockNumber = await this.#blockArchiveIndex.getAsync(archive.toString());
|
|
510
|
+
if (blockNumber === undefined) {
|
|
511
|
+
return undefined;
|
|
512
|
+
}
|
|
513
|
+
return this.getBlockData(BlockNumber(blockNumber));
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
447
516
|
* Gets an L2 block.
|
|
448
517
|
* @param blockNumber - The number of the block to return.
|
|
449
518
|
* @returns The requested L2 block.
|
|
@@ -533,12 +602,19 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
533
602
|
];
|
|
534
603
|
}
|
|
535
604
|
}
|
|
605
|
+
getBlockDataFromBlockStorage(blockStorage) {
|
|
606
|
+
return {
|
|
607
|
+
header: BlockHeader.fromBuffer(blockStorage.header),
|
|
608
|
+
archive: AppendOnlyTreeSnapshot.fromBuffer(blockStorage.archive),
|
|
609
|
+
blockHash: Fr.fromBuffer(blockStorage.blockHash),
|
|
610
|
+
checkpointNumber: CheckpointNumber(blockStorage.checkpointNumber),
|
|
611
|
+
indexWithinCheckpoint: IndexWithinCheckpoint(blockStorage.indexWithinCheckpoint)
|
|
612
|
+
};
|
|
613
|
+
}
|
|
536
614
|
async getBlockFromBlockStorage(blockNumber, blockStorage) {
|
|
537
|
-
const header =
|
|
538
|
-
|
|
539
|
-
const
|
|
540
|
-
header.setHash(Fr.fromBuffer(blockHash));
|
|
541
|
-
const blockHashString = bufferToHex(blockHash);
|
|
615
|
+
const { header, archive, blockHash, checkpointNumber, indexWithinCheckpoint } = this.getBlockDataFromBlockStorage(blockStorage);
|
|
616
|
+
header.setHash(blockHash);
|
|
617
|
+
const blockHashString = bufferToHex(blockStorage.blockHash);
|
|
542
618
|
const blockTxsBuffer = await this.#blockTxs.getAsync(blockHashString);
|
|
543
619
|
if (blockTxsBuffer === undefined) {
|
|
544
620
|
this.#log.warn(`Could not find body for block ${header.globalVariables.blockNumber} ${blockHash}`);
|
|
@@ -556,7 +632,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
556
632
|
txEffects.push(deserializeIndexedTxEffect(txEffect).data);
|
|
557
633
|
}
|
|
558
634
|
const body = new Body(txEffects);
|
|
559
|
-
const block = new
|
|
635
|
+
const block = new L2Block(archive, header, body, checkpointNumber, indexWithinCheckpoint);
|
|
560
636
|
if (block.number !== blockNumber) {
|
|
561
637
|
throw new Error(`Block number mismatch when retrieving block from archive (expected ${blockNumber} but got ${block.number} with hash ${blockHashString})`);
|
|
562
638
|
}
|
|
@@ -582,7 +658,24 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
582
658
|
if (!txEffect) {
|
|
583
659
|
return undefined;
|
|
584
660
|
}
|
|
585
|
-
|
|
661
|
+
const blockNumber = BlockNumber(txEffect.l2BlockNumber);
|
|
662
|
+
// Use existing archiver methods to determine finalization level
|
|
663
|
+
const [provenBlockNumber, checkpointedBlockNumber, finalizedBlockNumber] = await Promise.all([
|
|
664
|
+
this.getProvenBlockNumber(),
|
|
665
|
+
this.getCheckpointedL2BlockNumber(),
|
|
666
|
+
this.getFinalizedL2BlockNumber()
|
|
667
|
+
]);
|
|
668
|
+
let status;
|
|
669
|
+
if (blockNumber <= finalizedBlockNumber) {
|
|
670
|
+
status = TxStatus.FINALIZED;
|
|
671
|
+
} else if (blockNumber <= provenBlockNumber) {
|
|
672
|
+
status = TxStatus.PROVEN;
|
|
673
|
+
} else if (blockNumber <= checkpointedBlockNumber) {
|
|
674
|
+
status = TxStatus.CHECKPOINTED;
|
|
675
|
+
} else {
|
|
676
|
+
status = TxStatus.PROPOSED;
|
|
677
|
+
}
|
|
678
|
+
return new TxReceipt(txHash, status, TxReceipt.executionResultFromRevertCode(txEffect.data.revertCode), undefined, txEffect.data.transactionFee.toBigInt(), txEffect.l2BlockHash, blockNumber);
|
|
586
679
|
}
|
|
587
680
|
/**
|
|
588
681
|
* Looks up which block included the requested tx effect.
|
|
@@ -615,7 +708,7 @@ export { TxReceipt } from '@aztec/stdlib/tx';
|
|
|
615
708
|
if (!checkpoint) {
|
|
616
709
|
return BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
|
|
617
710
|
}
|
|
618
|
-
return BlockNumber(checkpoint.startBlock + checkpoint.
|
|
711
|
+
return BlockNumber(checkpoint.startBlock + checkpoint.blockCount - 1);
|
|
619
712
|
}
|
|
620
713
|
async getLatestL2BlockNumber() {
|
|
621
714
|
const [lastBlockNumber] = await toArray(this.#blocks.keysAsync({
|
|
@@ -15,4 +15,4 @@ export declare class ContractClassStore {
|
|
|
15
15
|
getContractClassIds(): Promise<Fr[]>;
|
|
16
16
|
addFunctions(contractClassId: Fr, newPrivateFunctions: ExecutablePrivateFunctionWithMembershipProof[], newUtilityFunctions: UtilityFunctionWithMembershipProof[]): Promise<boolean>;
|
|
17
17
|
}
|
|
18
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3RfY2xhc3Nfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9jb250cmFjdF9jbGFzc19zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFHcEQsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQWlCLE1BQU0saUJBQWlCLENBQUM7QUFFeEUsT0FBTyxLQUFLLEVBQ1YsbUJBQW1CLEVBRW5CLDRDQUE0QyxFQUM1QyxrQ0FBa0MsRUFDbkMsTUFBTSx3QkFBd0IsQ0FBQztBQUdoQzs7R0FFRztBQUNILHFCQUFhLGtCQUFrQjs7SUFJakIsT0FBTyxDQUFDLEVBQUU7SUFBdEIsWUFBb0IsRUFBRSxFQUFFLGlCQUFpQixFQUd4QztJQUVLLGdCQUFnQixDQUNwQixhQUFhLEVBQUUsbUJBQW1CLEVBQ2xDLGtCQUFrQixFQUFFLEVBQUUsRUFDdEIsV0FBVyxFQUFFLE1BQU0sR0FDbEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQVFmO0lBRUsscUJBQXFCLENBQUMsYUFBYSxFQUFFLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQVFsRztJQUVLLGdCQUFnQixDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixHQUFHLFNBQVMsQ0FBQyxDQUd2RTtJQUVLLHFCQUFxQixDQUFDLEVBQUUsRUFBRSxFQUFFLEdBQUcsT0FBTyxDQUFDLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FHM0Q7SUFFSyxtQkFBbUIsSUFBSSxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FFekM7SUFFSyxZQUFZLENBQ2hCLGVBQWUsRUFBRSxFQUFFLEVBQ25CLG1CQUFtQixFQUFFLDRDQUE0QyxFQUFFLEVBQ25FLG1CQUFtQixFQUFFLGtDQUFrQyxFQUFFLEdBQ3hELE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0F5QmxCO0NBQ0YifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract_class_store.d.ts","sourceRoot":"","sources":["../../src/store/contract_class_store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AAExE,OAAO,KAAK,EACV,mBAAmB,EAEnB,4CAA4C,EAC5C,kCAAkC,EACnC,MAAM,wBAAwB,CAAC;AAGhC;;GAEG;AACH,qBAAa,kBAAkB;;IAIjB,OAAO,CAAC,EAAE;IAAtB,YAAoB,EAAE,EAAE,iBAAiB,EAGxC;IAEK,gBAAgB,CACpB,aAAa,EAAE,mBAAmB,EAClC,kBAAkB,EAAE,EAAE,EACtB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"contract_class_store.d.ts","sourceRoot":"","sources":["../../src/store/contract_class_store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AAGpD,OAAO,KAAK,EAAE,iBAAiB,EAAiB,MAAM,iBAAiB,CAAC;AAExE,OAAO,KAAK,EACV,mBAAmB,EAEnB,4CAA4C,EAC5C,kCAAkC,EACnC,MAAM,wBAAwB,CAAC;AAGhC;;GAEG;AACH,qBAAa,kBAAkB;;IAIjB,OAAO,CAAC,EAAE;IAAtB,YAAoB,EAAE,EAAE,iBAAiB,EAGxC;IAEK,gBAAgB,CACpB,aAAa,EAAE,mBAAmB,EAClC,kBAAkB,EAAE,EAAE,EACtB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAQf;IAEK,qBAAqB,CAAC,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlG;IAEK,gBAAgB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAGvE;IAEK,qBAAqB,CAAC,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,GAAG,SAAS,CAAC,CAG3D;IAEK,mBAAmB,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC,CAEzC;IAEK,YAAY,CAChB,eAAe,EAAE,EAAE,EACnB,mBAAmB,EAAE,4CAA4C,EAAE,EACnE,mBAAmB,EAAE,kCAAkC,EAAE,GACxD,OAAO,CAAC,OAAO,CAAC,CAyBlB;CACF"}
|
|
@@ -15,17 +15,21 @@ import { Vector } from '@aztec/stdlib/types';
|
|
|
15
15
|
this.#bytecodeCommitments = db.openMap('archiver_bytecode_commitments');
|
|
16
16
|
}
|
|
17
17
|
async addContractClass(contractClass, bytecodeCommitment, blockNumber) {
|
|
18
|
-
await this
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
await this.db.transactionAsync(async ()=>{
|
|
19
|
+
await this.#contractClasses.setIfNotExists(contractClass.id.toString(), serializeContractClassPublic({
|
|
20
|
+
...contractClass,
|
|
21
|
+
l2BlockNumber: blockNumber
|
|
22
|
+
}));
|
|
23
|
+
await this.#bytecodeCommitments.setIfNotExists(contractClass.id.toString(), bytecodeCommitment.toBuffer());
|
|
24
|
+
});
|
|
23
25
|
}
|
|
24
26
|
async deleteContractClasses(contractClass, blockNumber) {
|
|
25
27
|
const restoredContractClass = await this.#contractClasses.getAsync(contractClass.id.toString());
|
|
26
28
|
if (restoredContractClass && deserializeContractClassPublic(restoredContractClass).l2BlockNumber >= blockNumber) {
|
|
27
|
-
await this
|
|
28
|
-
|
|
29
|
+
await this.db.transactionAsync(async ()=>{
|
|
30
|
+
await this.#contractClasses.delete(contractClass.id.toString());
|
|
31
|
+
await this.#bytecodeCommitments.delete(contractClass.id.toString());
|
|
32
|
+
});
|
|
29
33
|
}
|
|
30
34
|
}
|
|
31
35
|
async getContractClass(id) {
|
|
@@ -4,15 +4,16 @@ import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
4
4
|
import type { AztecAsyncKVStore, CustomRange, StoreSize } from '@aztec/kv-store';
|
|
5
5
|
import { FunctionSelector } from '@aztec/stdlib/abi';
|
|
6
6
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
7
|
-
import { CheckpointedL2Block,
|
|
8
|
-
import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
7
|
+
import { type BlockData, BlockHash, CheckpointedL2Block, L2Block, type ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
8
|
+
import type { CheckpointData, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
9
9
|
import type { ContractClassPublic, ContractDataSource, ContractInstanceUpdateWithAddress, ContractInstanceWithAddress, ExecutablePrivateFunctionWithMembershipProof, UtilityFunctionWithMembershipProof } from '@aztec/stdlib/contract';
|
|
10
|
+
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
10
11
|
import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
|
|
11
12
|
import type { LogFilter, SiloedTag, Tag, TxScopedL2Log } from '@aztec/stdlib/logs';
|
|
12
13
|
import type { BlockHeader, TxHash, TxReceipt } from '@aztec/stdlib/tx';
|
|
13
14
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
14
15
|
import type { InboxMessage } from '../structs/inbox_message.js';
|
|
15
|
-
import { type
|
|
16
|
+
import { BlockStore, type RemoveCheckpointsResult } from './block_store.js';
|
|
16
17
|
export declare const ARCHIVER_DB_VERSION = 5;
|
|
17
18
|
export declare const MAX_FUNCTION_SIGNATURES = 1000;
|
|
18
19
|
export declare const MAX_FUNCTION_NAME_LEN = 256;
|
|
@@ -34,7 +35,9 @@ export declare class KVArchiverDataStore implements ContractDataSource {
|
|
|
34
35
|
private db;
|
|
35
36
|
static readonly SCHEMA_VERSION = 5;
|
|
36
37
|
private functionNames;
|
|
37
|
-
constructor(db: AztecAsyncKVStore, logsMaxPageSize
|
|
38
|
+
constructor(db: AztecAsyncKVStore, logsMaxPageSize: number | undefined, l1Constants: Pick<L1RollupConstants, 'epochDuration'>);
|
|
39
|
+
/** Returns the underlying block store. Used by L2TipsCache. */
|
|
40
|
+
get blockStore(): BlockStore;
|
|
38
41
|
/** Opens a new transaction to the underlying store and runs all operations within it. */
|
|
39
42
|
transactionAsync<T>(callback: () => Promise<T>): Promise<T>;
|
|
40
43
|
getBlockNumber(): Promise<BlockNumber>;
|
|
@@ -43,6 +46,8 @@ export declare class KVArchiverDataStore implements ContractDataSource {
|
|
|
43
46
|
backupTo(path: string, compress?: boolean): Promise<string>;
|
|
44
47
|
/** Closes the underlying data store. */
|
|
45
48
|
close(): Promise<void>;
|
|
49
|
+
/** Computes the finalized block number based on the proven block number. */
|
|
50
|
+
getFinalizedL2BlockNumber(): Promise<BlockNumber>;
|
|
46
51
|
/** Looks up a public function name given a selector. */
|
|
47
52
|
getDebugFunctionName(_address: AztecAddress, selector: FunctionSelector): Promise<string | undefined>;
|
|
48
53
|
/** Register a public function signature, so it can be looked up by selector. */
|
|
@@ -91,11 +96,13 @@ export declare class KVArchiverDataStore implements ContractDataSource {
|
|
|
91
96
|
addContractInstanceUpdates(data: ContractInstanceUpdateWithAddress[], timestamp: UInt64): Promise<boolean>;
|
|
92
97
|
deleteContractInstanceUpdates(data: ContractInstanceUpdateWithAddress[], timestamp: UInt64): Promise<boolean>;
|
|
93
98
|
/**
|
|
94
|
-
* Append new blocks to the store's list.
|
|
95
|
-
*
|
|
99
|
+
* Append new proposed blocks to the store's list.
|
|
100
|
+
* These are uncheckpointed blocks that have been proposed by the sequencer but not yet included in a checkpoint on L1.
|
|
101
|
+
* For checkpointed blocks (already published to L1), use addCheckpoints() instead.
|
|
102
|
+
* @param blocks - The proposed L2 blocks to be added to the store.
|
|
96
103
|
* @returns True if the operation is successful.
|
|
97
104
|
*/
|
|
98
|
-
|
|
105
|
+
addProposedBlocks(blocks: L2Block[], opts?: {
|
|
99
106
|
force?: boolean;
|
|
100
107
|
checkpointNumber?: number;
|
|
101
108
|
}): Promise<boolean>;
|
|
@@ -112,13 +119,11 @@ export declare class KVArchiverDataStore implements ContractDataSource {
|
|
|
112
119
|
*/
|
|
113
120
|
getLatestBlockNumber(): Promise<BlockNumber>;
|
|
114
121
|
/**
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
* @param checkpointsToUnwind - The number of checkpoints we are to unwind
|
|
119
|
-
* @returns True if the operation is successful
|
|
122
|
+
* Removes all checkpoints with checkpoint number > checkpointNumber.
|
|
123
|
+
* Also removes ALL blocks (both checkpointed and uncheckpointed) after the last block of the given checkpoint.
|
|
124
|
+
* @param checkpointNumber - Remove all checkpoints strictly after this one.
|
|
120
125
|
*/
|
|
121
|
-
|
|
126
|
+
removeCheckpointsAfter(checkpointNumber: CheckpointNumber): Promise<RemoveCheckpointsResult>;
|
|
122
127
|
/**
|
|
123
128
|
* Appends new checkpoints, and their blocks to the store's collection
|
|
124
129
|
* @param checkpoints The collection of checkpoints to be added
|
|
@@ -134,7 +139,7 @@ export declare class KVArchiverDataStore implements ContractDataSource {
|
|
|
134
139
|
* Returns the block for the given hash, or undefined if not exists.
|
|
135
140
|
* @param blockHash - The block hash to return.
|
|
136
141
|
*/
|
|
137
|
-
getCheckpointedBlockByHash(blockHash:
|
|
142
|
+
getCheckpointedBlockByHash(blockHash: BlockHash): Promise<CheckpointedL2Block | undefined>;
|
|
138
143
|
/**
|
|
139
144
|
* Returns the block for the given archive root, or undefined if not exists.
|
|
140
145
|
* @param archive - The archive root to return.
|
|
@@ -144,24 +149,24 @@ export declare class KVArchiverDataStore implements ContractDataSource {
|
|
|
144
149
|
* Returns the block for the given number, or undefined if not exists.
|
|
145
150
|
* @param number - The block number to return.
|
|
146
151
|
*/
|
|
147
|
-
getBlock(number: BlockNumber): Promise<
|
|
152
|
+
getBlock(number: BlockNumber): Promise<L2Block | undefined>;
|
|
148
153
|
/**
|
|
149
154
|
* Returns the block for the given hash, or undefined if not exists.
|
|
150
155
|
* @param blockHash - The block hash to return.
|
|
151
156
|
*/
|
|
152
|
-
getBlockByHash(blockHash:
|
|
157
|
+
getBlockByHash(blockHash: BlockHash): Promise<L2Block | undefined>;
|
|
153
158
|
/**
|
|
154
159
|
* Returns the block for the given archive root, or undefined if not exists.
|
|
155
160
|
* @param archive - The archive root to return.
|
|
156
161
|
*/
|
|
157
|
-
getBlockByArchive(archive: Fr): Promise<
|
|
162
|
+
getBlockByArchive(archive: Fr): Promise<L2Block | undefined>;
|
|
158
163
|
/**
|
|
159
164
|
* Gets up to `limit` amount of published L2 blocks starting from `from`.
|
|
160
165
|
* @param from - Number of the first block to return (inclusive).
|
|
161
166
|
* @param limit - The number of blocks to return.
|
|
162
167
|
* @returns The requested L2 blocks.
|
|
163
168
|
*/
|
|
164
|
-
getBlocks(from: BlockNumber, limit: number): Promise<
|
|
169
|
+
getBlocks(from: BlockNumber, limit: number): Promise<L2Block[]>;
|
|
165
170
|
/**
|
|
166
171
|
* Gets up to `limit` amount of checkpointed L2 blocks starting from `from`.
|
|
167
172
|
* @param from - Number of the first block to return (inclusive).
|
|
@@ -180,12 +185,22 @@ export declare class KVArchiverDataStore implements ContractDataSource {
|
|
|
180
185
|
* Returns the block header for the given hash, or undefined if not exists.
|
|
181
186
|
* @param blockHash - The block hash to return.
|
|
182
187
|
*/
|
|
183
|
-
getBlockHeaderByHash(blockHash:
|
|
188
|
+
getBlockHeaderByHash(blockHash: BlockHash): Promise<BlockHeader | undefined>;
|
|
184
189
|
/**
|
|
185
190
|
* Returns the block header for the given archive root, or undefined if not exists.
|
|
186
191
|
* @param archive - The archive root to return.
|
|
187
192
|
*/
|
|
188
193
|
getBlockHeaderByArchive(archive: Fr): Promise<BlockHeader | undefined>;
|
|
194
|
+
/**
|
|
195
|
+
* Gets block metadata (without tx data) by block number.
|
|
196
|
+
* @param blockNumber - The block number to return.
|
|
197
|
+
*/
|
|
198
|
+
getBlockData(blockNumber: BlockNumber): Promise<BlockData | undefined>;
|
|
199
|
+
/**
|
|
200
|
+
* Gets block metadata (without tx data) by archive root.
|
|
201
|
+
* @param archive - The archive root to return.
|
|
202
|
+
*/
|
|
203
|
+
getBlockDataByArchive(archive: Fr): Promise<BlockData | undefined>;
|
|
189
204
|
/**
|
|
190
205
|
* Gets a tx effect.
|
|
191
206
|
* @param txHash - The hash of the tx corresponding to the tx effect.
|
|
@@ -203,8 +218,8 @@ export declare class KVArchiverDataStore implements ContractDataSource {
|
|
|
203
218
|
* @param blocks - The blocks for which to add the logs.
|
|
204
219
|
* @returns True if the operation is successful.
|
|
205
220
|
*/
|
|
206
|
-
addLogs(blocks:
|
|
207
|
-
deleteLogs(blocks:
|
|
221
|
+
addLogs(blocks: L2Block[]): Promise<boolean>;
|
|
222
|
+
deleteLogs(blocks: L2Block[]): Promise<boolean>;
|
|
208
223
|
/**
|
|
209
224
|
* Get the total number of L1 to L2 messages
|
|
210
225
|
* @returns The number of L1 to L2 messages in the store
|
|
@@ -313,24 +328,27 @@ export declare class KVArchiverDataStore implements ContractDataSource {
|
|
|
313
328
|
* @param checkpointNumber Retrieves all blocks for the given checkpoint
|
|
314
329
|
* @returns The collection of blocks for the requested checkpoint if available (undefined otherwise)
|
|
315
330
|
*/
|
|
316
|
-
getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<
|
|
331
|
+
getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<L2Block[] | undefined>;
|
|
317
332
|
/**
|
|
318
333
|
* Returns checkpoint data for the requested checkpoint number
|
|
319
334
|
* @param checkpointNumber - The checkpoint requested
|
|
320
335
|
* @returns The checkpoint data or undefined if not found
|
|
321
336
|
*/
|
|
322
337
|
getCheckpointData(checkpointNumber: CheckpointNumber): Promise<CheckpointData | undefined>;
|
|
338
|
+
/** Returns checkpoint data for all checkpoints whose slot falls within the given range (inclusive). */
|
|
339
|
+
getCheckpointDataForSlotRange(startSlot: SlotNumber, endSlot: SlotNumber): Promise<CheckpointData[]>;
|
|
323
340
|
/**
|
|
324
341
|
* Gets all blocks that have the given slot number.
|
|
325
342
|
* @param slotNumber - The slot number to search for.
|
|
326
343
|
* @returns All blocks with the given slot number.
|
|
327
344
|
*/
|
|
328
|
-
getBlocksForSlot(slotNumber: SlotNumber): Promise<
|
|
345
|
+
getBlocksForSlot(slotNumber: SlotNumber): Promise<L2Block[]>;
|
|
329
346
|
/**
|
|
330
347
|
* Removes all blocks with block number > blockNumber.
|
|
348
|
+
* Does not remove any associated checkpoints.
|
|
331
349
|
* @param blockNumber - The block number to remove after.
|
|
332
350
|
* @returns The removed blocks (for event emission).
|
|
333
351
|
*/
|
|
334
|
-
removeBlocksAfter(blockNumber: BlockNumber): Promise<
|
|
352
|
+
removeBlocksAfter(blockNumber: BlockNumber): Promise<L2Block[]>;
|
|
335
353
|
}
|
|
336
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia3ZfYXJjaGl2ZXJfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9rdl9hcmNoaXZlcl9zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDakcsT0FBTyxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFHekQsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2pGLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3JELE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxtQkFBbUIsRUFBZSxVQUFVLEVBQUUsS0FBSyx3QkFBd0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2xILE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDcEUsT0FBTyxLQUFLLEVBQ1YsbUJBQW1CLEVBQ25CLGtCQUFrQixFQUNsQixpQ0FBaUMsRUFDakMsMkJBQTJCLEVBQzNCLDRDQUE0QyxFQUM1QyxrQ0FBa0MsRUFDbkMsTUFBTSx3QkFBd0IsQ0FBQztBQUNoQyxPQUFPLEtBQUssRUFBRSw0QkFBNEIsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzNHLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLGFBQWEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ25GLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JB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
|
|
354
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia3ZfYXJjaGl2ZXJfc3RvcmUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZS9rdl9hcmNoaXZlcl9zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDakcsT0FBTyxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFHekQsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2pGLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3JELE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2hFLE9BQU8sRUFDTCxLQUFLLFNBQVMsRUFDZCxTQUFTLEVBQ1QsbUJBQW1CLEVBQ25CLE9BQU8sRUFDUCxLQUFLLHdCQUF3QixFQUM5QixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3BGLE9BQU8sS0FBSyxFQUNWLG1CQUFtQixFQUNuQixrQkFBa0IsRUFDbEIsaUNBQWlDLEVBQ2pDLDJCQUEyQixFQUMzQiw0Q0FBNEMsRUFDNUMsa0NBQWtDLEVBQ25DLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNyRSxPQUFPLEtBQUssRUFBRSw0QkFBNEIsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzNHLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFF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
|