@aztec/archiver 0.0.1-commit.d3ec352c → 0.0.1-commit.fcb71a6
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/dest/archiver/archiver.d.ts +84 -70
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +439 -228
- package/dest/archiver/archiver_store.d.ts +95 -43
- package/dest/archiver/archiver_store.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.d.ts +1 -1
- package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.js +1847 -366
- package/dest/archiver/config.d.ts +5 -4
- package/dest/archiver/config.d.ts.map +1 -1
- package/dest/archiver/config.js +10 -3
- package/dest/archiver/errors.d.ts +25 -1
- package/dest/archiver/errors.d.ts.map +1 -1
- package/dest/archiver/errors.js +37 -0
- package/dest/archiver/index.d.ts +2 -2
- package/dest/archiver/index.d.ts.map +1 -1
- package/dest/archiver/instrumentation.d.ts +3 -1
- package/dest/archiver/instrumentation.d.ts.map +1 -1
- package/dest/archiver/instrumentation.js +11 -0
- package/dest/archiver/kv_archiver_store/block_store.d.ts +50 -18
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_store.js +320 -84
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +2 -2
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/contract_class_store.js +1 -1
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +2 -2
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +40 -51
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +65 -48
- package/dest/archiver/kv_archiver_store/log_store.d.ts +12 -16
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/log_store.js +148 -84
- package/dest/archiver/kv_archiver_store/message_store.d.ts +6 -5
- package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/message_store.js +15 -14
- package/dest/archiver/l1/bin/retrieve-calldata.d.ts +3 -0
- package/dest/archiver/l1/bin/retrieve-calldata.d.ts.map +1 -0
- package/dest/archiver/l1/bin/retrieve-calldata.js +149 -0
- package/dest/archiver/l1/calldata_retriever.d.ts +112 -0
- package/dest/archiver/l1/calldata_retriever.d.ts.map +1 -0
- package/dest/archiver/l1/calldata_retriever.js +471 -0
- package/dest/archiver/l1/data_retrieval.d.ts +90 -0
- package/dest/archiver/l1/data_retrieval.d.ts.map +1 -0
- package/dest/archiver/{data_retrieval.js → l1/data_retrieval.js} +50 -106
- package/dest/archiver/l1/debug_tx.d.ts +19 -0
- package/dest/archiver/l1/debug_tx.d.ts.map +1 -0
- package/dest/archiver/l1/debug_tx.js +73 -0
- package/dest/archiver/l1/spire_proposer.d.ts +70 -0
- package/dest/archiver/l1/spire_proposer.d.ts.map +1 -0
- package/dest/archiver/l1/spire_proposer.js +157 -0
- package/dest/archiver/l1/trace_tx.d.ts +97 -0
- package/dest/archiver/l1/trace_tx.d.ts.map +1 -0
- package/dest/archiver/l1/trace_tx.js +91 -0
- package/dest/archiver/l1/types.d.ts +12 -0
- package/dest/archiver/l1/types.d.ts.map +1 -0
- package/dest/archiver/l1/types.js +3 -0
- package/dest/archiver/l1/validate_trace.d.ts +29 -0
- package/dest/archiver/l1/validate_trace.d.ts.map +1 -0
- package/dest/archiver/l1/validate_trace.js +150 -0
- package/dest/archiver/structs/inbox_message.d.ts +4 -4
- package/dest/archiver/structs/inbox_message.d.ts.map +1 -1
- package/dest/archiver/structs/inbox_message.js +6 -6
- package/dest/archiver/structs/published.d.ts +1 -2
- package/dest/archiver/structs/published.d.ts.map +1 -1
- package/dest/factory.d.ts +1 -1
- package/dest/factory.js +1 -1
- package/dest/index.d.ts +2 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -1
- package/dest/test/mock_archiver.d.ts +4 -5
- package/dest/test/mock_archiver.d.ts.map +1 -1
- package/dest/test/mock_archiver.js +5 -9
- package/dest/test/mock_l1_to_l2_message_source.d.ts +5 -6
- package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
- package/dest/test/mock_l1_to_l2_message_source.js +7 -11
- package/dest/test/mock_l2_block_source.d.ts +11 -4
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +18 -17
- 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 +9 -9
- package/package.json +15 -14
- package/src/archiver/archiver.ts +567 -290
- package/src/archiver/archiver_store.ts +104 -42
- package/src/archiver/archiver_store_test_suite.ts +1895 -347
- package/src/archiver/config.ts +15 -10
- package/src/archiver/errors.ts +64 -0
- package/src/archiver/index.ts +1 -1
- package/src/archiver/instrumentation.ts +14 -0
- package/src/archiver/kv_archiver_store/block_store.ts +435 -95
- package/src/archiver/kv_archiver_store/contract_class_store.ts +1 -1
- package/src/archiver/kv_archiver_store/contract_instance_store.ts +1 -1
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +81 -66
- package/src/archiver/kv_archiver_store/log_store.ts +208 -99
- package/src/archiver/kv_archiver_store/message_store.ts +21 -18
- package/src/archiver/l1/README.md +98 -0
- package/src/archiver/l1/bin/retrieve-calldata.ts +182 -0
- package/src/archiver/l1/calldata_retriever.ts +641 -0
- package/src/archiver/{data_retrieval.ts → l1/data_retrieval.ts} +96 -161
- package/src/archiver/l1/debug_tx.ts +99 -0
- package/src/archiver/l1/spire_proposer.ts +160 -0
- package/src/archiver/l1/trace_tx.ts +128 -0
- package/src/archiver/l1/types.ts +13 -0
- package/src/archiver/l1/validate_trace.ts +211 -0
- package/src/archiver/structs/inbox_message.ts +7 -8
- package/src/archiver/structs/published.ts +0 -1
- package/src/factory.ts +1 -1
- package/src/index.ts +1 -1
- package/src/test/fixtures/debug_traceTransaction-multicall3.json +88 -0
- package/src/test/fixtures/debug_traceTransaction-multiplePropose.json +153 -0
- package/src/test/fixtures/debug_traceTransaction-proxied.json +122 -0
- package/src/test/fixtures/trace_transaction-multicall3.json +65 -0
- package/src/test/fixtures/trace_transaction-multiplePropose.json +319 -0
- package/src/test/fixtures/trace_transaction-proxied.json +128 -0
- package/src/test/fixtures/trace_transaction-randomRevert.json +216 -0
- package/src/test/mock_archiver.ts +6 -11
- package/src/test/mock_l1_to_l2_message_source.ts +6 -11
- package/src/test/mock_l2_block_source.ts +22 -18
- package/src/test/mock_structs.ts +10 -10
- package/dest/archiver/data_retrieval.d.ts +0 -80
- package/dest/archiver/data_retrieval.d.ts.map +0 -1
package/src/archiver/archiver.ts
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BlobClientInterface } from '@aztec/blob-client/client';
|
|
2
2
|
import { GENESIS_BLOCK_HEADER_HASH } from '@aztec/constants';
|
|
3
3
|
import { EpochCache } from '@aztec/epoch-cache';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type ViemPublicClient,
|
|
10
|
-
createEthereumChain,
|
|
11
|
-
} from '@aztec/ethereum';
|
|
4
|
+
import { createEthereumChain } from '@aztec/ethereum/chain';
|
|
5
|
+
import { BlockTagTooOldError, InboxContract, RollupContract } from '@aztec/ethereum/contracts';
|
|
6
|
+
import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
7
|
+
import type { L1BlockId } from '@aztec/ethereum/l1-types';
|
|
8
|
+
import type { ViemPublicClient, ViemPublicDebugClient } from '@aztec/ethereum/types';
|
|
12
9
|
import { maxBigint } from '@aztec/foundation/bigint';
|
|
13
10
|
import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
14
11
|
import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
|
|
15
12
|
import { merge, pick } from '@aztec/foundation/collection';
|
|
13
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
16
14
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
17
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
18
15
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
19
16
|
import { type PromiseWithResolvers, promiseWithResolvers } from '@aztec/foundation/promise';
|
|
20
17
|
import { RunningPromise, makeLoggingErrorHandler } from '@aztec/foundation/running-promise';
|
|
21
18
|
import { count } from '@aztec/foundation/string';
|
|
22
19
|
import { DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
|
|
20
|
+
import { isDefined } from '@aztec/foundation/types';
|
|
23
21
|
import type { CustomRange } from '@aztec/kv-store';
|
|
24
22
|
import { RollupAbi } from '@aztec/l1-artifacts';
|
|
25
23
|
import {
|
|
@@ -35,13 +33,17 @@ import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
|
35
33
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
36
34
|
import {
|
|
37
35
|
type ArchiverEmitter,
|
|
36
|
+
CheckpointedL2Block,
|
|
37
|
+
CommitteeAttestation,
|
|
38
38
|
L2Block,
|
|
39
|
+
L2BlockNew,
|
|
40
|
+
type L2BlockSink,
|
|
39
41
|
type L2BlockSource,
|
|
40
42
|
L2BlockSourceEvents,
|
|
41
43
|
type L2Tips,
|
|
42
44
|
PublishedL2Block,
|
|
43
45
|
} from '@aztec/stdlib/block';
|
|
44
|
-
import
|
|
46
|
+
import { Checkpoint, PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
45
47
|
import {
|
|
46
48
|
type ContractClassPublic,
|
|
47
49
|
type ContractDataSource,
|
|
@@ -62,8 +64,16 @@ import {
|
|
|
62
64
|
} from '@aztec/stdlib/epoch-helpers';
|
|
63
65
|
import type { GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
|
|
64
66
|
import type { L2LogsSource } from '@aztec/stdlib/interfaces/server';
|
|
65
|
-
import {
|
|
66
|
-
|
|
67
|
+
import {
|
|
68
|
+
ContractClassLog,
|
|
69
|
+
type LogFilter,
|
|
70
|
+
type PrivateLog,
|
|
71
|
+
type PublicLog,
|
|
72
|
+
type SiloedTag,
|
|
73
|
+
Tag,
|
|
74
|
+
TxScopedL2Log,
|
|
75
|
+
} from '@aztec/stdlib/logs';
|
|
76
|
+
import { type L1ToL2MessageSource, computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
|
|
67
77
|
import type { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
68
78
|
import { type BlockHeader, type IndexedTxEffect, TxHash, TxReceipt } from '@aztec/stdlib/tx';
|
|
69
79
|
import type { UInt64 } from '@aztec/stdlib/types';
|
|
@@ -81,14 +91,16 @@ import { type GetContractReturnType, type Hex, createPublicClient, fallback, htt
|
|
|
81
91
|
|
|
82
92
|
import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.js';
|
|
83
93
|
import type { ArchiverConfig } from './config.js';
|
|
94
|
+
import { InitialCheckpointNumberNotSequentialError, NoBlobBodiesFoundError } from './errors.js';
|
|
95
|
+
import { ArchiverInstrumentation } from './instrumentation.js';
|
|
96
|
+
import type { CheckpointData } from './kv_archiver_store/block_store.js';
|
|
84
97
|
import {
|
|
85
98
|
retrieveCheckpointsFromRollup,
|
|
86
99
|
retrieveL1ToL2Message,
|
|
87
100
|
retrieveL1ToL2Messages,
|
|
88
101
|
retrievedToPublishedCheckpoint,
|
|
89
|
-
} from './data_retrieval.js';
|
|
90
|
-
import {
|
|
91
|
-
import { ArchiverInstrumentation } from './instrumentation.js';
|
|
102
|
+
} from './l1/data_retrieval.js';
|
|
103
|
+
import { validateAndLogTraceAvailability } from './l1/validate_trace.js';
|
|
92
104
|
import type { InboxMessage } from './structs/inbox_message.js';
|
|
93
105
|
import { type ValidateBlockResult, validateCheckpointAttestations } from './validation.js';
|
|
94
106
|
|
|
@@ -97,9 +109,16 @@ import { type ValidateBlockResult, validateCheckpointAttestations } from './vali
|
|
|
97
109
|
*/
|
|
98
110
|
export type ArchiveSource = L2BlockSource & L2LogsSource & ContractDataSource & L1ToL2MessageSource;
|
|
99
111
|
|
|
112
|
+
/** Request to add a block to the archiver, queued for processing by the sync loop. */
|
|
113
|
+
type AddBlockRequest = {
|
|
114
|
+
block: L2BlockNew;
|
|
115
|
+
resolve: () => void;
|
|
116
|
+
reject: (err: Error) => void;
|
|
117
|
+
};
|
|
118
|
+
|
|
100
119
|
export type ArchiverDeps = {
|
|
101
120
|
telemetry?: TelemetryClient;
|
|
102
|
-
|
|
121
|
+
blobClient: BlobClientInterface;
|
|
103
122
|
epochCache?: EpochCache;
|
|
104
123
|
dateProvider?: DateProvider;
|
|
105
124
|
};
|
|
@@ -110,6 +129,7 @@ function mapArchiverConfig(config: Partial<ArchiverConfig>) {
|
|
|
110
129
|
batchSize: config.archiverBatchSize,
|
|
111
130
|
skipValidateBlockAttestations: config.skipValidateBlockAttestations,
|
|
112
131
|
maxAllowedEthClientDriftSeconds: config.maxAllowedEthClientDriftSeconds,
|
|
132
|
+
ethereumAllowNoDebugHosts: config.ethereumAllowNoDebugHosts,
|
|
113
133
|
};
|
|
114
134
|
}
|
|
115
135
|
|
|
@@ -128,7 +148,10 @@ type RollupStatus = {
|
|
|
128
148
|
* Responsible for handling robust L1 polling so that other components do not need to
|
|
129
149
|
* concern themselves with it.
|
|
130
150
|
*/
|
|
131
|
-
export class Archiver
|
|
151
|
+
export class Archiver
|
|
152
|
+
extends (EventEmitter as new () => ArchiverEmitter)
|
|
153
|
+
implements ArchiveSource, L2BlockSink, Traceable
|
|
154
|
+
{
|
|
132
155
|
/** A loop in which we will be continually fetching new checkpoints. */
|
|
133
156
|
private runningPromise: RunningPromise;
|
|
134
157
|
|
|
@@ -142,11 +165,15 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
142
165
|
private initialSyncComplete: boolean = false;
|
|
143
166
|
private initialSyncPromise: PromiseWithResolvers<void>;
|
|
144
167
|
|
|
168
|
+
/** Queue of blocks to be added to the store, processed by the sync loop. */
|
|
169
|
+
private blockQueue: AddBlockRequest[] = [];
|
|
170
|
+
|
|
145
171
|
public readonly tracer: Tracer;
|
|
146
172
|
|
|
147
173
|
/**
|
|
148
174
|
* Creates a new instance of the Archiver.
|
|
149
175
|
* @param publicClient - A client for interacting with the Ethereum node.
|
|
176
|
+
* @param debugClient - A client for interacting with the Ethereum node for debug/trace methods.
|
|
150
177
|
* @param rollupAddress - Ethereum address of the rollup contract.
|
|
151
178
|
* @param inboxAddress - Ethereum address of the inbox contract.
|
|
152
179
|
* @param registryAddress - Ethereum address of the registry contract.
|
|
@@ -156,15 +183,20 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
156
183
|
*/
|
|
157
184
|
constructor(
|
|
158
185
|
private readonly publicClient: ViemPublicClient,
|
|
159
|
-
private readonly
|
|
186
|
+
private readonly debugClient: ViemPublicDebugClient,
|
|
187
|
+
private readonly l1Addresses: Pick<
|
|
188
|
+
L1ContractAddresses,
|
|
189
|
+
'rollupAddress' | 'inboxAddress' | 'registryAddress' | 'governanceProposerAddress' | 'slashFactoryAddress'
|
|
190
|
+
> & { slashingProposerAddress: EthAddress },
|
|
160
191
|
readonly dataStore: ArchiverDataStore,
|
|
161
192
|
private config: {
|
|
162
193
|
pollingIntervalMs: number;
|
|
163
194
|
batchSize: number;
|
|
164
195
|
skipValidateBlockAttestations?: boolean;
|
|
165
196
|
maxAllowedEthClientDriftSeconds: number;
|
|
197
|
+
ethereumAllowNoDebugHosts?: boolean;
|
|
166
198
|
},
|
|
167
|
-
private readonly
|
|
199
|
+
private readonly blobClient: BlobClientInterface,
|
|
168
200
|
private readonly epochCache: EpochCache,
|
|
169
201
|
private readonly dateProvider: DateProvider,
|
|
170
202
|
private readonly instrumentation: ArchiverInstrumentation,
|
|
@@ -206,18 +238,28 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
206
238
|
const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
|
|
207
239
|
const publicClient = createPublicClient({
|
|
208
240
|
chain: chain.chainInfo,
|
|
209
|
-
transport: fallback(config.l1RpcUrls.map(url => http(url))),
|
|
241
|
+
transport: fallback(config.l1RpcUrls.map(url => http(url, { batch: false }))),
|
|
210
242
|
pollingInterval: config.viemPollingIntervalMS,
|
|
211
243
|
});
|
|
212
244
|
|
|
245
|
+
// Create debug client using debug RPC URLs if available, otherwise fall back to regular RPC URLs
|
|
246
|
+
const debugRpcUrls = config.l1DebugRpcUrls.length > 0 ? config.l1DebugRpcUrls : config.l1RpcUrls;
|
|
247
|
+
const debugClient = createPublicClient({
|
|
248
|
+
chain: chain.chainInfo,
|
|
249
|
+
transport: fallback(debugRpcUrls.map(url => http(url, { batch: false }))),
|
|
250
|
+
pollingInterval: config.viemPollingIntervalMS,
|
|
251
|
+
}) as ViemPublicDebugClient;
|
|
252
|
+
|
|
213
253
|
const rollup = new RollupContract(publicClient, config.l1Contracts.rollupAddress);
|
|
214
254
|
|
|
215
|
-
const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, genesisArchiveRoot] =
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
255
|
+
const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, genesisArchiveRoot, slashingProposerAddress] =
|
|
256
|
+
await Promise.all([
|
|
257
|
+
rollup.getL1StartBlock(),
|
|
258
|
+
rollup.getL1GenesisTime(),
|
|
259
|
+
rollup.getProofSubmissionEpochs(),
|
|
260
|
+
rollup.getGenesisArchiveTreeRoot(),
|
|
261
|
+
rollup.getSlashingProposerAddress(),
|
|
262
|
+
] as const);
|
|
221
263
|
|
|
222
264
|
const l1StartBlockHash = await publicClient
|
|
223
265
|
.getBlock({ blockNumber: l1StartBlock, includeTransactions: false })
|
|
@@ -237,7 +279,12 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
237
279
|
};
|
|
238
280
|
|
|
239
281
|
const opts = merge(
|
|
240
|
-
{
|
|
282
|
+
{
|
|
283
|
+
pollingIntervalMs: 10_000,
|
|
284
|
+
batchSize: 100,
|
|
285
|
+
maxAllowedEthClientDriftSeconds: 300,
|
|
286
|
+
ethereumAllowNoDebugHosts: false,
|
|
287
|
+
},
|
|
241
288
|
mapArchiverConfig(config),
|
|
242
289
|
);
|
|
243
290
|
|
|
@@ -246,10 +293,11 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
246
293
|
|
|
247
294
|
const archiver = new Archiver(
|
|
248
295
|
publicClient,
|
|
249
|
-
|
|
296
|
+
debugClient,
|
|
297
|
+
{ ...config.l1Contracts, slashingProposerAddress },
|
|
250
298
|
archiverStore,
|
|
251
299
|
opts,
|
|
252
|
-
deps.
|
|
300
|
+
deps.blobClient,
|
|
253
301
|
epochCache,
|
|
254
302
|
deps.dateProvider ?? new DateProvider(),
|
|
255
303
|
await ArchiverInstrumentation.new(telemetry, () => archiverStore.estimateSize()),
|
|
@@ -273,16 +321,17 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
273
321
|
throw new Error('Archiver is already running');
|
|
274
322
|
}
|
|
275
323
|
|
|
276
|
-
await this.
|
|
324
|
+
await this.blobClient.testSources();
|
|
277
325
|
await this.testEthereumNodeSynced();
|
|
326
|
+
await validateAndLogTraceAvailability(this.debugClient, this.config.ethereumAllowNoDebugHosts ?? false);
|
|
278
327
|
|
|
279
328
|
// Log initial state for the archiver
|
|
280
329
|
const { l1StartBlock } = this.l1constants;
|
|
281
330
|
const { blocksSynchedTo = l1StartBlock, messagesSynchedTo = l1StartBlock } = await this.store.getSynchPoint();
|
|
282
|
-
const
|
|
331
|
+
const currentL2Checkpoint = await this.getSynchedCheckpointNumber();
|
|
283
332
|
this.log.info(
|
|
284
|
-
`Starting archiver sync to rollup contract ${this.l1Addresses.rollupAddress.toString()} from L1 block ${blocksSynchedTo} and L2
|
|
285
|
-
{ blocksSynchedTo, messagesSynchedTo,
|
|
333
|
+
`Starting archiver sync to rollup contract ${this.l1Addresses.rollupAddress.toString()} from L1 block ${blocksSynchedTo} and L2 checkpoint ${currentL2Checkpoint}`,
|
|
334
|
+
{ blocksSynchedTo, messagesSynchedTo, currentL2Checkpoint },
|
|
286
335
|
);
|
|
287
336
|
|
|
288
337
|
// Start sync loop, and return the wait for initial sync if we are asked to block until synced
|
|
@@ -296,6 +345,51 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
296
345
|
return this.runningPromise.trigger();
|
|
297
346
|
}
|
|
298
347
|
|
|
348
|
+
/**
|
|
349
|
+
* Queues a block to be added to the archiver store and triggers processing.
|
|
350
|
+
* The block will be processed by the sync loop.
|
|
351
|
+
* Implements the L2BlockSink interface.
|
|
352
|
+
* @param block - The L2 block to add.
|
|
353
|
+
* @returns A promise that resolves when the block has been added to the store, or rejects on error.
|
|
354
|
+
*/
|
|
355
|
+
public addBlock(block: L2BlockNew): Promise<void> {
|
|
356
|
+
return new Promise<void>((resolve, reject) => {
|
|
357
|
+
this.blockQueue.push({ block, resolve, reject });
|
|
358
|
+
this.log.debug(`Queued block ${block.number} for processing`);
|
|
359
|
+
// Trigger an immediate sync, but don't wait for it - the promise resolves when the block is processed
|
|
360
|
+
this.syncImmediate().catch(err => {
|
|
361
|
+
this.log.error(`Sync immediate call failed: ${err}`);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Processes all queued blocks, adding them to the store.
|
|
368
|
+
* Called at the beginning of each sync iteration.
|
|
369
|
+
* Blocks are processed in the order they were queued.
|
|
370
|
+
*/
|
|
371
|
+
private async processQueuedBlocks(): Promise<void> {
|
|
372
|
+
if (this.blockQueue.length === 0) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Take all blocks from the queue
|
|
377
|
+
const queuedItems = this.blockQueue.splice(0, this.blockQueue.length);
|
|
378
|
+
this.log.debug(`Processing ${queuedItems.length} queued block(s)`);
|
|
379
|
+
|
|
380
|
+
// Process each block individually to properly resolve/reject each promise
|
|
381
|
+
for (const { block, resolve, reject } of queuedItems) {
|
|
382
|
+
try {
|
|
383
|
+
await this.store.addBlocks([block]);
|
|
384
|
+
this.log.debug(`Added block ${block.number} to store`);
|
|
385
|
+
resolve();
|
|
386
|
+
} catch (err: any) {
|
|
387
|
+
this.log.error(`Failed to add block ${block.number} to store: ${err.message}`);
|
|
388
|
+
reject(err);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
299
393
|
public waitForInitialSync() {
|
|
300
394
|
return this.initialSyncPromise.promise;
|
|
301
395
|
}
|
|
@@ -315,11 +409,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
315
409
|
}
|
|
316
410
|
}
|
|
317
411
|
|
|
318
|
-
|
|
319
|
-
* Fetches logs from L1 contracts and processes them.
|
|
320
|
-
*/
|
|
321
|
-
@trackSpan('Archiver.sync')
|
|
322
|
-
private async sync() {
|
|
412
|
+
private async syncFromL1() {
|
|
323
413
|
/**
|
|
324
414
|
* We keep track of three "pointers" to L1 blocks:
|
|
325
415
|
* 1. the last L1 block that published an L2 block
|
|
@@ -405,7 +495,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
405
495
|
// past it, since otherwise we'll keep downloading it and reprocessing it on every iteration until
|
|
406
496
|
// we get a valid checkpoint to advance the syncpoint.
|
|
407
497
|
if (!rollupStatus.validationResult?.valid && rollupStatus.lastL1BlockWithCheckpoint !== undefined) {
|
|
408
|
-
await this.store.
|
|
498
|
+
await this.store.setCheckpointSynchedL1BlockNumber(rollupStatus.lastL1BlockWithCheckpoint);
|
|
409
499
|
}
|
|
410
500
|
|
|
411
501
|
// And lastly we check if we are missing any checkpoints behind us due to a possible L1 reorg.
|
|
@@ -439,6 +529,17 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
439
529
|
}
|
|
440
530
|
}
|
|
441
531
|
|
|
532
|
+
/**
|
|
533
|
+
* Fetches logs from L1 contracts and processes them.
|
|
534
|
+
*/
|
|
535
|
+
@trackSpan('Archiver.sync')
|
|
536
|
+
private async sync() {
|
|
537
|
+
// Process any queued blocks first, before doing L1 sync
|
|
538
|
+
await this.processQueuedBlocks();
|
|
539
|
+
// Now perform L1 sync
|
|
540
|
+
await this.syncFromL1();
|
|
541
|
+
}
|
|
542
|
+
|
|
442
543
|
/** Queries the rollup contract on whether a prune can be executed on the immediate next L1 block. */
|
|
443
544
|
private async canPrune(currentL1BlockNumber: bigint, currentL1Timestamp: bigint) {
|
|
444
545
|
const time = (currentL1Timestamp ?? 0n) + BigInt(this.l1constants.ethereumSlotDuration);
|
|
@@ -477,13 +578,26 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
477
578
|
|
|
478
579
|
const checkpointsToUnwind = localPendingCheckpointNumber - provenCheckpointNumber;
|
|
479
580
|
|
|
480
|
-
const
|
|
581
|
+
const checkpointPromises = Array.from({ length: checkpointsToUnwind })
|
|
582
|
+
.fill(0)
|
|
583
|
+
.map((_, i) => this.store.getCheckpointData(CheckpointNumber(i + pruneFrom)));
|
|
584
|
+
const checkpoints = await Promise.all(checkpointPromises);
|
|
585
|
+
|
|
586
|
+
const blockPromises = await Promise.all(
|
|
587
|
+
checkpoints
|
|
588
|
+
.filter(isDefined)
|
|
589
|
+
.map(cp => this.store.getBlocksForCheckpoint(CheckpointNumber(cp.checkpointNumber))),
|
|
590
|
+
);
|
|
591
|
+
const newBlocks = blockPromises.filter(isDefined).flat();
|
|
592
|
+
|
|
593
|
+
// TODO(pw/mbps): Don't convert to legacy blocks here
|
|
594
|
+
const blocks: L2Block[] = (await Promise.all(newBlocks.map(x => this.getBlock(x.number)))).filter(isDefined);
|
|
481
595
|
|
|
482
596
|
// Emit an event for listening services to react to the chain prune
|
|
483
597
|
this.emit(L2BlockSourceEvents.L2PruneDetected, {
|
|
484
598
|
type: L2BlockSourceEvents.L2PruneDetected,
|
|
485
599
|
epochNumber: pruneFromEpochNumber,
|
|
486
|
-
blocks
|
|
600
|
+
blocks,
|
|
487
601
|
});
|
|
488
602
|
|
|
489
603
|
this.log.debug(
|
|
@@ -594,7 +708,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
594
708
|
// Log stats for messages retrieved (if any).
|
|
595
709
|
if (messageCount > 0) {
|
|
596
710
|
this.log.info(
|
|
597
|
-
`Retrieved ${messageCount} new L1 to L2 messages up to message with index ${lastMessage?.index} for
|
|
711
|
+
`Retrieved ${messageCount} new L1 to L2 messages up to message with index ${lastMessage?.index} for checkpoint ${lastMessage?.checkpointNumber}`,
|
|
598
712
|
{ lastMessage, messageCount },
|
|
599
713
|
);
|
|
600
714
|
}
|
|
@@ -711,17 +825,18 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
711
825
|
}
|
|
712
826
|
}
|
|
713
827
|
|
|
714
|
-
const localCheckpointForDestinationProvenCheckpointNumber =
|
|
828
|
+
const localCheckpointForDestinationProvenCheckpointNumber =
|
|
829
|
+
await this.store.getCheckpointData(provenCheckpointNumber);
|
|
715
830
|
|
|
716
831
|
// Sanity check. I've hit what seems to be a state where the proven checkpoint is set to a value greater than the latest
|
|
717
832
|
// synched checkpoint when requesting L2Tips from the archiver. This is the only place where the proven checkpoint is set.
|
|
718
833
|
const synched = await this.getSynchedCheckpointNumber();
|
|
719
834
|
if (
|
|
720
835
|
localCheckpointForDestinationProvenCheckpointNumber &&
|
|
721
|
-
synched < localCheckpointForDestinationProvenCheckpointNumber.
|
|
836
|
+
synched < localCheckpointForDestinationProvenCheckpointNumber.checkpointNumber
|
|
722
837
|
) {
|
|
723
838
|
this.log.error(
|
|
724
|
-
`Hit local checkpoint greater than last synched checkpoint: ${localCheckpointForDestinationProvenCheckpointNumber.
|
|
839
|
+
`Hit local checkpoint greater than last synched checkpoint: ${localCheckpointForDestinationProvenCheckpointNumber.checkpointNumber} > ${synched}`,
|
|
725
840
|
);
|
|
726
841
|
}
|
|
727
842
|
|
|
@@ -731,7 +846,6 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
731
846
|
}`,
|
|
732
847
|
);
|
|
733
848
|
|
|
734
|
-
const lastProvenBlockNumber = await this.getLastBlockNumberInCheckpoint(provenCheckpointNumber);
|
|
735
849
|
if (
|
|
736
850
|
localCheckpointForDestinationProvenCheckpointNumber &&
|
|
737
851
|
provenArchive === localCheckpointForDestinationProvenCheckpointNumber.archive.root.toString()
|
|
@@ -744,25 +858,29 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
744
858
|
});
|
|
745
859
|
const provenSlotNumber = localCheckpointForDestinationProvenCheckpointNumber.header.slotNumber;
|
|
746
860
|
const provenEpochNumber: EpochNumber = getEpochAtSlot(provenSlotNumber, this.l1constants);
|
|
861
|
+
const lastBlockNumberInCheckpoint =
|
|
862
|
+
localCheckpointForDestinationProvenCheckpointNumber.startBlock +
|
|
863
|
+
localCheckpointForDestinationProvenCheckpointNumber.numBlocks -
|
|
864
|
+
1;
|
|
747
865
|
|
|
748
866
|
this.emit(L2BlockSourceEvents.L2BlockProven, {
|
|
749
867
|
type: L2BlockSourceEvents.L2BlockProven,
|
|
750
|
-
blockNumber:
|
|
868
|
+
blockNumber: BlockNumber(lastBlockNumberInCheckpoint),
|
|
751
869
|
slotNumber: provenSlotNumber,
|
|
752
870
|
epochNumber: provenEpochNumber,
|
|
753
871
|
});
|
|
872
|
+
this.instrumentation.updateLastProvenBlock(lastBlockNumberInCheckpoint);
|
|
754
873
|
} else {
|
|
755
874
|
this.log.trace(`Proven checkpoint ${provenCheckpointNumber} already stored.`);
|
|
756
875
|
}
|
|
757
876
|
}
|
|
758
|
-
this.instrumentation.updateLastProvenBlock(lastProvenBlockNumber);
|
|
759
877
|
};
|
|
760
878
|
|
|
761
879
|
// This is an edge case that we only hit if there are no proposed checkpoints.
|
|
762
880
|
// If we have 0 checkpoints locally and there are no checkpoints onchain there is nothing to do.
|
|
763
881
|
const noCheckpoints = localPendingCheckpointNumber === 0 && pendingCheckpointNumber === 0;
|
|
764
882
|
if (noCheckpoints) {
|
|
765
|
-
await this.store.
|
|
883
|
+
await this.store.setCheckpointSynchedL1BlockNumber(currentL1BlockNumber);
|
|
766
884
|
this.log.debug(
|
|
767
885
|
`No checkpoints to retrieve from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}, no checkpoints on chain`,
|
|
768
886
|
);
|
|
@@ -774,7 +892,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
774
892
|
// Related to the L2 reorgs of the pending chain. We are only interested in actually addressing a reorg if there
|
|
775
893
|
// are any state that could be impacted by it. If we have no checkpoints, there is no impact.
|
|
776
894
|
if (localPendingCheckpointNumber > 0) {
|
|
777
|
-
const localPendingCheckpoint = await this.
|
|
895
|
+
const localPendingCheckpoint = await this.store.getCheckpointData(localPendingCheckpointNumber);
|
|
778
896
|
if (localPendingCheckpoint === undefined) {
|
|
779
897
|
throw new Error(`Missing checkpoint ${localPendingCheckpointNumber}`);
|
|
780
898
|
}
|
|
@@ -807,14 +925,14 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
807
925
|
|
|
808
926
|
let tipAfterUnwind = localPendingCheckpointNumber;
|
|
809
927
|
while (true) {
|
|
810
|
-
const candidateCheckpoint = await this.
|
|
928
|
+
const candidateCheckpoint = await this.store.getCheckpointData(tipAfterUnwind);
|
|
811
929
|
if (candidateCheckpoint === undefined) {
|
|
812
930
|
break;
|
|
813
931
|
}
|
|
814
932
|
|
|
815
|
-
const archiveAtContract = await this.rollup.archiveAt(candidateCheckpoint.
|
|
933
|
+
const archiveAtContract = await this.rollup.archiveAt(candidateCheckpoint.checkpointNumber);
|
|
816
934
|
this.log.trace(
|
|
817
|
-
`Checking local checkpoint ${candidateCheckpoint.
|
|
935
|
+
`Checking local checkpoint ${candidateCheckpoint.checkpointNumber} with archive ${candidateCheckpoint.archive.root}`,
|
|
818
936
|
{
|
|
819
937
|
archiveAtContract,
|
|
820
938
|
archiveLocal: candidateCheckpoint.archive.root.toString(),
|
|
@@ -849,14 +967,18 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
849
967
|
|
|
850
968
|
this.log.trace(`Retrieving checkpoints from L1 block ${searchStartBlock} to ${searchEndBlock}`);
|
|
851
969
|
|
|
852
|
-
// TODO(md): Retrieve from blob
|
|
970
|
+
// TODO(md): Retrieve from blob client then from consensus client, then from peers
|
|
853
971
|
const retrievedCheckpoints = await retrieveCheckpointsFromRollup(
|
|
854
972
|
this.rollup.getContract() as GetContractReturnType<typeof RollupAbi, ViemPublicClient>,
|
|
855
973
|
this.publicClient,
|
|
856
|
-
this.
|
|
974
|
+
this.debugClient,
|
|
975
|
+
this.blobClient,
|
|
857
976
|
searchStartBlock, // TODO(palla/reorg): If the L2 reorg was due to an L1 reorg, we need to start search earlier
|
|
858
977
|
searchEndBlock,
|
|
978
|
+
this.l1Addresses,
|
|
979
|
+
this.instrumentation,
|
|
859
980
|
this.log,
|
|
981
|
+
!this.initialSyncComplete, // isHistoricalSync
|
|
860
982
|
);
|
|
861
983
|
|
|
862
984
|
if (retrievedCheckpoints.length === 0) {
|
|
@@ -916,6 +1038,25 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
916
1038
|
continue;
|
|
917
1039
|
}
|
|
918
1040
|
|
|
1041
|
+
// Check the inHash of the checkpoint against the l1->l2 messages.
|
|
1042
|
+
// The messages should've been synced up to the currentL1BlockNumber and must be available for the published
|
|
1043
|
+
// checkpoints we just retrieved.
|
|
1044
|
+
const l1ToL2Messages = await this.getL1ToL2Messages(published.checkpoint.number);
|
|
1045
|
+
const computedInHash = computeInHashFromL1ToL2Messages(l1ToL2Messages);
|
|
1046
|
+
const publishedInHash = published.checkpoint.header.contentCommitment.inHash;
|
|
1047
|
+
if (!computedInHash.equals(publishedInHash)) {
|
|
1048
|
+
this.log.fatal(`Mismatch inHash for checkpoint ${published.checkpoint.number}`, {
|
|
1049
|
+
checkpointHash: published.checkpoint.hash(),
|
|
1050
|
+
l1BlockNumber: published.l1.blockNumber,
|
|
1051
|
+
computedInHash,
|
|
1052
|
+
publishedInHash,
|
|
1053
|
+
});
|
|
1054
|
+
// Throwing an error since this is most likely caused by a bug.
|
|
1055
|
+
throw new Error(
|
|
1056
|
+
`Mismatch inHash for checkpoint ${published.checkpoint.number}. Expected ${computedInHash} but got ${publishedInHash}`,
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
919
1060
|
validCheckpoints.push(published);
|
|
920
1061
|
this.log.debug(
|
|
921
1062
|
`Ingesting new checkpoint ${published.checkpoint.number} with ${published.checkpoint.blocks.length} blocks`,
|
|
@@ -937,19 +1078,18 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
937
1078
|
validCheckpoints.flatMap(c => c.checkpoint.blocks),
|
|
938
1079
|
);
|
|
939
1080
|
} catch (err) {
|
|
940
|
-
if (err instanceof
|
|
941
|
-
const {
|
|
942
|
-
const
|
|
943
|
-
? await this.store.
|
|
1081
|
+
if (err instanceof InitialCheckpointNumberNotSequentialError) {
|
|
1082
|
+
const { previousCheckpointNumber, newCheckpointNumber } = err;
|
|
1083
|
+
const previousCheckpoint = previousCheckpointNumber
|
|
1084
|
+
? await this.store.getCheckpointData(CheckpointNumber(previousCheckpointNumber))
|
|
944
1085
|
: undefined;
|
|
945
|
-
const updatedL1SyncPoint =
|
|
1086
|
+
const updatedL1SyncPoint = previousCheckpoint?.l1.blockNumber ?? this.l1constants.l1StartBlock;
|
|
946
1087
|
await this.store.setBlockSynchedL1BlockNumber(updatedL1SyncPoint);
|
|
947
1088
|
this.log.warn(
|
|
948
|
-
`Attempting to insert
|
|
1089
|
+
`Attempting to insert checkpoint ${newCheckpointNumber} with previous block ${previousCheckpointNumber}. Rolling back L1 sync point to ${updatedL1SyncPoint} to try and fetch the missing blocks.`,
|
|
949
1090
|
{
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
newBlockNumber,
|
|
1091
|
+
previousCheckpointNumber,
|
|
1092
|
+
newCheckpointNumber,
|
|
953
1093
|
updatedL1SyncPoint,
|
|
954
1094
|
},
|
|
955
1095
|
);
|
|
@@ -969,7 +1109,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
969
1109
|
});
|
|
970
1110
|
}
|
|
971
1111
|
lastRetrievedCheckpoint = validCheckpoints.at(-1) ?? lastRetrievedCheckpoint;
|
|
972
|
-
lastL1BlockWithCheckpoint =
|
|
1112
|
+
lastL1BlockWithCheckpoint = retrievedCheckpoints.at(-1)?.l1.blockNumber ?? lastL1BlockWithCheckpoint;
|
|
973
1113
|
} while (searchEndBlock < currentL1BlockNumber);
|
|
974
1114
|
|
|
975
1115
|
// Important that we update AFTER inserting the blocks.
|
|
@@ -994,13 +1134,16 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
994
1134
|
// We suspect an L1 reorg that added checkpoints *behind* us. If that is the case, it must have happened between
|
|
995
1135
|
// the last checkpoint we saw and the current one, so we reset the last synched L1 block number. In the edge case
|
|
996
1136
|
// we don't have one, we go back 2 L1 epochs, which is the deepest possible reorg (assuming Casper is working).
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1137
|
+
let latestLocalCheckpointArchive: string | undefined = undefined;
|
|
1138
|
+
let targetL1BlockNumber = maxBigint(currentL1BlockNumber - 64n, 0n);
|
|
1139
|
+
if (lastRetrievedCheckpoint) {
|
|
1140
|
+
latestLocalCheckpointArchive = lastRetrievedCheckpoint.checkpoint.archive.root.toString();
|
|
1141
|
+
targetL1BlockNumber = lastRetrievedCheckpoint.l1.blockNumber;
|
|
1142
|
+
} else if (latestLocalCheckpointNumber > 0) {
|
|
1143
|
+
const checkpoint = await this.store.getRangeOfCheckpoints(latestLocalCheckpointNumber, 1).then(([c]) => c);
|
|
1144
|
+
latestLocalCheckpointArchive = checkpoint.archive.root.toString();
|
|
1145
|
+
targetL1BlockNumber = checkpoint.l1.blockNumber;
|
|
1146
|
+
}
|
|
1004
1147
|
this.log.warn(
|
|
1005
1148
|
`Failed to reach checkpoint ${pendingCheckpointNumber} at ${currentL1BlockNumber} (latest is ${latestLocalCheckpointNumber}). ` +
|
|
1006
1149
|
`Rolling back last synched L1 block number to ${targetL1BlockNumber}.`,
|
|
@@ -1086,15 +1229,22 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1086
1229
|
const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1constants);
|
|
1087
1230
|
const blocks: L2Block[] = [];
|
|
1088
1231
|
|
|
1089
|
-
// Walk the list of
|
|
1090
|
-
// We'll typically ask for
|
|
1091
|
-
let
|
|
1092
|
-
const slot = (b:
|
|
1093
|
-
while (
|
|
1094
|
-
if (slot(
|
|
1095
|
-
blocks
|
|
1232
|
+
// Walk the list of checkpoints backwards and filter by slots matching the requested epoch.
|
|
1233
|
+
// We'll typically ask for checkpoints for a very recent epoch, so we shouldn't need an index here.
|
|
1234
|
+
let checkpoint = await this.store.getCheckpointData(await this.store.getSynchedCheckpointNumber());
|
|
1235
|
+
const slot = (b: CheckpointData) => b.header.slotNumber;
|
|
1236
|
+
while (checkpoint && slot(checkpoint) >= start) {
|
|
1237
|
+
if (slot(checkpoint) <= end) {
|
|
1238
|
+
// push the blocks on backwards
|
|
1239
|
+
const endBlock = checkpoint.startBlock + checkpoint.numBlocks - 1;
|
|
1240
|
+
for (let i = endBlock; i >= checkpoint.startBlock; i--) {
|
|
1241
|
+
const block = await this.getBlock(BlockNumber(i));
|
|
1242
|
+
if (block) {
|
|
1243
|
+
blocks.push(block);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1096
1246
|
}
|
|
1097
|
-
|
|
1247
|
+
checkpoint = await this.store.getCheckpointData(CheckpointNumber(checkpoint.checkpointNumber - 1));
|
|
1098
1248
|
}
|
|
1099
1249
|
|
|
1100
1250
|
return blocks.reverse();
|
|
@@ -1104,17 +1254,22 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1104
1254
|
const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1constants);
|
|
1105
1255
|
const blocks: BlockHeader[] = [];
|
|
1106
1256
|
|
|
1107
|
-
// Walk the list of
|
|
1108
|
-
// We'll typically ask for
|
|
1109
|
-
let
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1257
|
+
// Walk the list of checkpoints backwards and filter by slots matching the requested epoch.
|
|
1258
|
+
// We'll typically ask for checkpoints for a very recent epoch, so we shouldn't need an index here.
|
|
1259
|
+
let checkpoint = await this.store.getCheckpointData(await this.store.getSynchedCheckpointNumber());
|
|
1260
|
+
const slot = (b: CheckpointData) => b.header.slotNumber;
|
|
1261
|
+
while (checkpoint && slot(checkpoint) >= start) {
|
|
1262
|
+
if (slot(checkpoint) <= end) {
|
|
1263
|
+
// push the blocks on backwards
|
|
1264
|
+
const endBlock = checkpoint.startBlock + checkpoint.numBlocks - 1;
|
|
1265
|
+
for (let i = endBlock; i >= checkpoint.startBlock; i--) {
|
|
1266
|
+
const block = await this.getBlockHeader(BlockNumber(i));
|
|
1267
|
+
if (block) {
|
|
1268
|
+
blocks.push(block);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1115
1271
|
}
|
|
1116
|
-
|
|
1117
|
-
header = await this.getBlockHeader(number);
|
|
1272
|
+
checkpoint = await this.store.getCheckpointData(CheckpointNumber(checkpoint.checkpointNumber - 1));
|
|
1118
1273
|
}
|
|
1119
1274
|
return blocks.reverse();
|
|
1120
1275
|
}
|
|
@@ -1152,37 +1307,6 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1152
1307
|
return this.initialSyncComplete;
|
|
1153
1308
|
}
|
|
1154
1309
|
|
|
1155
|
-
public async getPublishedCheckpoints(
|
|
1156
|
-
from: CheckpointNumber,
|
|
1157
|
-
limit: number,
|
|
1158
|
-
proven?: boolean,
|
|
1159
|
-
): Promise<PublishedCheckpoint[]> {
|
|
1160
|
-
// TODO: Implement this properly. This only works when we have one block per checkpoint.
|
|
1161
|
-
const blocks = await this.getPublishedBlocks(BlockNumber(from), limit, proven);
|
|
1162
|
-
return blocks.map(b => b.toPublishedCheckpoint());
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
public async getCheckpointByArchive(archive: Fr): Promise<Checkpoint | undefined> {
|
|
1166
|
-
// TODO: Implement this properly. This only works when we have one block per checkpoint.
|
|
1167
|
-
return (await this.getPublishedBlockByArchive(archive))?.block.toCheckpoint();
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
public async getCheckpoints(from: CheckpointNumber, limit: number, proven?: boolean): Promise<Checkpoint[]> {
|
|
1171
|
-
const published = await this.getPublishedCheckpoints(from, limit, proven);
|
|
1172
|
-
return published.map(p => p.checkpoint);
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
public async getCheckpoint(number: CheckpointNumber): Promise<Checkpoint | undefined> {
|
|
1176
|
-
if (number < 0) {
|
|
1177
|
-
number = await this.getSynchedCheckpointNumber();
|
|
1178
|
-
}
|
|
1179
|
-
if (number === 0) {
|
|
1180
|
-
return undefined;
|
|
1181
|
-
}
|
|
1182
|
-
const published = await this.getPublishedCheckpoints(number, 1);
|
|
1183
|
-
return published[0]?.checkpoint;
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
1310
|
public async getCheckpointHeader(number: CheckpointNumber | 'latest'): Promise<CheckpointHeader | undefined> {
|
|
1187
1311
|
if (number === 'latest') {
|
|
1188
1312
|
number = await this.getSynchedCheckpointNumber();
|
|
@@ -1190,94 +1314,46 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1190
1314
|
if (number === 0) {
|
|
1191
1315
|
return undefined;
|
|
1192
1316
|
}
|
|
1193
|
-
const checkpoint = await this.
|
|
1194
|
-
|
|
1317
|
+
const checkpoint = await this.store.getCheckpointData(number);
|
|
1318
|
+
if (!checkpoint) {
|
|
1319
|
+
return undefined;
|
|
1320
|
+
}
|
|
1321
|
+
return checkpoint.header;
|
|
1195
1322
|
}
|
|
1196
1323
|
|
|
1197
1324
|
public getCheckpointNumber(): Promise<CheckpointNumber> {
|
|
1198
1325
|
return this.getSynchedCheckpointNumber();
|
|
1199
1326
|
}
|
|
1200
1327
|
|
|
1201
|
-
public
|
|
1202
|
-
|
|
1203
|
-
// Checkpoint number will no longer be the same as the block number once we support multiple blocks per checkpoint.
|
|
1204
|
-
return CheckpointNumber(await this.store.getSynchedL2BlockNumber());
|
|
1328
|
+
public getSynchedCheckpointNumber(): Promise<CheckpointNumber> {
|
|
1329
|
+
return this.store.getSynchedCheckpointNumber();
|
|
1205
1330
|
}
|
|
1206
1331
|
|
|
1207
|
-
public
|
|
1208
|
-
|
|
1209
|
-
// Proven checkpoint number will no longer be the same as the proven block number once we support multiple blocks per checkpoint.
|
|
1210
|
-
return CheckpointNumber(await this.store.getProvenL2BlockNumber());
|
|
1332
|
+
public getProvenCheckpointNumber(): Promise<CheckpointNumber> {
|
|
1333
|
+
return this.store.getProvenCheckpointNumber();
|
|
1211
1334
|
}
|
|
1212
1335
|
|
|
1213
1336
|
public setProvenCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
|
|
1214
|
-
|
|
1215
|
-
// Proven checkpoint number will no longer be the same as the proven block number once we support multiple blocks per checkpoint.
|
|
1216
|
-
return this.store.setProvenL2BlockNumber(BlockNumber.fromCheckpointNumber(checkpointNumber));
|
|
1337
|
+
return this.store.setProvenCheckpointNumber(checkpointNumber);
|
|
1217
1338
|
}
|
|
1218
1339
|
|
|
1219
1340
|
public unwindCheckpoints(from: CheckpointNumber, checkpointsToUnwind: number): Promise<boolean> {
|
|
1220
|
-
|
|
1221
|
-
// This only works when we have one block per checkpoint.
|
|
1222
|
-
return this.store.unwindBlocks(BlockNumber.fromCheckpointNumber(from), checkpointsToUnwind);
|
|
1341
|
+
return this.store.unwindCheckpoints(from, checkpointsToUnwind);
|
|
1223
1342
|
}
|
|
1224
1343
|
|
|
1225
|
-
public getLastBlockNumberInCheckpoint(checkpointNumber: CheckpointNumber): Promise<BlockNumber> {
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1344
|
+
public async getLastBlockNumberInCheckpoint(checkpointNumber: CheckpointNumber): Promise<BlockNumber | undefined> {
|
|
1345
|
+
const checkpointData = await this.store.getCheckpointData(checkpointNumber);
|
|
1346
|
+
if (!checkpointData) {
|
|
1347
|
+
return undefined;
|
|
1348
|
+
}
|
|
1349
|
+
return BlockNumber(checkpointData.startBlock + checkpointData.numBlocks - 1);
|
|
1229
1350
|
}
|
|
1230
1351
|
|
|
1231
1352
|
public addCheckpoints(
|
|
1232
1353
|
checkpoints: PublishedCheckpoint[],
|
|
1233
1354
|
pendingChainValidationStatus?: ValidateBlockResult,
|
|
1234
1355
|
): Promise<boolean> {
|
|
1235
|
-
|
|
1236
|
-
// This only works when we have one block per checkpoint.
|
|
1237
|
-
return this.store.addBlocks(
|
|
1238
|
-
checkpoints.map(p => PublishedL2Block.fromPublishedCheckpoint(p)),
|
|
1239
|
-
pendingChainValidationStatus,
|
|
1240
|
-
);
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
|
-
public async getCheckpointsForEpoch(epochNumber: EpochNumber): Promise<Checkpoint[]> {
|
|
1244
|
-
// TODO: Create store and apis for checkpoints.
|
|
1245
|
-
// This only works when we have one block per checkpoint.
|
|
1246
|
-
const blocks = await this.getBlocksForEpoch(epochNumber);
|
|
1247
|
-
return blocks.map(b => b.toCheckpoint());
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
public getL1ToL2MessagesForCheckpoint(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
|
|
1251
|
-
// TODO: Create dedicated api for checkpoints.
|
|
1252
|
-
// This only works when we have one block per checkpoint.
|
|
1253
|
-
return this.getL1ToL2Messages(BlockNumber.fromCheckpointNumber(checkpointNumber));
|
|
1254
|
-
}
|
|
1255
|
-
|
|
1256
|
-
/**
|
|
1257
|
-
* Gets up to `limit` amount of L2 blocks starting from `from`.
|
|
1258
|
-
* @param from - Number of the first block to return (inclusive).
|
|
1259
|
-
* @param limit - The number of blocks to return.
|
|
1260
|
-
* @param proven - If true, only return blocks that have been proven.
|
|
1261
|
-
* @returns The requested L2 blocks.
|
|
1262
|
-
*/
|
|
1263
|
-
public getBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<L2Block[]> {
|
|
1264
|
-
return this.getPublishedBlocks(from, limit, proven).then(blocks => blocks.map(b => b.block));
|
|
1265
|
-
}
|
|
1266
|
-
|
|
1267
|
-
/** Equivalent to getBlocks but includes publish data. */
|
|
1268
|
-
public async getPublishedBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<PublishedL2Block[]> {
|
|
1269
|
-
const limitWithProven = proven
|
|
1270
|
-
? Math.min(limit, Math.max((await this.store.getProvenL2BlockNumber()) - from + 1, 0))
|
|
1271
|
-
: limit;
|
|
1272
|
-
return limitWithProven === 0 ? [] : await this.store.getPublishedBlocks(from, limitWithProven);
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
public getPublishedBlockByHash(blockHash: Fr): Promise<PublishedL2Block | undefined> {
|
|
1276
|
-
return this.store.getPublishedBlockByHash(blockHash);
|
|
1277
|
-
}
|
|
1278
|
-
|
|
1279
|
-
public getPublishedBlockByArchive(archive: Fr): Promise<PublishedL2Block | undefined> {
|
|
1280
|
-
return this.store.getPublishedBlockByArchive(archive);
|
|
1356
|
+
return this.store.addCheckpoints(checkpoints, pendingChainValidationStatus);
|
|
1281
1357
|
}
|
|
1282
1358
|
|
|
1283
1359
|
public getBlockHeaderByHash(blockHash: Fr): Promise<BlockHeader | undefined> {
|
|
@@ -1293,7 +1369,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1293
1369
|
* @param number - The block number to return.
|
|
1294
1370
|
* @returns The requested L2 block.
|
|
1295
1371
|
*/
|
|
1296
|
-
public async
|
|
1372
|
+
public async getL2BlockNew(number: BlockNumber): Promise<L2BlockNew | undefined> {
|
|
1297
1373
|
// If the number provided is -ve, then return the latest block.
|
|
1298
1374
|
if (number < 0) {
|
|
1299
1375
|
number = await this.store.getSynchedL2BlockNumber();
|
|
@@ -1301,8 +1377,8 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1301
1377
|
if (number === 0) {
|
|
1302
1378
|
return undefined;
|
|
1303
1379
|
}
|
|
1304
|
-
const publishedBlock = await this.store.
|
|
1305
|
-
return publishedBlock
|
|
1380
|
+
const publishedBlock = await this.store.store.getBlock(number);
|
|
1381
|
+
return publishedBlock;
|
|
1306
1382
|
}
|
|
1307
1383
|
|
|
1308
1384
|
public async getBlockHeader(number: BlockNumber | 'latest'): Promise<BlockHeader | undefined> {
|
|
@@ -1316,6 +1392,21 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1316
1392
|
return headers.length === 0 ? undefined : headers[0];
|
|
1317
1393
|
}
|
|
1318
1394
|
|
|
1395
|
+
getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
|
|
1396
|
+
return this.store.getCheckpointedBlock(number);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
getCheckpointedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
1400
|
+
return this.store.getCheckpointedBlockByHash(blockHash);
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
getProvenBlockNumber(): Promise<BlockNumber> {
|
|
1404
|
+
return this.store.getProvenBlockNumber();
|
|
1405
|
+
}
|
|
1406
|
+
getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
1407
|
+
return this.store.getCheckpointedBlockByArchive(archive);
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1319
1410
|
public getTxEffect(txHash: TxHash) {
|
|
1320
1411
|
return this.store.getTxEffect(txHash);
|
|
1321
1412
|
}
|
|
@@ -1324,24 +1415,12 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1324
1415
|
return this.store.getSettledTxReceipt(txHash);
|
|
1325
1416
|
}
|
|
1326
1417
|
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
* @param from - The block number from which to begin retrieving logs.
|
|
1330
|
-
* @param limit - The maximum number of blocks to retrieve logs from.
|
|
1331
|
-
* @returns An array of private logs from the specified range of blocks.
|
|
1332
|
-
*/
|
|
1333
|
-
public getPrivateLogs(from: BlockNumber, limit: number): Promise<PrivateLog[]> {
|
|
1334
|
-
return this.store.getPrivateLogs(from, limit);
|
|
1418
|
+
getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
|
|
1419
|
+
return this.store.getPrivateLogsByTags(tags);
|
|
1335
1420
|
}
|
|
1336
1421
|
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
* @param tags - The tags to filter the logs by.
|
|
1340
|
-
* @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
|
|
1341
|
-
* that tag.
|
|
1342
|
-
*/
|
|
1343
|
-
getLogsByTags(tags: Fr[]): Promise<TxScopedL2Log[][]> {
|
|
1344
|
-
return this.store.getLogsByTags(tags);
|
|
1422
|
+
getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
|
|
1423
|
+
return this.store.getPublicLogsByTagsFromContract(contractAddress, tags);
|
|
1345
1424
|
}
|
|
1346
1425
|
|
|
1347
1426
|
/**
|
|
@@ -1364,19 +1443,11 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1364
1443
|
|
|
1365
1444
|
/**
|
|
1366
1445
|
* Gets the number of the latest L2 block processed by the block source implementation.
|
|
1446
|
+
* This includes both checkpointed and uncheckpointed blocks.
|
|
1367
1447
|
* @returns The number of the latest L2 block processed by the block source implementation.
|
|
1368
1448
|
*/
|
|
1369
1449
|
public getBlockNumber(): Promise<BlockNumber> {
|
|
1370
|
-
return this.store.
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
public getProvenBlockNumber(): Promise<BlockNumber> {
|
|
1374
|
-
return this.store.getProvenL2BlockNumber();
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
/** Forcefully updates the last proven block number. Use for testing. */
|
|
1378
|
-
public setProvenBlockNumber(blockNumber: BlockNumber): Promise<void> {
|
|
1379
|
-
return this.store.setProvenL2BlockNumber(blockNumber);
|
|
1450
|
+
return this.store.getLatestBlockNumber();
|
|
1380
1451
|
}
|
|
1381
1452
|
|
|
1382
1453
|
public getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
|
|
@@ -1404,12 +1475,12 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1404
1475
|
}
|
|
1405
1476
|
|
|
1406
1477
|
/**
|
|
1407
|
-
* Gets L1 to L2 message (to be) included in a given
|
|
1408
|
-
* @param
|
|
1478
|
+
* Gets L1 to L2 message (to be) included in a given checkpoint.
|
|
1479
|
+
* @param checkpointNumber - Checkpoint number to get messages for.
|
|
1409
1480
|
* @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found).
|
|
1410
1481
|
*/
|
|
1411
|
-
getL1ToL2Messages(
|
|
1412
|
-
return this.store.getL1ToL2Messages(
|
|
1482
|
+
getL1ToL2Messages(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
|
|
1483
|
+
return this.store.getL1ToL2Messages(checkpointNumber);
|
|
1413
1484
|
}
|
|
1414
1485
|
|
|
1415
1486
|
/**
|
|
@@ -1486,31 +1557,32 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1486
1557
|
}
|
|
1487
1558
|
|
|
1488
1559
|
public async rollbackTo(targetL2BlockNumber: BlockNumber): Promise<void> {
|
|
1560
|
+
// TODO(pw/mbps): This still assumes 1 block per checkpoint
|
|
1489
1561
|
const currentBlocks = await this.getL2Tips();
|
|
1490
1562
|
const currentL2Block = currentBlocks.latest.number;
|
|
1491
1563
|
const currentProvenBlock = currentBlocks.proven.number;
|
|
1492
|
-
// const currentFinalizedBlock = currentBlocks.finalized.number;
|
|
1493
1564
|
|
|
1494
1565
|
if (targetL2BlockNumber >= currentL2Block) {
|
|
1495
1566
|
throw new Error(`Target L2 block ${targetL2BlockNumber} must be less than current L2 block ${currentL2Block}`);
|
|
1496
1567
|
}
|
|
1497
1568
|
const blocksToUnwind = currentL2Block - targetL2BlockNumber;
|
|
1498
|
-
const targetL2Block = await this.store.
|
|
1569
|
+
const targetL2Block = await this.store.getCheckpointedBlock(targetL2BlockNumber);
|
|
1499
1570
|
if (!targetL2Block) {
|
|
1500
1571
|
throw new Error(`Target L2 block ${targetL2BlockNumber} not found`);
|
|
1501
1572
|
}
|
|
1502
1573
|
const targetL1BlockNumber = targetL2Block.l1.blockNumber;
|
|
1574
|
+
const targetCheckpointNumber = CheckpointNumber.fromBlockNumber(targetL2BlockNumber);
|
|
1503
1575
|
const targetL1BlockHash = await this.getL1BlockHash(targetL1BlockNumber);
|
|
1504
|
-
this.log.info(`Unwinding ${blocksToUnwind}
|
|
1505
|
-
await this.store.
|
|
1506
|
-
this.log.info(`Unwinding L1 to L2 messages to ${
|
|
1507
|
-
await this.store.
|
|
1576
|
+
this.log.info(`Unwinding ${blocksToUnwind} checkpoints from L2 block ${currentL2Block}`);
|
|
1577
|
+
await this.store.unwindCheckpoints(CheckpointNumber(currentL2Block), blocksToUnwind);
|
|
1578
|
+
this.log.info(`Unwinding L1 to L2 messages to checkpoint ${targetCheckpointNumber}`);
|
|
1579
|
+
await this.store.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
|
|
1508
1580
|
this.log.info(`Setting L1 syncpoints to ${targetL1BlockNumber}`);
|
|
1509
1581
|
await this.store.setBlockSynchedL1BlockNumber(targetL1BlockNumber);
|
|
1510
1582
|
await this.store.setMessageSynchedL1Block({ l1BlockNumber: targetL1BlockNumber, l1BlockHash: targetL1BlockHash });
|
|
1511
1583
|
if (targetL2BlockNumber < currentProvenBlock) {
|
|
1512
1584
|
this.log.info(`Clearing proven L2 block number`);
|
|
1513
|
-
await this.store.
|
|
1585
|
+
await this.store.setProvenCheckpointNumber(CheckpointNumber.ZERO);
|
|
1514
1586
|
}
|
|
1515
1587
|
// TODO(palla/reorg): Set the finalized block when we add support for it.
|
|
1516
1588
|
// if (targetL2BlockNumber < currentFinalizedBlock) {
|
|
@@ -1518,6 +1590,150 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1518
1590
|
// await this.store.setFinalizedL2BlockNumber(0);
|
|
1519
1591
|
// }
|
|
1520
1592
|
}
|
|
1593
|
+
|
|
1594
|
+
public async getPublishedCheckpoints(
|
|
1595
|
+
checkpointNumber: CheckpointNumber,
|
|
1596
|
+
limit: number,
|
|
1597
|
+
): Promise<PublishedCheckpoint[]> {
|
|
1598
|
+
const checkpoints = await this.store.getRangeOfCheckpoints(checkpointNumber, limit);
|
|
1599
|
+
const blocks = (
|
|
1600
|
+
await Promise.all(checkpoints.map(ch => this.store.getBlocksForCheckpoint(ch.checkpointNumber)))
|
|
1601
|
+
).filter(isDefined);
|
|
1602
|
+
|
|
1603
|
+
const fullCheckpoints: PublishedCheckpoint[] = [];
|
|
1604
|
+
for (let i = 0; i < checkpoints.length; i++) {
|
|
1605
|
+
const blocksForCheckpoint = blocks[i];
|
|
1606
|
+
const checkpoint = checkpoints[i];
|
|
1607
|
+
const fullCheckpoint = new Checkpoint(
|
|
1608
|
+
checkpoint.archive,
|
|
1609
|
+
checkpoint.header,
|
|
1610
|
+
blocksForCheckpoint,
|
|
1611
|
+
checkpoint.checkpointNumber,
|
|
1612
|
+
);
|
|
1613
|
+
const publishedCheckpoint = new PublishedCheckpoint(
|
|
1614
|
+
fullCheckpoint,
|
|
1615
|
+
checkpoint.l1,
|
|
1616
|
+
checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
|
|
1617
|
+
);
|
|
1618
|
+
fullCheckpoints.push(publishedCheckpoint);
|
|
1619
|
+
}
|
|
1620
|
+
return fullCheckpoints;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
public async getCheckpointsForEpoch(epochNumber: EpochNumber): Promise<Checkpoint[]> {
|
|
1624
|
+
const [start, end] = getSlotRangeForEpoch(epochNumber, this.l1constants);
|
|
1625
|
+
const checkpoints: Checkpoint[] = [];
|
|
1626
|
+
|
|
1627
|
+
// Walk the list of checkpoints backwards and filter by slots matching the requested epoch.
|
|
1628
|
+
// We'll typically ask for checkpoints for a very recent epoch, so we shouldn't need an index here.
|
|
1629
|
+
let checkpointData = await this.store.getCheckpointData(await this.store.getSynchedCheckpointNumber());
|
|
1630
|
+
const slot = (b: CheckpointData) => b.header.slotNumber;
|
|
1631
|
+
while (checkpointData && slot(checkpointData) >= start) {
|
|
1632
|
+
if (slot(checkpointData) <= end) {
|
|
1633
|
+
// push the checkpoints on backwards
|
|
1634
|
+
const [checkpoint] = await this.getPublishedCheckpoints(checkpointData.checkpointNumber, 1);
|
|
1635
|
+
checkpoints.push(checkpoint.checkpoint);
|
|
1636
|
+
}
|
|
1637
|
+
checkpointData = await this.store.getCheckpointData(CheckpointNumber(checkpointData.checkpointNumber - 1));
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
return checkpoints.reverse();
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
/* Legacy APIs */
|
|
1644
|
+
|
|
1645
|
+
public async getPublishedBlockByHash(blockHash: Fr): Promise<PublishedL2Block | undefined> {
|
|
1646
|
+
const checkpointedBlock = await this.store.getCheckpointedBlockByHash(blockHash);
|
|
1647
|
+
return this.buildOldBlockFromCheckpointedBlock(checkpointedBlock);
|
|
1648
|
+
}
|
|
1649
|
+
public async getPublishedBlockByArchive(archive: Fr): Promise<PublishedL2Block | undefined> {
|
|
1650
|
+
const checkpointedBlock = await this.store.getCheckpointedBlockByArchive(archive);
|
|
1651
|
+
return this.buildOldBlockFromCheckpointedBlock(checkpointedBlock);
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
/**
|
|
1655
|
+
* Gets up to `limit` amount of L2 blocks starting from `from`.
|
|
1656
|
+
* @param from - Number of the first block to return (inclusive).
|
|
1657
|
+
* @param limit - The number of blocks to return.
|
|
1658
|
+
* @param proven - If true, only return blocks that have been proven.
|
|
1659
|
+
* @returns The requested L2 blocks.
|
|
1660
|
+
*/
|
|
1661
|
+
public async getBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<L2Block[]> {
|
|
1662
|
+
const publishedBlocks = await this.getPublishedBlocks(from, limit, proven);
|
|
1663
|
+
return publishedBlocks.map(x => x.block);
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
public async getPublishedBlocks(from: BlockNumber, limit: number, proven?: boolean): Promise<PublishedL2Block[]> {
|
|
1667
|
+
const checkpoints = await this.store.getRangeOfCheckpoints(CheckpointNumber(from), limit);
|
|
1668
|
+
const provenCheckpointNumber = await this.getProvenCheckpointNumber();
|
|
1669
|
+
const blocks = (
|
|
1670
|
+
await Promise.all(checkpoints.map(ch => this.store.getBlocksForCheckpoint(ch.checkpointNumber)))
|
|
1671
|
+
).filter(isDefined);
|
|
1672
|
+
|
|
1673
|
+
const olbBlocks: PublishedL2Block[] = [];
|
|
1674
|
+
for (let i = 0; i < checkpoints.length; i++) {
|
|
1675
|
+
const blockForCheckpoint = blocks[i][0];
|
|
1676
|
+
const checkpoint = checkpoints[i];
|
|
1677
|
+
if (checkpoint.checkpointNumber > provenCheckpointNumber && proven === true) {
|
|
1678
|
+
// this checkpointisn't proven and we only want proven
|
|
1679
|
+
continue;
|
|
1680
|
+
}
|
|
1681
|
+
const oldCheckpoint = new Checkpoint(
|
|
1682
|
+
blockForCheckpoint.archive,
|
|
1683
|
+
checkpoint.header,
|
|
1684
|
+
[blockForCheckpoint],
|
|
1685
|
+
checkpoint.checkpointNumber,
|
|
1686
|
+
);
|
|
1687
|
+
const oldBlock = L2Block.fromCheckpoint(oldCheckpoint);
|
|
1688
|
+
const publishedBlock = new PublishedL2Block(
|
|
1689
|
+
oldBlock,
|
|
1690
|
+
checkpoint.l1,
|
|
1691
|
+
checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
|
|
1692
|
+
);
|
|
1693
|
+
olbBlocks.push(publishedBlock);
|
|
1694
|
+
}
|
|
1695
|
+
return olbBlocks;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
private async buildOldBlockFromCheckpointedBlock(
|
|
1699
|
+
checkpointedBlock: CheckpointedL2Block | undefined,
|
|
1700
|
+
): Promise<PublishedL2Block | undefined> {
|
|
1701
|
+
if (!checkpointedBlock) {
|
|
1702
|
+
return undefined;
|
|
1703
|
+
}
|
|
1704
|
+
const checkpoint = await this.store.getCheckpointData(checkpointedBlock.checkpointNumber);
|
|
1705
|
+
if (!checkpoint) {
|
|
1706
|
+
return checkpoint;
|
|
1707
|
+
}
|
|
1708
|
+
const fullCheckpoint = new Checkpoint(
|
|
1709
|
+
checkpointedBlock?.block.archive,
|
|
1710
|
+
checkpoint?.header,
|
|
1711
|
+
[checkpointedBlock.block],
|
|
1712
|
+
checkpoint.checkpointNumber,
|
|
1713
|
+
);
|
|
1714
|
+
const oldBlock = L2Block.fromCheckpoint(fullCheckpoint);
|
|
1715
|
+
const published = new PublishedL2Block(
|
|
1716
|
+
oldBlock,
|
|
1717
|
+
checkpoint.l1,
|
|
1718
|
+
checkpoint.attestations.map(x => CommitteeAttestation.fromBuffer(x)),
|
|
1719
|
+
);
|
|
1720
|
+
return published;
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
public async getBlock(number: BlockNumber): Promise<L2Block | undefined> {
|
|
1724
|
+
// If the number provided is -ve, then return the latest block.
|
|
1725
|
+
if (number < 0) {
|
|
1726
|
+
number = await this.store.getSynchedL2BlockNumber();
|
|
1727
|
+
}
|
|
1728
|
+
if (number === 0) {
|
|
1729
|
+
return undefined;
|
|
1730
|
+
}
|
|
1731
|
+
const publishedBlocks = await this.getPublishedBlocks(number, 1);
|
|
1732
|
+
if (publishedBlocks.length === 0) {
|
|
1733
|
+
return undefined;
|
|
1734
|
+
}
|
|
1735
|
+
return publishedBlocks[0].block;
|
|
1736
|
+
}
|
|
1521
1737
|
}
|
|
1522
1738
|
|
|
1523
1739
|
enum Operation {
|
|
@@ -1548,11 +1764,13 @@ export class ArchiverStoreHelper
|
|
|
1548
1764
|
| 'close'
|
|
1549
1765
|
| 'transactionAsync'
|
|
1550
1766
|
| 'addBlocks'
|
|
1767
|
+
| 'getBlock'
|
|
1768
|
+
| 'getBlocks'
|
|
1551
1769
|
>
|
|
1552
1770
|
{
|
|
1553
1771
|
#log = createLogger('archiver:block-helper');
|
|
1554
1772
|
|
|
1555
|
-
constructor(
|
|
1773
|
+
constructor(public readonly store: ArchiverDataStore) {}
|
|
1556
1774
|
|
|
1557
1775
|
/**
|
|
1558
1776
|
* Extracts and stores contract classes out of ContractClassPublished events emitted by the class registry contract.
|
|
@@ -1690,7 +1908,23 @@ export class ArchiverStoreHelper
|
|
|
1690
1908
|
return true;
|
|
1691
1909
|
}
|
|
1692
1910
|
|
|
1693
|
-
|
|
1911
|
+
private async addBlockDataToDB(block: L2BlockNew) {
|
|
1912
|
+
const contractClassLogs = block.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
|
|
1913
|
+
// ContractInstancePublished event logs are broadcast in privateLogs.
|
|
1914
|
+
const privateLogs = block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
|
|
1915
|
+
const publicLogs = block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
|
|
1916
|
+
|
|
1917
|
+
return (
|
|
1918
|
+
await Promise.all([
|
|
1919
|
+
this.#updatePublishedContractClasses(contractClassLogs, block.number, Operation.Store),
|
|
1920
|
+
this.#updateDeployedContractInstances(privateLogs, block.number, Operation.Store),
|
|
1921
|
+
this.#updateUpdatedContractInstances(publicLogs, block.header.globalVariables.timestamp, Operation.Store),
|
|
1922
|
+
this.#storeBroadcastedIndividualFunctions(contractClassLogs, block.number),
|
|
1923
|
+
])
|
|
1924
|
+
).every(Boolean);
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
public addBlocks(blocks: L2BlockNew[], pendingChainValidationStatus?: ValidateBlockResult): Promise<boolean> {
|
|
1694
1928
|
// Add the blocks to the store. Store will throw if the blocks are not in order, there are gaps,
|
|
1695
1929
|
// or if the previous block is not in the store.
|
|
1696
1930
|
return this.store.transactionAsync(async () => {
|
|
@@ -1700,25 +1934,10 @@ export class ArchiverStoreHelper
|
|
|
1700
1934
|
// Update the pending chain validation status if provided
|
|
1701
1935
|
pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
|
|
1702
1936
|
// Add any logs emitted during the retrieved blocks
|
|
1703
|
-
this.store.addLogs(blocks
|
|
1937
|
+
this.store.addLogs(blocks),
|
|
1704
1938
|
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
1705
|
-
...blocks.map(
|
|
1706
|
-
|
|
1707
|
-
// ContractInstancePublished event logs are broadcast in privateLogs.
|
|
1708
|
-
const privateLogs = block.block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
|
|
1709
|
-
const publicLogs = block.block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
|
|
1710
|
-
return (
|
|
1711
|
-
await Promise.all([
|
|
1712
|
-
this.#updatePublishedContractClasses(contractClassLogs, block.block.number, Operation.Store),
|
|
1713
|
-
this.#updateDeployedContractInstances(privateLogs, block.block.number, Operation.Store),
|
|
1714
|
-
this.#updateUpdatedContractInstances(
|
|
1715
|
-
publicLogs,
|
|
1716
|
-
block.block.header.globalVariables.timestamp,
|
|
1717
|
-
Operation.Store,
|
|
1718
|
-
),
|
|
1719
|
-
this.#storeBroadcastedIndividualFunctions(contractClassLogs, block.block.number),
|
|
1720
|
-
])
|
|
1721
|
-
).every(Boolean);
|
|
1939
|
+
...blocks.map(block => {
|
|
1940
|
+
return this.addBlockDataToDB(block);
|
|
1722
1941
|
}),
|
|
1723
1942
|
]);
|
|
1724
1943
|
|
|
@@ -1726,59 +1945,102 @@ export class ArchiverStoreHelper
|
|
|
1726
1945
|
});
|
|
1727
1946
|
}
|
|
1728
1947
|
|
|
1729
|
-
public
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1948
|
+
public addCheckpoints(
|
|
1949
|
+
checkpoints: PublishedCheckpoint[],
|
|
1950
|
+
pendingChainValidationStatus?: ValidateBlockResult,
|
|
1951
|
+
): Promise<boolean> {
|
|
1952
|
+
// Add the blocks to the store. Store will throw if the blocks are not in order, there are gaps,
|
|
1953
|
+
// or if the previous block is not in the store.
|
|
1954
|
+
return this.store.transactionAsync(async () => {
|
|
1955
|
+
await this.store.addCheckpoints(checkpoints);
|
|
1956
|
+
const allBlocks = checkpoints.flatMap((ch: PublishedCheckpoint) => ch.checkpoint.blocks);
|
|
1957
|
+
|
|
1958
|
+
const opResults = await Promise.all([
|
|
1959
|
+
// Update the pending chain validation status if provided
|
|
1960
|
+
pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
|
|
1961
|
+
// Add any logs emitted during the retrieved blocks
|
|
1962
|
+
this.store.addLogs(allBlocks),
|
|
1963
|
+
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
1964
|
+
...allBlocks.map(block => {
|
|
1965
|
+
return this.addBlockDataToDB(block);
|
|
1966
|
+
}),
|
|
1967
|
+
]);
|
|
1968
|
+
|
|
1969
|
+
return opResults.every(Boolean);
|
|
1970
|
+
});
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
public async unwindCheckpoints(from: CheckpointNumber, checkpointsToUnwind: number): Promise<boolean> {
|
|
1974
|
+
if (checkpointsToUnwind <= 0) {
|
|
1975
|
+
throw new Error(`Cannot unwind ${checkpointsToUnwind} blocks`);
|
|
1733
1976
|
}
|
|
1734
|
-
|
|
1735
|
-
|
|
1977
|
+
|
|
1978
|
+
const last = await this.getSynchedCheckpointNumber();
|
|
1979
|
+
if (from != last) {
|
|
1980
|
+
throw new Error(`Cannot unwind checkpoints from checkpoint ${from} when the last checkpoint is ${last}`);
|
|
1736
1981
|
}
|
|
1737
1982
|
|
|
1738
|
-
|
|
1739
|
-
const
|
|
1983
|
+
const blocks = [];
|
|
1984
|
+
const lastCheckpointNumber = from + checkpointsToUnwind - 1;
|
|
1985
|
+
for (let checkpointNumber = from; checkpointNumber <= lastCheckpointNumber; checkpointNumber++) {
|
|
1986
|
+
const blocksForCheckpoint = await this.store.getBlocksForCheckpoint(checkpointNumber);
|
|
1987
|
+
if (!blocksForCheckpoint) {
|
|
1988
|
+
continue;
|
|
1989
|
+
}
|
|
1990
|
+
blocks.push(...blocksForCheckpoint);
|
|
1991
|
+
}
|
|
1740
1992
|
|
|
1741
1993
|
const opResults = await Promise.all([
|
|
1742
1994
|
// Prune rolls back to the last proven block, which is by definition valid
|
|
1743
1995
|
this.store.setPendingChainValidationStatus({ valid: true }),
|
|
1744
1996
|
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
1745
1997
|
...blocks.map(async block => {
|
|
1746
|
-
const contractClassLogs = block.
|
|
1998
|
+
const contractClassLogs = block.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
|
|
1747
1999
|
// ContractInstancePublished event logs are broadcast in privateLogs.
|
|
1748
|
-
const privateLogs = block.
|
|
1749
|
-
const publicLogs = block.
|
|
2000
|
+
const privateLogs = block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
|
|
2001
|
+
const publicLogs = block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
|
|
1750
2002
|
|
|
1751
2003
|
return (
|
|
1752
2004
|
await Promise.all([
|
|
1753
|
-
this.#updatePublishedContractClasses(contractClassLogs, block.
|
|
1754
|
-
this.#updateDeployedContractInstances(privateLogs, block.
|
|
1755
|
-
this.#updateUpdatedContractInstances(
|
|
1756
|
-
publicLogs,
|
|
1757
|
-
block.block.header.globalVariables.timestamp,
|
|
1758
|
-
Operation.Delete,
|
|
1759
|
-
),
|
|
2005
|
+
this.#updatePublishedContractClasses(contractClassLogs, block.number, Operation.Delete),
|
|
2006
|
+
this.#updateDeployedContractInstances(privateLogs, block.number, Operation.Delete),
|
|
2007
|
+
this.#updateUpdatedContractInstances(publicLogs, block.header.globalVariables.timestamp, Operation.Delete),
|
|
1760
2008
|
])
|
|
1761
2009
|
).every(Boolean);
|
|
1762
2010
|
}),
|
|
1763
2011
|
|
|
1764
|
-
this.store.deleteLogs(blocks
|
|
1765
|
-
this.store.
|
|
2012
|
+
this.store.deleteLogs(blocks),
|
|
2013
|
+
this.store.unwindCheckpoints(from, checkpointsToUnwind),
|
|
1766
2014
|
]);
|
|
1767
2015
|
|
|
1768
2016
|
return opResults.every(Boolean);
|
|
1769
2017
|
}
|
|
1770
2018
|
|
|
1771
|
-
|
|
1772
|
-
return this.store.
|
|
2019
|
+
getCheckpointData(checkpointNumber: CheckpointNumber): Promise<CheckpointData | undefined> {
|
|
2020
|
+
return this.store.getCheckpointData(checkpointNumber);
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
getRangeOfCheckpoints(from: CheckpointNumber, limit: number): Promise<CheckpointData[]> {
|
|
2024
|
+
return this.store.getRangeOfCheckpoints(from, limit);
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
getCheckpointedL2BlockNumber(): Promise<BlockNumber> {
|
|
2028
|
+
return this.store.getCheckpointedL2BlockNumber();
|
|
2029
|
+
}
|
|
2030
|
+
getSynchedCheckpointNumber(): Promise<CheckpointNumber> {
|
|
2031
|
+
return this.store.getSynchedCheckpointNumber();
|
|
1773
2032
|
}
|
|
1774
|
-
|
|
1775
|
-
return this.store.
|
|
2033
|
+
setCheckpointSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<void> {
|
|
2034
|
+
return this.store.setCheckpointSynchedL1BlockNumber(l1BlockNumber);
|
|
1776
2035
|
}
|
|
1777
|
-
|
|
1778
|
-
return this.store.
|
|
2036
|
+
getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
|
|
2037
|
+
return this.store.getCheckpointedBlock(number);
|
|
1779
2038
|
}
|
|
1780
|
-
|
|
1781
|
-
return this.store.
|
|
2039
|
+
getCheckpointedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
2040
|
+
return this.store.getCheckpointedBlockByHash(blockHash);
|
|
2041
|
+
}
|
|
2042
|
+
getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
2043
|
+
return this.store.getCheckpointedBlockByArchive(archive);
|
|
1782
2044
|
}
|
|
1783
2045
|
getBlockHeaders(from: BlockNumber, limit: number): Promise<BlockHeader[]> {
|
|
1784
2046
|
return this.store.getBlockHeaders(from, limit);
|
|
@@ -1789,6 +2051,18 @@ export class ArchiverStoreHelper
|
|
|
1789
2051
|
getBlockHeaderByArchive(archive: Fr): Promise<BlockHeader | undefined> {
|
|
1790
2052
|
return this.store.getBlockHeaderByArchive(archive);
|
|
1791
2053
|
}
|
|
2054
|
+
getBlockByHash(blockHash: Fr): Promise<L2BlockNew | undefined> {
|
|
2055
|
+
return this.store.getBlockByHash(blockHash);
|
|
2056
|
+
}
|
|
2057
|
+
getBlockByArchive(archive: Fr): Promise<L2BlockNew | undefined> {
|
|
2058
|
+
return this.store.getBlockByArchive(archive);
|
|
2059
|
+
}
|
|
2060
|
+
getLatestBlockNumber(): Promise<BlockNumber> {
|
|
2061
|
+
return this.store.getLatestBlockNumber();
|
|
2062
|
+
}
|
|
2063
|
+
getBlocksForCheckpoint(checkpointNumber: CheckpointNumber): Promise<L2BlockNew[] | undefined> {
|
|
2064
|
+
return this.store.getBlocksForCheckpoint(checkpointNumber);
|
|
2065
|
+
}
|
|
1792
2066
|
getTxEffect(txHash: TxHash): Promise<IndexedTxEffect | undefined> {
|
|
1793
2067
|
return this.store.getTxEffect(txHash);
|
|
1794
2068
|
}
|
|
@@ -1798,17 +2072,17 @@ export class ArchiverStoreHelper
|
|
|
1798
2072
|
addL1ToL2Messages(messages: InboxMessage[]): Promise<void> {
|
|
1799
2073
|
return this.store.addL1ToL2Messages(messages);
|
|
1800
2074
|
}
|
|
1801
|
-
getL1ToL2Messages(
|
|
1802
|
-
return this.store.getL1ToL2Messages(
|
|
2075
|
+
getL1ToL2Messages(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
|
|
2076
|
+
return this.store.getL1ToL2Messages(checkpointNumber);
|
|
1803
2077
|
}
|
|
1804
2078
|
getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
|
|
1805
2079
|
return this.store.getL1ToL2MessageIndex(l1ToL2Message);
|
|
1806
2080
|
}
|
|
1807
|
-
|
|
1808
|
-
return this.store.
|
|
2081
|
+
getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
|
|
2082
|
+
return this.store.getPrivateLogsByTags(tags);
|
|
1809
2083
|
}
|
|
1810
|
-
|
|
1811
|
-
return this.store.
|
|
2084
|
+
getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
|
|
2085
|
+
return this.store.getPublicLogsByTagsFromContract(contractAddress, tags);
|
|
1812
2086
|
}
|
|
1813
2087
|
getPublicLogs(filter: LogFilter): Promise<GetPublicLogsResponse> {
|
|
1814
2088
|
return this.store.getPublicLogs(filter);
|
|
@@ -1817,16 +2091,19 @@ export class ArchiverStoreHelper
|
|
|
1817
2091
|
return this.store.getContractClassLogs(filter);
|
|
1818
2092
|
}
|
|
1819
2093
|
getSynchedL2BlockNumber(): Promise<BlockNumber> {
|
|
1820
|
-
return this.store.
|
|
2094
|
+
return this.store.getCheckpointedL2BlockNumber();
|
|
2095
|
+
}
|
|
2096
|
+
getProvenCheckpointNumber(): Promise<CheckpointNumber> {
|
|
2097
|
+
return this.store.getProvenCheckpointNumber();
|
|
1821
2098
|
}
|
|
1822
|
-
|
|
1823
|
-
return this.store.
|
|
2099
|
+
getProvenBlockNumber(): Promise<BlockNumber> {
|
|
2100
|
+
return this.store.getProvenBlockNumber();
|
|
1824
2101
|
}
|
|
1825
|
-
|
|
1826
|
-
return this.store.
|
|
2102
|
+
setProvenCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
|
|
2103
|
+
return this.store.setProvenCheckpointNumber(checkpointNumber);
|
|
1827
2104
|
}
|
|
1828
2105
|
setBlockSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<void> {
|
|
1829
|
-
return this.store.
|
|
2106
|
+
return this.store.setCheckpointSynchedL1BlockNumber(l1BlockNumber);
|
|
1830
2107
|
}
|
|
1831
2108
|
setMessageSynchedL1Block(l1Block: L1BlockId): Promise<void> {
|
|
1832
2109
|
return this.store.setMessageSynchedL1Block(l1Block);
|
|
@@ -1858,8 +2135,8 @@ export class ArchiverStoreHelper
|
|
|
1858
2135
|
estimateSize(): Promise<{ mappingSize: number; physicalFileSize: number; actualSize: number; numItems: number }> {
|
|
1859
2136
|
return this.store.estimateSize();
|
|
1860
2137
|
}
|
|
1861
|
-
|
|
1862
|
-
return this.store.
|
|
2138
|
+
rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber: CheckpointNumber): Promise<void> {
|
|
2139
|
+
return this.store.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
|
|
1863
2140
|
}
|
|
1864
2141
|
iterateL1ToL2Messages(range: CustomRange<bigint> = {}): AsyncIterableIterator<InboxMessage> {
|
|
1865
2142
|
return this.store.iterateL1ToL2Messages(range);
|