@aztec/archiver 0.0.1-commit.9b94fc1 → 0.0.1-commit.c7c42ec
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 +96 -79
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +451 -214
- package/dest/archiver/archiver_store.d.ts +100 -47
- 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 +1867 -386
- 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 +51 -18
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_store.js +324 -87
- 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 +46 -56
- 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 +149 -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} +52 -107
- 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 -5
- package/dest/archiver/structs/published.d.ts +1 -2
- package/dest/archiver/structs/published.d.ts.map +1 -1
- package/dest/factory.d.ts +2 -2
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +4 -3
- 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 +16 -8
- package/dest/test/mock_archiver.d.ts.map +1 -1
- package/dest/test/mock_archiver.js +19 -14
- package/dest/test/mock_l1_to_l2_message_source.d.ts +7 -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 +10 -9
- package/dest/test/mock_l2_block_source.d.ts +18 -7
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +37 -23
- 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 -8
- package/package.json +17 -16
- package/src/archiver/archiver.ts +595 -296
- package/src/archiver/archiver_store.ts +113 -46
- package/src/archiver/archiver_store_test_suite.ts +1932 -353
- 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 +442 -101
- 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 +87 -71
- package/src/archiver/kv_archiver_store/log_store.ts +209 -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} +101 -165
- 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 +8 -8
- package/src/archiver/structs/published.ts +0 -1
- package/src/factory.ts +4 -3
- 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 +22 -16
- package/src/test/mock_l1_to_l2_message_source.ts +10 -9
- package/src/test/mock_l2_block_source.ts +45 -25
- package/src/test/mock_structs.ts +10 -9
- package/dest/archiver/data_retrieval.d.ts +0 -79
- package/dest/archiver/data_retrieval.d.ts.map +0 -1
package/src/archiver/archiver.ts
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BlobClientInterface } from '@aztec/blob-client/client';
|
|
2
|
+
import { GENESIS_BLOCK_HEADER_HASH } from '@aztec/constants';
|
|
2
3
|
import { EpochCache } from '@aztec/epoch-cache';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
type ViemPublicClient,
|
|
9
|
-
createEthereumChain,
|
|
10
|
-
} 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';
|
|
11
9
|
import { maxBigint } from '@aztec/foundation/bigint';
|
|
12
|
-
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
10
|
+
import { BlockNumber, CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
13
11
|
import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
|
|
14
12
|
import { merge, pick } from '@aztec/foundation/collection';
|
|
13
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
15
14
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
16
|
-
import { Fr } from '@aztec/foundation/fields';
|
|
17
15
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
18
16
|
import { type PromiseWithResolvers, promiseWithResolvers } from '@aztec/foundation/promise';
|
|
19
17
|
import { RunningPromise, makeLoggingErrorHandler } from '@aztec/foundation/running-promise';
|
|
20
18
|
import { count } from '@aztec/foundation/string';
|
|
21
19
|
import { DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
|
|
20
|
+
import { isDefined } from '@aztec/foundation/types';
|
|
22
21
|
import type { CustomRange } from '@aztec/kv-store';
|
|
23
22
|
import { RollupAbi } from '@aztec/l1-artifacts';
|
|
24
23
|
import {
|
|
@@ -34,14 +33,17 @@ import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
|
34
33
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
35
34
|
import {
|
|
36
35
|
type ArchiverEmitter,
|
|
36
|
+
CheckpointedL2Block,
|
|
37
|
+
CommitteeAttestation,
|
|
37
38
|
L2Block,
|
|
38
|
-
|
|
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,13 +129,14 @@ 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
|
|
|
116
136
|
type RollupStatus = {
|
|
117
|
-
provenCheckpointNumber:
|
|
137
|
+
provenCheckpointNumber: CheckpointNumber;
|
|
118
138
|
provenArchive: Hex;
|
|
119
|
-
pendingCheckpointNumber:
|
|
139
|
+
pendingCheckpointNumber: CheckpointNumber;
|
|
120
140
|
pendingArchive: Hex;
|
|
121
141
|
validationResult: ValidateBlockResult | undefined;
|
|
122
142
|
lastRetrievedCheckpoint?: PublishedCheckpoint;
|
|
@@ -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);
|
|
@@ -455,7 +556,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
455
556
|
|
|
456
557
|
/** Checks if there'd be a reorg for the next checkpoint submission and start pruning now. */
|
|
457
558
|
private async handleEpochPrune(
|
|
458
|
-
provenCheckpointNumber:
|
|
559
|
+
provenCheckpointNumber: CheckpointNumber,
|
|
459
560
|
currentL1BlockNumber: bigint,
|
|
460
561
|
currentL1Timestamp: bigint,
|
|
461
562
|
) {
|
|
@@ -465,9 +566,9 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
465
566
|
|
|
466
567
|
if (canPrune) {
|
|
467
568
|
const timer = new Timer();
|
|
468
|
-
const pruneFrom = provenCheckpointNumber + 1;
|
|
569
|
+
const pruneFrom = CheckpointNumber(provenCheckpointNumber + 1);
|
|
469
570
|
|
|
470
|
-
const header = await this.getCheckpointHeader(
|
|
571
|
+
const header = await this.getCheckpointHeader(pruneFrom);
|
|
471
572
|
if (header === undefined) {
|
|
472
573
|
throw new Error(`Missing checkpoint header ${pruneFrom}`);
|
|
473
574
|
}
|
|
@@ -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
|
}
|
|
@@ -681,9 +795,9 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
681
795
|
rollupPendingCheckpointNumber,
|
|
682
796
|
pendingArchive,
|
|
683
797
|
archiveForLocalPendingCheckpointNumber,
|
|
684
|
-
] = await this.rollup.status(
|
|
685
|
-
const provenCheckpointNumber =
|
|
686
|
-
const pendingCheckpointNumber =
|
|
798
|
+
] = await this.rollup.status(localPendingCheckpointNumber, { blockNumber: currentL1BlockNumber });
|
|
799
|
+
const provenCheckpointNumber = CheckpointNumber.fromBigInt(rollupProvenCheckpointNumber);
|
|
800
|
+
const pendingCheckpointNumber = CheckpointNumber.fromBigInt(rollupPendingCheckpointNumber);
|
|
687
801
|
const rollupStatus = {
|
|
688
802
|
provenCheckpointNumber,
|
|
689
803
|
provenArchive,
|
|
@@ -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(
|
|
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,16 +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
|
-
|
|
1272
|
+
checkpoint = await this.store.getCheckpointData(CheckpointNumber(checkpoint.checkpointNumber - 1));
|
|
1117
1273
|
}
|
|
1118
1274
|
return blocks.reverse();
|
|
1119
1275
|
}
|
|
@@ -1151,102 +1307,53 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1151
1307
|
return this.initialSyncComplete;
|
|
1152
1308
|
}
|
|
1153
1309
|
|
|
1154
|
-
public async
|
|
1155
|
-
|
|
1156
|
-
return blocks.map(b => b.toPublishedCheckpoint());
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
public async getCheckpoints(from: number, limit: number, proven?: boolean): Promise<Checkpoint[]> {
|
|
1160
|
-
const published = await this.getPublishedCheckpoints(from, limit, proven);
|
|
1161
|
-
return published.map(p => p.checkpoint);
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
|
-
public async getCheckpoint(number: number): Promise<Checkpoint | undefined> {
|
|
1165
|
-
if (number < 0) {
|
|
1310
|
+
public async getCheckpointHeader(number: CheckpointNumber | 'latest'): Promise<CheckpointHeader | undefined> {
|
|
1311
|
+
if (number === 'latest') {
|
|
1166
1312
|
number = await this.getSynchedCheckpointNumber();
|
|
1167
1313
|
}
|
|
1168
1314
|
if (number === 0) {
|
|
1169
1315
|
return undefined;
|
|
1170
1316
|
}
|
|
1171
|
-
const
|
|
1172
|
-
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
public async getCheckpointHeader(number: number | 'latest'): Promise<CheckpointHeader | undefined> {
|
|
1176
|
-
if (number === 'latest') {
|
|
1177
|
-
number = await this.getSynchedCheckpointNumber();
|
|
1178
|
-
}
|
|
1179
|
-
if (number === 0) {
|
|
1317
|
+
const checkpoint = await this.store.getCheckpointData(number);
|
|
1318
|
+
if (!checkpoint) {
|
|
1180
1319
|
return undefined;
|
|
1181
1320
|
}
|
|
1182
|
-
|
|
1183
|
-
return checkpoint?.header;
|
|
1321
|
+
return checkpoint.header;
|
|
1184
1322
|
}
|
|
1185
1323
|
|
|
1186
|
-
public getCheckpointNumber(): Promise<
|
|
1324
|
+
public getCheckpointNumber(): Promise<CheckpointNumber> {
|
|
1187
1325
|
return this.getSynchedCheckpointNumber();
|
|
1188
1326
|
}
|
|
1189
1327
|
|
|
1190
|
-
public getSynchedCheckpointNumber(): Promise<
|
|
1191
|
-
|
|
1192
|
-
return this.store.getSynchedL2BlockNumber();
|
|
1328
|
+
public getSynchedCheckpointNumber(): Promise<CheckpointNumber> {
|
|
1329
|
+
return this.store.getSynchedCheckpointNumber();
|
|
1193
1330
|
}
|
|
1194
1331
|
|
|
1195
|
-
public getProvenCheckpointNumber(): Promise<
|
|
1196
|
-
|
|
1197
|
-
return this.store.getProvenL2BlockNumber();
|
|
1332
|
+
public getProvenCheckpointNumber(): Promise<CheckpointNumber> {
|
|
1333
|
+
return this.store.getProvenCheckpointNumber();
|
|
1198
1334
|
}
|
|
1199
1335
|
|
|
1200
|
-
public setProvenCheckpointNumber(checkpointNumber:
|
|
1201
|
-
|
|
1202
|
-
return this.store.setProvenL2BlockNumber(checkpointNumber);
|
|
1336
|
+
public setProvenCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
|
|
1337
|
+
return this.store.setProvenCheckpointNumber(checkpointNumber);
|
|
1203
1338
|
}
|
|
1204
1339
|
|
|
1205
|
-
public unwindCheckpoints(from:
|
|
1206
|
-
|
|
1207
|
-
return this.store.unwindBlocks(from, checkpointsToUnwind);
|
|
1340
|
+
public unwindCheckpoints(from: CheckpointNumber, checkpointsToUnwind: number): Promise<boolean> {
|
|
1341
|
+
return this.store.unwindCheckpoints(from, checkpointsToUnwind);
|
|
1208
1342
|
}
|
|
1209
1343
|
|
|
1210
|
-
public getLastBlockNumberInCheckpoint(checkpointNumber:
|
|
1211
|
-
|
|
1212
|
-
|
|
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);
|
|
1213
1350
|
}
|
|
1214
1351
|
|
|
1215
1352
|
public addCheckpoints(
|
|
1216
1353
|
checkpoints: PublishedCheckpoint[],
|
|
1217
1354
|
pendingChainValidationStatus?: ValidateBlockResult,
|
|
1218
1355
|
): Promise<boolean> {
|
|
1219
|
-
return this.store.
|
|
1220
|
-
checkpoints.map(p => PublishedL2Block.fromPublishedCheckpoint(p)),
|
|
1221
|
-
pendingChainValidationStatus,
|
|
1222
|
-
);
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
/**
|
|
1226
|
-
* Gets up to `limit` amount of L2 blocks starting from `from`.
|
|
1227
|
-
* @param from - Number of the first block to return (inclusive).
|
|
1228
|
-
* @param limit - The number of blocks to return.
|
|
1229
|
-
* @param proven - If true, only return blocks that have been proven.
|
|
1230
|
-
* @returns The requested L2 blocks.
|
|
1231
|
-
*/
|
|
1232
|
-
public getBlocks(from: number, limit: number, proven?: boolean): Promise<L2Block[]> {
|
|
1233
|
-
return this.getPublishedBlocks(from, limit, proven).then(blocks => blocks.map(b => b.block));
|
|
1234
|
-
}
|
|
1235
|
-
|
|
1236
|
-
/** Equivalent to getBlocks but includes publish data. */
|
|
1237
|
-
public async getPublishedBlocks(from: number, limit: number, proven?: boolean): Promise<PublishedL2Block[]> {
|
|
1238
|
-
const limitWithProven = proven
|
|
1239
|
-
? Math.min(limit, Math.max((await this.store.getProvenL2BlockNumber()) - from + 1, 0))
|
|
1240
|
-
: limit;
|
|
1241
|
-
return limitWithProven === 0 ? [] : await this.store.getPublishedBlocks(from, limitWithProven);
|
|
1242
|
-
}
|
|
1243
|
-
|
|
1244
|
-
public getPublishedBlockByHash(blockHash: Fr): Promise<PublishedL2Block | undefined> {
|
|
1245
|
-
return this.store.getPublishedBlockByHash(blockHash);
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
public getPublishedBlockByArchive(archive: Fr): Promise<PublishedL2Block | undefined> {
|
|
1249
|
-
return this.store.getPublishedBlockByArchive(archive);
|
|
1356
|
+
return this.store.addCheckpoints(checkpoints, pendingChainValidationStatus);
|
|
1250
1357
|
}
|
|
1251
1358
|
|
|
1252
1359
|
public getBlockHeaderByHash(blockHash: Fr): Promise<BlockHeader | undefined> {
|
|
@@ -1262,7 +1369,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1262
1369
|
* @param number - The block number to return.
|
|
1263
1370
|
* @returns The requested L2 block.
|
|
1264
1371
|
*/
|
|
1265
|
-
public async
|
|
1372
|
+
public async getL2BlockNew(number: BlockNumber): Promise<L2BlockNew | undefined> {
|
|
1266
1373
|
// If the number provided is -ve, then return the latest block.
|
|
1267
1374
|
if (number < 0) {
|
|
1268
1375
|
number = await this.store.getSynchedL2BlockNumber();
|
|
@@ -1270,11 +1377,11 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1270
1377
|
if (number === 0) {
|
|
1271
1378
|
return undefined;
|
|
1272
1379
|
}
|
|
1273
|
-
const publishedBlock = await this.store.
|
|
1274
|
-
return publishedBlock
|
|
1380
|
+
const publishedBlock = await this.store.store.getBlock(number);
|
|
1381
|
+
return publishedBlock;
|
|
1275
1382
|
}
|
|
1276
1383
|
|
|
1277
|
-
public async getBlockHeader(number:
|
|
1384
|
+
public async getBlockHeader(number: BlockNumber | 'latest'): Promise<BlockHeader | undefined> {
|
|
1278
1385
|
if (number === 'latest') {
|
|
1279
1386
|
number = await this.store.getSynchedL2BlockNumber();
|
|
1280
1387
|
}
|
|
@@ -1285,6 +1392,21 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1285
1392
|
return headers.length === 0 ? undefined : headers[0];
|
|
1286
1393
|
}
|
|
1287
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
|
+
|
|
1288
1410
|
public getTxEffect(txHash: TxHash) {
|
|
1289
1411
|
return this.store.getTxEffect(txHash);
|
|
1290
1412
|
}
|
|
@@ -1293,24 +1415,12 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1293
1415
|
return this.store.getSettledTxReceipt(txHash);
|
|
1294
1416
|
}
|
|
1295
1417
|
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
* @param from - The block number from which to begin retrieving logs.
|
|
1299
|
-
* @param limit - The maximum number of blocks to retrieve logs from.
|
|
1300
|
-
* @returns An array of private logs from the specified range of blocks.
|
|
1301
|
-
*/
|
|
1302
|
-
public getPrivateLogs(from: number, limit: number): Promise<PrivateLog[]> {
|
|
1303
|
-
return this.store.getPrivateLogs(from, limit);
|
|
1418
|
+
getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
|
|
1419
|
+
return this.store.getPrivateLogsByTags(tags);
|
|
1304
1420
|
}
|
|
1305
1421
|
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
* @param tags - The tags to filter the logs by.
|
|
1309
|
-
* @returns For each received tag, an array of matching logs is returned. An empty array implies no logs match
|
|
1310
|
-
* that tag.
|
|
1311
|
-
*/
|
|
1312
|
-
getLogsByTags(tags: Fr[]): Promise<TxScopedL2Log[][]> {
|
|
1313
|
-
return this.store.getLogsByTags(tags);
|
|
1422
|
+
getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
|
|
1423
|
+
return this.store.getPublicLogsByTagsFromContract(contractAddress, tags);
|
|
1314
1424
|
}
|
|
1315
1425
|
|
|
1316
1426
|
/**
|
|
@@ -1333,19 +1443,11 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1333
1443
|
|
|
1334
1444
|
/**
|
|
1335
1445
|
* Gets the number of the latest L2 block processed by the block source implementation.
|
|
1446
|
+
* This includes both checkpointed and uncheckpointed blocks.
|
|
1336
1447
|
* @returns The number of the latest L2 block processed by the block source implementation.
|
|
1337
1448
|
*/
|
|
1338
|
-
public getBlockNumber(): Promise<
|
|
1339
|
-
return this.store.
|
|
1340
|
-
}
|
|
1341
|
-
|
|
1342
|
-
public getProvenBlockNumber(): Promise<number> {
|
|
1343
|
-
return this.store.getProvenL2BlockNumber();
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
|
-
/** Forcefully updates the last proven block number. Use for testing. */
|
|
1347
|
-
public setProvenBlockNumber(blockNumber: number): Promise<void> {
|
|
1348
|
-
return this.store.setProvenL2BlockNumber(blockNumber);
|
|
1449
|
+
public getBlockNumber(): Promise<BlockNumber> {
|
|
1450
|
+
return this.store.getLatestBlockNumber();
|
|
1349
1451
|
}
|
|
1350
1452
|
|
|
1351
1453
|
public getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
|
|
@@ -1373,12 +1475,12 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1373
1475
|
}
|
|
1374
1476
|
|
|
1375
1477
|
/**
|
|
1376
|
-
* Gets L1 to L2 message (to be) included in a given
|
|
1377
|
-
* @param
|
|
1478
|
+
* Gets L1 to L2 message (to be) included in a given checkpoint.
|
|
1479
|
+
* @param checkpointNumber - Checkpoint number to get messages for.
|
|
1378
1480
|
* @returns The L1 to L2 messages/leaves of the messages subtree (throws if not found).
|
|
1379
1481
|
*/
|
|
1380
|
-
getL1ToL2Messages(
|
|
1381
|
-
return this.store.getL1ToL2Messages(
|
|
1482
|
+
getL1ToL2Messages(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
|
|
1483
|
+
return this.store.getL1ToL2Messages(checkpointNumber);
|
|
1382
1484
|
}
|
|
1383
1485
|
|
|
1384
1486
|
/**
|
|
@@ -1419,7 +1521,7 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1419
1521
|
// TODO(#13569): Compute proper finalized block number based on L1 finalized block.
|
|
1420
1522
|
// We just force it 2 epochs worth of proven data for now.
|
|
1421
1523
|
// NOTE: update end-to-end/src/e2e_epochs/epochs_empty_blocks.test.ts as that uses finalized blocks in computations
|
|
1422
|
-
const finalizedBlockNumber = Math.max(provenBlockNumber - this.l1constants.epochDuration * 2, 0);
|
|
1524
|
+
const finalizedBlockNumber = BlockNumber(Math.max(provenBlockNumber - this.l1constants.epochDuration * 2, 0));
|
|
1423
1525
|
|
|
1424
1526
|
const [latestBlockHeader, provenBlockHeader, finalizedBlockHeader] = await Promise.all([
|
|
1425
1527
|
latestBlockNumber > 0 ? this.getBlockHeader(latestBlockNumber) : undefined,
|
|
@@ -1443,52 +1545,44 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1443
1545
|
);
|
|
1444
1546
|
}
|
|
1445
1547
|
|
|
1446
|
-
const latestBlockHeaderHash = await latestBlockHeader?.hash();
|
|
1447
|
-
const provenBlockHeaderHash = await provenBlockHeader?.hash();
|
|
1448
|
-
const finalizedBlockHeaderHash = await finalizedBlockHeader?.hash();
|
|
1548
|
+
const latestBlockHeaderHash = (await latestBlockHeader?.hash()) ?? GENESIS_BLOCK_HEADER_HASH;
|
|
1549
|
+
const provenBlockHeaderHash = (await provenBlockHeader?.hash()) ?? GENESIS_BLOCK_HEADER_HASH;
|
|
1550
|
+
const finalizedBlockHeaderHash = (await finalizedBlockHeader?.hash()) ?? GENESIS_BLOCK_HEADER_HASH;
|
|
1449
1551
|
|
|
1450
1552
|
return {
|
|
1451
|
-
latest: {
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
} as L2BlockId,
|
|
1455
|
-
proven: {
|
|
1456
|
-
number: provenBlockNumber,
|
|
1457
|
-
hash: provenBlockHeaderHash?.toString(),
|
|
1458
|
-
} as L2BlockId,
|
|
1459
|
-
finalized: {
|
|
1460
|
-
number: finalizedBlockNumber,
|
|
1461
|
-
hash: finalizedBlockHeaderHash?.toString(),
|
|
1462
|
-
} as L2BlockId,
|
|
1553
|
+
latest: { number: latestBlockNumber, hash: latestBlockHeaderHash.toString() },
|
|
1554
|
+
proven: { number: provenBlockNumber, hash: provenBlockHeaderHash.toString() },
|
|
1555
|
+
finalized: { number: finalizedBlockNumber, hash: finalizedBlockHeaderHash.toString() },
|
|
1463
1556
|
};
|
|
1464
1557
|
}
|
|
1465
1558
|
|
|
1466
|
-
public async rollbackTo(targetL2BlockNumber:
|
|
1559
|
+
public async rollbackTo(targetL2BlockNumber: BlockNumber): Promise<void> {
|
|
1560
|
+
// TODO(pw/mbps): This still assumes 1 block per checkpoint
|
|
1467
1561
|
const currentBlocks = await this.getL2Tips();
|
|
1468
1562
|
const currentL2Block = currentBlocks.latest.number;
|
|
1469
1563
|
const currentProvenBlock = currentBlocks.proven.number;
|
|
1470
|
-
// const currentFinalizedBlock = currentBlocks.finalized.number;
|
|
1471
1564
|
|
|
1472
1565
|
if (targetL2BlockNumber >= currentL2Block) {
|
|
1473
1566
|
throw new Error(`Target L2 block ${targetL2BlockNumber} must be less than current L2 block ${currentL2Block}`);
|
|
1474
1567
|
}
|
|
1475
1568
|
const blocksToUnwind = currentL2Block - targetL2BlockNumber;
|
|
1476
|
-
const targetL2Block = await this.store.
|
|
1569
|
+
const targetL2Block = await this.store.getCheckpointedBlock(targetL2BlockNumber);
|
|
1477
1570
|
if (!targetL2Block) {
|
|
1478
1571
|
throw new Error(`Target L2 block ${targetL2BlockNumber} not found`);
|
|
1479
1572
|
}
|
|
1480
1573
|
const targetL1BlockNumber = targetL2Block.l1.blockNumber;
|
|
1574
|
+
const targetCheckpointNumber = CheckpointNumber.fromBlockNumber(targetL2BlockNumber);
|
|
1481
1575
|
const targetL1BlockHash = await this.getL1BlockHash(targetL1BlockNumber);
|
|
1482
|
-
this.log.info(`Unwinding ${blocksToUnwind}
|
|
1483
|
-
await this.store.
|
|
1484
|
-
this.log.info(`Unwinding L1 to L2 messages to ${
|
|
1485
|
-
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);
|
|
1486
1580
|
this.log.info(`Setting L1 syncpoints to ${targetL1BlockNumber}`);
|
|
1487
1581
|
await this.store.setBlockSynchedL1BlockNumber(targetL1BlockNumber);
|
|
1488
1582
|
await this.store.setMessageSynchedL1Block({ l1BlockNumber: targetL1BlockNumber, l1BlockHash: targetL1BlockHash });
|
|
1489
1583
|
if (targetL2BlockNumber < currentProvenBlock) {
|
|
1490
1584
|
this.log.info(`Clearing proven L2 block number`);
|
|
1491
|
-
await this.store.
|
|
1585
|
+
await this.store.setProvenCheckpointNumber(CheckpointNumber.ZERO);
|
|
1492
1586
|
}
|
|
1493
1587
|
// TODO(palla/reorg): Set the finalized block when we add support for it.
|
|
1494
1588
|
// if (targetL2BlockNumber < currentFinalizedBlock) {
|
|
@@ -1496,6 +1590,150 @@ export class Archiver extends (EventEmitter as new () => ArchiverEmitter) implem
|
|
|
1496
1590
|
// await this.store.setFinalizedL2BlockNumber(0);
|
|
1497
1591
|
// }
|
|
1498
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
|
+
}
|
|
1499
1737
|
}
|
|
1500
1738
|
|
|
1501
1739
|
enum Operation {
|
|
@@ -1526,17 +1764,19 @@ export class ArchiverStoreHelper
|
|
|
1526
1764
|
| 'close'
|
|
1527
1765
|
| 'transactionAsync'
|
|
1528
1766
|
| 'addBlocks'
|
|
1767
|
+
| 'getBlock'
|
|
1768
|
+
| 'getBlocks'
|
|
1529
1769
|
>
|
|
1530
1770
|
{
|
|
1531
1771
|
#log = createLogger('archiver:block-helper');
|
|
1532
1772
|
|
|
1533
|
-
constructor(
|
|
1773
|
+
constructor(public readonly store: ArchiverDataStore) {}
|
|
1534
1774
|
|
|
1535
1775
|
/**
|
|
1536
1776
|
* Extracts and stores contract classes out of ContractClassPublished events emitted by the class registry contract.
|
|
1537
1777
|
* @param allLogs - All logs emitted in a bunch of blocks.
|
|
1538
1778
|
*/
|
|
1539
|
-
async #updatePublishedContractClasses(allLogs: ContractClassLog[], blockNum:
|
|
1779
|
+
async #updatePublishedContractClasses(allLogs: ContractClassLog[], blockNum: BlockNumber, operation: Operation) {
|
|
1540
1780
|
const contractClassPublishedEvents = allLogs
|
|
1541
1781
|
.filter(log => ContractClassPublishedEvent.isContractClassPublishedEvent(log))
|
|
1542
1782
|
.map(log => ContractClassPublishedEvent.fromLog(log));
|
|
@@ -1561,7 +1801,7 @@ export class ArchiverStoreHelper
|
|
|
1561
1801
|
* Extracts and stores contract instances out of ContractInstancePublished events emitted by the canonical deployer contract.
|
|
1562
1802
|
* @param allLogs - All logs emitted in a bunch of blocks.
|
|
1563
1803
|
*/
|
|
1564
|
-
async #updateDeployedContractInstances(allLogs: PrivateLog[], blockNum:
|
|
1804
|
+
async #updateDeployedContractInstances(allLogs: PrivateLog[], blockNum: BlockNumber, operation: Operation) {
|
|
1565
1805
|
const contractInstances = allLogs
|
|
1566
1806
|
.filter(log => ContractInstancePublishedEvent.isContractInstancePublishedEvent(log))
|
|
1567
1807
|
.map(log => ContractInstancePublishedEvent.fromLog(log))
|
|
@@ -1614,7 +1854,7 @@ export class ArchiverStoreHelper
|
|
|
1614
1854
|
* @param _blockNum - The block number
|
|
1615
1855
|
* @returns
|
|
1616
1856
|
*/
|
|
1617
|
-
async #storeBroadcastedIndividualFunctions(allLogs: ContractClassLog[], _blockNum:
|
|
1857
|
+
async #storeBroadcastedIndividualFunctions(allLogs: ContractClassLog[], _blockNum: BlockNumber) {
|
|
1618
1858
|
// Filter out private and utility function broadcast events
|
|
1619
1859
|
const privateFnEvents = allLogs
|
|
1620
1860
|
.filter(log => PrivateFunctionBroadcastedEvent.isPrivateFunctionBroadcastedEvent(log))
|
|
@@ -1668,7 +1908,23 @@ export class ArchiverStoreHelper
|
|
|
1668
1908
|
return true;
|
|
1669
1909
|
}
|
|
1670
1910
|
|
|
1671
|
-
|
|
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> {
|
|
1672
1928
|
// Add the blocks to the store. Store will throw if the blocks are not in order, there are gaps,
|
|
1673
1929
|
// or if the previous block is not in the store.
|
|
1674
1930
|
return this.store.transactionAsync(async () => {
|
|
@@ -1678,25 +1934,10 @@ export class ArchiverStoreHelper
|
|
|
1678
1934
|
// Update the pending chain validation status if provided
|
|
1679
1935
|
pendingChainValidationStatus && this.store.setPendingChainValidationStatus(pendingChainValidationStatus),
|
|
1680
1936
|
// Add any logs emitted during the retrieved blocks
|
|
1681
|
-
this.store.addLogs(blocks
|
|
1937
|
+
this.store.addLogs(blocks),
|
|
1682
1938
|
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
1683
|
-
...blocks.map(
|
|
1684
|
-
|
|
1685
|
-
// ContractInstancePublished event logs are broadcast in privateLogs.
|
|
1686
|
-
const privateLogs = block.block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
|
|
1687
|
-
const publicLogs = block.block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
|
|
1688
|
-
return (
|
|
1689
|
-
await Promise.all([
|
|
1690
|
-
this.#updatePublishedContractClasses(contractClassLogs, block.block.number, Operation.Store),
|
|
1691
|
-
this.#updateDeployedContractInstances(privateLogs, block.block.number, Operation.Store),
|
|
1692
|
-
this.#updateUpdatedContractInstances(
|
|
1693
|
-
publicLogs,
|
|
1694
|
-
block.block.header.globalVariables.timestamp,
|
|
1695
|
-
Operation.Store,
|
|
1696
|
-
),
|
|
1697
|
-
this.#storeBroadcastedIndividualFunctions(contractClassLogs, block.block.number),
|
|
1698
|
-
])
|
|
1699
|
-
).every(Boolean);
|
|
1939
|
+
...blocks.map(block => {
|
|
1940
|
+
return this.addBlockDataToDB(block);
|
|
1700
1941
|
}),
|
|
1701
1942
|
]);
|
|
1702
1943
|
|
|
@@ -1704,61 +1945,104 @@ export class ArchiverStoreHelper
|
|
|
1704
1945
|
});
|
|
1705
1946
|
}
|
|
1706
1947
|
|
|
1707
|
-
public
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
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`);
|
|
1711
1976
|
}
|
|
1712
|
-
|
|
1713
|
-
|
|
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}`);
|
|
1714
1981
|
}
|
|
1715
1982
|
|
|
1716
|
-
|
|
1717
|
-
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
|
+
}
|
|
1718
1992
|
|
|
1719
1993
|
const opResults = await Promise.all([
|
|
1720
1994
|
// Prune rolls back to the last proven block, which is by definition valid
|
|
1721
1995
|
this.store.setPendingChainValidationStatus({ valid: true }),
|
|
1722
1996
|
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
1723
1997
|
...blocks.map(async block => {
|
|
1724
|
-
const contractClassLogs = block.
|
|
1998
|
+
const contractClassLogs = block.body.txEffects.flatMap(txEffect => txEffect.contractClassLogs);
|
|
1725
1999
|
// ContractInstancePublished event logs are broadcast in privateLogs.
|
|
1726
|
-
const privateLogs = block.
|
|
1727
|
-
const publicLogs = block.
|
|
2000
|
+
const privateLogs = block.body.txEffects.flatMap(txEffect => txEffect.privateLogs);
|
|
2001
|
+
const publicLogs = block.body.txEffects.flatMap(txEffect => txEffect.publicLogs);
|
|
1728
2002
|
|
|
1729
2003
|
return (
|
|
1730
2004
|
await Promise.all([
|
|
1731
|
-
this.#updatePublishedContractClasses(contractClassLogs, block.
|
|
1732
|
-
this.#updateDeployedContractInstances(privateLogs, block.
|
|
1733
|
-
this.#updateUpdatedContractInstances(
|
|
1734
|
-
publicLogs,
|
|
1735
|
-
block.block.header.globalVariables.timestamp,
|
|
1736
|
-
Operation.Delete,
|
|
1737
|
-
),
|
|
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),
|
|
1738
2008
|
])
|
|
1739
2009
|
).every(Boolean);
|
|
1740
2010
|
}),
|
|
1741
2011
|
|
|
1742
|
-
this.store.deleteLogs(blocks
|
|
1743
|
-
this.store.
|
|
2012
|
+
this.store.deleteLogs(blocks),
|
|
2013
|
+
this.store.unwindCheckpoints(from, checkpointsToUnwind),
|
|
1744
2014
|
]);
|
|
1745
2015
|
|
|
1746
2016
|
return opResults.every(Boolean);
|
|
1747
2017
|
}
|
|
1748
2018
|
|
|
1749
|
-
|
|
1750
|
-
return this.store.
|
|
2019
|
+
getCheckpointData(checkpointNumber: CheckpointNumber): Promise<CheckpointData | undefined> {
|
|
2020
|
+
return this.store.getCheckpointData(checkpointNumber);
|
|
1751
2021
|
}
|
|
1752
|
-
|
|
1753
|
-
|
|
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();
|
|
2032
|
+
}
|
|
2033
|
+
setCheckpointSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<void> {
|
|
2034
|
+
return this.store.setCheckpointSynchedL1BlockNumber(l1BlockNumber);
|
|
2035
|
+
}
|
|
2036
|
+
getCheckpointedBlock(number: BlockNumber): Promise<CheckpointedL2Block | undefined> {
|
|
2037
|
+
return this.store.getCheckpointedBlock(number);
|
|
1754
2038
|
}
|
|
1755
|
-
|
|
1756
|
-
return this.store.
|
|
2039
|
+
getCheckpointedBlockByHash(blockHash: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
2040
|
+
return this.store.getCheckpointedBlockByHash(blockHash);
|
|
1757
2041
|
}
|
|
1758
|
-
|
|
1759
|
-
return this.store.
|
|
2042
|
+
getCheckpointedBlockByArchive(archive: Fr): Promise<CheckpointedL2Block | undefined> {
|
|
2043
|
+
return this.store.getCheckpointedBlockByArchive(archive);
|
|
1760
2044
|
}
|
|
1761
|
-
getBlockHeaders(from:
|
|
2045
|
+
getBlockHeaders(from: BlockNumber, limit: number): Promise<BlockHeader[]> {
|
|
1762
2046
|
return this.store.getBlockHeaders(from, limit);
|
|
1763
2047
|
}
|
|
1764
2048
|
getBlockHeaderByHash(blockHash: Fr): Promise<BlockHeader | undefined> {
|
|
@@ -1767,6 +2051,18 @@ export class ArchiverStoreHelper
|
|
|
1767
2051
|
getBlockHeaderByArchive(archive: Fr): Promise<BlockHeader | undefined> {
|
|
1768
2052
|
return this.store.getBlockHeaderByArchive(archive);
|
|
1769
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
|
+
}
|
|
1770
2066
|
getTxEffect(txHash: TxHash): Promise<IndexedTxEffect | undefined> {
|
|
1771
2067
|
return this.store.getTxEffect(txHash);
|
|
1772
2068
|
}
|
|
@@ -1776,17 +2072,17 @@ export class ArchiverStoreHelper
|
|
|
1776
2072
|
addL1ToL2Messages(messages: InboxMessage[]): Promise<void> {
|
|
1777
2073
|
return this.store.addL1ToL2Messages(messages);
|
|
1778
2074
|
}
|
|
1779
|
-
getL1ToL2Messages(
|
|
1780
|
-
return this.store.getL1ToL2Messages(
|
|
2075
|
+
getL1ToL2Messages(checkpointNumber: CheckpointNumber): Promise<Fr[]> {
|
|
2076
|
+
return this.store.getL1ToL2Messages(checkpointNumber);
|
|
1781
2077
|
}
|
|
1782
2078
|
getL1ToL2MessageIndex(l1ToL2Message: Fr): Promise<bigint | undefined> {
|
|
1783
2079
|
return this.store.getL1ToL2MessageIndex(l1ToL2Message);
|
|
1784
2080
|
}
|
|
1785
|
-
|
|
1786
|
-
return this.store.
|
|
2081
|
+
getPrivateLogsByTags(tags: SiloedTag[]): Promise<TxScopedL2Log[][]> {
|
|
2082
|
+
return this.store.getPrivateLogsByTags(tags);
|
|
1787
2083
|
}
|
|
1788
|
-
|
|
1789
|
-
return this.store.
|
|
2084
|
+
getPublicLogsByTagsFromContract(contractAddress: AztecAddress, tags: Tag[]): Promise<TxScopedL2Log[][]> {
|
|
2085
|
+
return this.store.getPublicLogsByTagsFromContract(contractAddress, tags);
|
|
1790
2086
|
}
|
|
1791
2087
|
getPublicLogs(filter: LogFilter): Promise<GetPublicLogsResponse> {
|
|
1792
2088
|
return this.store.getPublicLogs(filter);
|
|
@@ -1794,17 +2090,20 @@ export class ArchiverStoreHelper
|
|
|
1794
2090
|
getContractClassLogs(filter: LogFilter): Promise<GetContractClassLogsResponse> {
|
|
1795
2091
|
return this.store.getContractClassLogs(filter);
|
|
1796
2092
|
}
|
|
1797
|
-
getSynchedL2BlockNumber(): Promise<
|
|
1798
|
-
return this.store.
|
|
2093
|
+
getSynchedL2BlockNumber(): Promise<BlockNumber> {
|
|
2094
|
+
return this.store.getCheckpointedL2BlockNumber();
|
|
2095
|
+
}
|
|
2096
|
+
getProvenCheckpointNumber(): Promise<CheckpointNumber> {
|
|
2097
|
+
return this.store.getProvenCheckpointNumber();
|
|
1799
2098
|
}
|
|
1800
|
-
|
|
1801
|
-
return this.store.
|
|
2099
|
+
getProvenBlockNumber(): Promise<BlockNumber> {
|
|
2100
|
+
return this.store.getProvenBlockNumber();
|
|
1802
2101
|
}
|
|
1803
|
-
|
|
1804
|
-
return this.store.
|
|
2102
|
+
setProvenCheckpointNumber(checkpointNumber: CheckpointNumber): Promise<void> {
|
|
2103
|
+
return this.store.setProvenCheckpointNumber(checkpointNumber);
|
|
1805
2104
|
}
|
|
1806
2105
|
setBlockSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<void> {
|
|
1807
|
-
return this.store.
|
|
2106
|
+
return this.store.setCheckpointSynchedL1BlockNumber(l1BlockNumber);
|
|
1808
2107
|
}
|
|
1809
2108
|
setMessageSynchedL1Block(l1Block: L1BlockId): Promise<void> {
|
|
1810
2109
|
return this.store.setMessageSynchedL1Block(l1Block);
|
|
@@ -1836,8 +2135,8 @@ export class ArchiverStoreHelper
|
|
|
1836
2135
|
estimateSize(): Promise<{ mappingSize: number; physicalFileSize: number; actualSize: number; numItems: number }> {
|
|
1837
2136
|
return this.store.estimateSize();
|
|
1838
2137
|
}
|
|
1839
|
-
|
|
1840
|
-
return this.store.
|
|
2138
|
+
rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber: CheckpointNumber): Promise<void> {
|
|
2139
|
+
return this.store.rollbackL1ToL2MessagesToCheckpoint(targetCheckpointNumber);
|
|
1841
2140
|
}
|
|
1842
2141
|
iterateL1ToL2Messages(range: CustomRange<bigint> = {}): AsyncIterableIterator<InboxMessage> {
|
|
1843
2142
|
return this.store.iterateL1ToL2Messages(range);
|