@aztec/archiver 0.56.0 → 0.57.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dest/archiver/archiver.d.ts +23 -20
- package/dest/archiver/archiver.d.ts.map +1 -1
- package/dest/archiver/archiver.js +353 -103
- package/dest/archiver/archiver_store.d.ts +39 -9
- package/dest/archiver/archiver_store.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.d.ts.map +1 -1
- package/dest/archiver/archiver_store_test_suite.js +75 -18
- package/dest/archiver/config.js +6 -6
- package/dest/archiver/data_retrieval.d.ts +2 -3
- package/dest/archiver/data_retrieval.d.ts.map +1 -1
- package/dest/archiver/data_retrieval.js +21 -20
- package/dest/archiver/epoch_helpers.d.ts +15 -0
- package/dest/archiver/epoch_helpers.d.ts.map +1 -0
- package/dest/archiver/epoch_helpers.js +23 -0
- package/dest/archiver/kv_archiver_store/block_store.d.ts +20 -1
- package/dest/archiver/kv_archiver_store/block_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/block_store.js +62 -5
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts +2 -1
- package/dest/archiver/kv_archiver_store/contract_class_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/contract_class_store.js +11 -4
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts +1 -0
- package/dest/archiver/kv_archiver_store/contract_instance_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/contract_instance_store.js +4 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts +29 -9
- package/dest/archiver/kv_archiver_store/kv_archiver_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/kv_archiver_store.js +57 -17
- package/dest/archiver/kv_archiver_store/log_store.d.ts +4 -5
- package/dest/archiver/kv_archiver_store/log_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/log_store.js +18 -14
- package/dest/archiver/kv_archiver_store/message_store.d.ts +1 -0
- package/dest/archiver/kv_archiver_store/message_store.d.ts.map +1 -1
- package/dest/archiver/kv_archiver_store/message_store.js +10 -3
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts +1 -0
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.d.ts.map +1 -1
- package/dest/archiver/memory_archiver_store/l1_to_l2_message_store.js +4 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts +23 -22
- package/dest/archiver/memory_archiver_store/memory_archiver_store.d.ts.map +1 -1
- package/dest/archiver/memory_archiver_store/memory_archiver_store.js +129 -69
- package/dest/index.js +2 -1
- package/dest/test/index.d.ts +2 -0
- package/dest/test/index.d.ts.map +1 -0
- package/dest/test/index.js +2 -0
- package/dest/test/mock_l2_block_source.d.ts +73 -0
- package/dest/test/mock_l2_block_source.d.ts.map +1 -0
- package/dest/test/mock_l2_block_source.js +134 -0
- package/package.json +15 -11
- package/src/archiver/archiver.ts +457 -149
- package/src/archiver/archiver_store.ts +44 -16
- package/src/archiver/archiver_store_test_suite.ts +91 -52
- package/src/archiver/config.ts +5 -5
- package/src/archiver/data_retrieval.ts +23 -24
- package/src/archiver/epoch_helpers.ts +26 -0
- package/src/archiver/kv_archiver_store/block_store.ts +70 -2
- package/src/archiver/kv_archiver_store/contract_class_store.ts +18 -5
- package/src/archiver/kv_archiver_store/contract_instance_store.ts +4 -0
- package/src/archiver/kv_archiver_store/kv_archiver_store.ts +65 -24
- package/src/archiver/kv_archiver_store/log_store.ts +18 -18
- package/src/archiver/kv_archiver_store/message_store.ts +9 -0
- package/src/archiver/memory_archiver_store/l1_to_l2_message_store.ts +4 -0
- package/src/archiver/memory_archiver_store/memory_archiver_store.ts +149 -80
- package/src/index.ts +1 -0
- package/src/test/index.ts +1 -0
- package/src/test/mock_l2_block_source.ts +165 -0
- package/dest/archiver/kv_archiver_store/proven_store.d.ts +0 -14
- package/dest/archiver/kv_archiver_store/proven_store.d.ts.map +0 -1
- package/dest/archiver/kv_archiver_store/proven_store.js +0 -30
- package/src/archiver/kv_archiver_store/proven_store.ts +0 -34
package/src/archiver/archiver.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type FromLogType,
|
|
3
3
|
type GetUnencryptedLogsResponse,
|
|
4
|
+
type InboxLeaf,
|
|
4
5
|
type L1ToL2MessageSource,
|
|
5
6
|
type L2Block,
|
|
6
7
|
type L2BlockL2Logs,
|
|
@@ -13,14 +14,16 @@ import {
|
|
|
13
14
|
type TxReceipt,
|
|
14
15
|
type UnencryptedL2Log,
|
|
15
16
|
} from '@aztec/circuit-types';
|
|
16
|
-
import { ContractClassRegisteredEvent, type FunctionSelector } from '@aztec/circuits.js';
|
|
17
17
|
import {
|
|
18
|
+
ContractClassRegisteredEvent,
|
|
18
19
|
ContractInstanceDeployedEvent,
|
|
20
|
+
type FunctionSelector,
|
|
21
|
+
type Header,
|
|
19
22
|
PrivateFunctionBroadcastedEvent,
|
|
20
23
|
UnconstrainedFunctionBroadcastedEvent,
|
|
21
24
|
isValidPrivateFunctionMembershipProof,
|
|
22
25
|
isValidUnconstrainedFunctionMembershipProof,
|
|
23
|
-
} from '@aztec/circuits.js
|
|
26
|
+
} from '@aztec/circuits.js';
|
|
24
27
|
import { createEthereumChain } from '@aztec/ethereum';
|
|
25
28
|
import { type ContractArtifact } from '@aztec/foundation/abi';
|
|
26
29
|
import { type AztecAddress } from '@aztec/foundation/aztec-address';
|
|
@@ -52,11 +55,18 @@ import {
|
|
|
52
55
|
http,
|
|
53
56
|
} from 'viem';
|
|
54
57
|
|
|
55
|
-
import { type ArchiverDataStore } from './archiver_store.js';
|
|
58
|
+
import { type ArchiverDataStore, type ArchiverL1SynchPoint } from './archiver_store.js';
|
|
56
59
|
import { type ArchiverConfig } from './config.js';
|
|
57
60
|
import { retrieveBlockFromRollup, retrieveL1ToL2Messages } from './data_retrieval.js';
|
|
61
|
+
import {
|
|
62
|
+
getEpochNumberAtTimestamp,
|
|
63
|
+
getSlotAtTimestamp,
|
|
64
|
+
getSlotRangeForEpoch,
|
|
65
|
+
getTimestampRangeForEpoch,
|
|
66
|
+
} from './epoch_helpers.js';
|
|
58
67
|
import { ArchiverInstrumentation } from './instrumentation.js';
|
|
59
|
-
import { type
|
|
68
|
+
import { type DataRetrieval } from './structs/data_retrieval.js';
|
|
69
|
+
import { type L1Published } from './structs/published.js';
|
|
60
70
|
|
|
61
71
|
/**
|
|
62
72
|
* Helper interface to combine all sources this archiver implementation provides.
|
|
@@ -77,6 +87,11 @@ export class Archiver implements ArchiveSource {
|
|
|
77
87
|
private rollup: GetContractReturnType<typeof RollupAbi, PublicClient<HttpTransport, Chain>>;
|
|
78
88
|
private inbox: GetContractReturnType<typeof InboxAbi, PublicClient<HttpTransport, Chain>>;
|
|
79
89
|
|
|
90
|
+
private store: ArchiverStoreHelper;
|
|
91
|
+
|
|
92
|
+
public l1BlockNumber: bigint | undefined;
|
|
93
|
+
public l1Timestamp: bigint | undefined;
|
|
94
|
+
|
|
80
95
|
/**
|
|
81
96
|
* Creates a new instance of the Archiver.
|
|
82
97
|
* @param publicClient - A client for interacting with the Ethereum node.
|
|
@@ -90,14 +105,16 @@ export class Archiver implements ArchiveSource {
|
|
|
90
105
|
constructor(
|
|
91
106
|
private readonly publicClient: PublicClient<HttpTransport, Chain>,
|
|
92
107
|
private readonly rollupAddress: EthAddress,
|
|
93
|
-
|
|
108
|
+
readonly inboxAddress: EthAddress,
|
|
94
109
|
private readonly registryAddress: EthAddress,
|
|
95
|
-
|
|
96
|
-
private readonly pollingIntervalMs
|
|
110
|
+
readonly dataStore: ArchiverDataStore,
|
|
111
|
+
private readonly pollingIntervalMs: number,
|
|
97
112
|
private readonly instrumentation: ArchiverInstrumentation,
|
|
98
|
-
private readonly
|
|
113
|
+
private readonly l1constants: L1RollupConstants = EmptyL1RollupConstants,
|
|
99
114
|
private readonly log: DebugLogger = createDebugLogger('aztec:archiver'),
|
|
100
115
|
) {
|
|
116
|
+
this.store = new ArchiverStoreHelper(dataStore);
|
|
117
|
+
|
|
101
118
|
this.rollup = getContract({
|
|
102
119
|
address: rollupAddress.toString(),
|
|
103
120
|
abi: RollupAbi,
|
|
@@ -137,7 +154,10 @@ export class Archiver implements ArchiveSource {
|
|
|
137
154
|
client: publicClient,
|
|
138
155
|
});
|
|
139
156
|
|
|
140
|
-
const l1StartBlock = await
|
|
157
|
+
const [l1StartBlock, l1GenesisTime] = await Promise.all([
|
|
158
|
+
rollup.read.L1_BLOCK_AT_GENESIS(),
|
|
159
|
+
rollup.read.GENESIS_TIME(),
|
|
160
|
+
] as const);
|
|
141
161
|
|
|
142
162
|
const archiver = new Archiver(
|
|
143
163
|
publicClient,
|
|
@@ -145,9 +165,9 @@ export class Archiver implements ArchiveSource {
|
|
|
145
165
|
config.l1Contracts.inboxAddress,
|
|
146
166
|
config.l1Contracts.registryAddress,
|
|
147
167
|
archiverStore,
|
|
148
|
-
config.archiverPollingIntervalMS,
|
|
168
|
+
config.archiverPollingIntervalMS ?? 10_000,
|
|
149
169
|
new ArchiverInstrumentation(telemetry),
|
|
150
|
-
|
|
170
|
+
{ l1StartBlock, l1GenesisTime },
|
|
151
171
|
);
|
|
152
172
|
await archiver.start(blockUntilSynced);
|
|
153
173
|
return archiver;
|
|
@@ -199,11 +219,8 @@ export class Archiver implements ArchiveSource {
|
|
|
199
219
|
*
|
|
200
220
|
* This code does not handle reorgs.
|
|
201
221
|
*/
|
|
202
|
-
const {
|
|
203
|
-
|
|
204
|
-
messagesSynchedTo = this.l1StartBlock,
|
|
205
|
-
provenLogsSynchedTo = this.l1StartBlock,
|
|
206
|
-
} = await this.store.getSynchPoint();
|
|
222
|
+
const { l1StartBlock } = this.l1constants;
|
|
223
|
+
const { blocksSynchedTo = l1StartBlock, messagesSynchedTo = l1StartBlock } = await this.store.getSynchPoint();
|
|
207
224
|
const currentL1BlockNumber = await this.publicClient.getBlockNumber();
|
|
208
225
|
|
|
209
226
|
// ********** Ensuring Consistency of data pulled from L1 **********
|
|
@@ -225,14 +242,17 @@ export class Archiver implements ArchiveSource {
|
|
|
225
242
|
* in future but for the time being it should give us the guarantees that we need
|
|
226
243
|
*/
|
|
227
244
|
|
|
228
|
-
await this.updateLastProvenL2Block(provenLogsSynchedTo, currentL1BlockNumber);
|
|
229
|
-
|
|
230
245
|
// ********** Events that are processed per L1 block **********
|
|
231
|
-
|
|
232
246
|
await this.handleL1ToL2Messages(blockUntilSynced, messagesSynchedTo, currentL1BlockNumber);
|
|
233
247
|
|
|
234
248
|
// ********** Events that are processed per L2 block **********
|
|
235
249
|
await this.handleL2blocks(blockUntilSynced, blocksSynchedTo, currentL1BlockNumber);
|
|
250
|
+
|
|
251
|
+
// Store latest l1 block number and timestamp seen. Used for epoch and slots calculations.
|
|
252
|
+
if (!this.l1BlockNumber || this.l1BlockNumber < currentL1BlockNumber) {
|
|
253
|
+
this.l1Timestamp = await this.publicClient.getBlock({ blockNumber: currentL1BlockNumber }).then(b => b.timestamp);
|
|
254
|
+
this.l1BlockNumber = currentL1BlockNumber;
|
|
255
|
+
}
|
|
236
256
|
}
|
|
237
257
|
|
|
238
258
|
private async handleL1ToL2Messages(
|
|
@@ -244,14 +264,10 @@ export class Archiver implements ArchiveSource {
|
|
|
244
264
|
return;
|
|
245
265
|
}
|
|
246
266
|
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
blockUntilSynced,
|
|
250
|
-
messagesSynchedTo + 1n,
|
|
251
|
-
currentL1BlockNumber,
|
|
252
|
-
);
|
|
267
|
+
const localTotalMessageCount = await this.store.getTotalL1ToL2MessageCount();
|
|
268
|
+
const destinationTotalMessageCount = await this.inbox.read.totalMessagesInserted();
|
|
253
269
|
|
|
254
|
-
if (
|
|
270
|
+
if (localTotalMessageCount === destinationTotalMessageCount) {
|
|
255
271
|
await this.store.setMessageSynchedL1BlockNumber(currentL1BlockNumber);
|
|
256
272
|
this.log.verbose(
|
|
257
273
|
`Retrieved no new L1 -> L2 messages between L1 blocks ${messagesSynchedTo + 1n} and ${currentL1BlockNumber}.`,
|
|
@@ -259,6 +275,13 @@ export class Archiver implements ArchiveSource {
|
|
|
259
275
|
return;
|
|
260
276
|
}
|
|
261
277
|
|
|
278
|
+
const retrievedL1ToL2Messages = await retrieveL1ToL2Messages(
|
|
279
|
+
this.inbox,
|
|
280
|
+
blockUntilSynced,
|
|
281
|
+
messagesSynchedTo + 1n,
|
|
282
|
+
currentL1BlockNumber,
|
|
283
|
+
);
|
|
284
|
+
|
|
262
285
|
await this.store.addL1ToL2Messages(retrievedL1ToL2Messages);
|
|
263
286
|
|
|
264
287
|
this.log.verbose(
|
|
@@ -268,46 +291,90 @@ export class Archiver implements ArchiveSource {
|
|
|
268
291
|
);
|
|
269
292
|
}
|
|
270
293
|
|
|
271
|
-
private async updateLastProvenL2Block(provenSynchedTo: bigint, currentL1BlockNumber: bigint) {
|
|
272
|
-
if (currentL1BlockNumber <= provenSynchedTo) {
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
const provenBlockNumber = await this.rollup.read.getProvenBlockNumber();
|
|
277
|
-
if (provenBlockNumber) {
|
|
278
|
-
await this.store.setProvenL2BlockNumber({
|
|
279
|
-
retrievedData: Number(provenBlockNumber),
|
|
280
|
-
lastProcessedL1BlockNumber: currentL1BlockNumber,
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
294
|
private async handleL2blocks(blockUntilSynced: boolean, blocksSynchedTo: bigint, currentL1BlockNumber: bigint) {
|
|
286
295
|
if (currentL1BlockNumber <= blocksSynchedTo) {
|
|
287
296
|
return;
|
|
288
297
|
}
|
|
289
298
|
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
299
|
+
const localPendingBlockNumber = BigInt(await this.getBlockNumber());
|
|
300
|
+
const [
|
|
301
|
+
provenBlockNumber,
|
|
302
|
+
provenArchive,
|
|
303
|
+
pendingBlockNumber,
|
|
304
|
+
pendingArchive,
|
|
305
|
+
archiveForLocalPendingBlockNumber,
|
|
306
|
+
provenEpochNumber,
|
|
307
|
+
] = await this.rollup.read.status([localPendingBlockNumber]);
|
|
308
|
+
|
|
309
|
+
const updateProvenBlock = async () => {
|
|
310
|
+
const localBlockForDestinationProvenBlockNumber = await this.getBlock(Number(provenBlockNumber));
|
|
311
|
+
if (
|
|
312
|
+
localBlockForDestinationProvenBlockNumber &&
|
|
313
|
+
provenArchive === localBlockForDestinationProvenBlockNumber.archive.root.toString()
|
|
314
|
+
) {
|
|
315
|
+
this.log.info(`Updating the proven block number to ${provenBlockNumber} and epoch to ${provenEpochNumber}`);
|
|
316
|
+
await this.store.setProvenL2BlockNumber(Number(provenBlockNumber));
|
|
317
|
+
// if we are here then we must have a valid proven epoch number
|
|
318
|
+
await this.store.setProvenL2EpochNumber(Number(provenEpochNumber));
|
|
319
|
+
}
|
|
320
|
+
};
|
|
301
321
|
|
|
302
|
-
if
|
|
322
|
+
// This is an edge case that we only hit if there are no proposed blocks.
|
|
323
|
+
// If we have 0 blocks locally and there are no blocks onchain there is nothing to do.
|
|
324
|
+
const noBlocks = localPendingBlockNumber === 0n && pendingBlockNumber === 0n;
|
|
325
|
+
if (noBlocks) {
|
|
303
326
|
await this.store.setBlockSynchedL1BlockNumber(currentL1BlockNumber);
|
|
304
327
|
this.log.verbose(`No blocks to retrieve from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
|
|
305
328
|
return;
|
|
306
329
|
}
|
|
307
330
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
331
|
+
await updateProvenBlock();
|
|
332
|
+
|
|
333
|
+
// Related to the L2 reorgs of the pending chain. We are only interested in actually addressing a reorg if there
|
|
334
|
+
// are any state that could be impacted by it. If we have no blocks, there is no impact.
|
|
335
|
+
if (localPendingBlockNumber > 0) {
|
|
336
|
+
const localPendingBlock = await this.getBlock(Number(localPendingBlockNumber));
|
|
337
|
+
if (localPendingBlock === undefined) {
|
|
338
|
+
throw new Error(`Missing block ${localPendingBlockNumber}`);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
const noBlockSinceLast = localPendingBlock && pendingArchive === localPendingBlock.archive.root.toString();
|
|
342
|
+
if (noBlockSinceLast) {
|
|
343
|
+
await this.store.setBlockSynchedL1BlockNumber(currentL1BlockNumber);
|
|
344
|
+
this.log.verbose(`No blocks to retrieve from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const localPendingBlockInChain = archiveForLocalPendingBlockNumber === localPendingBlock.archive.root.toString();
|
|
349
|
+
if (!localPendingBlockInChain) {
|
|
350
|
+
// If our local pending block tip is not in the chain on L1 a "prune" must have happened
|
|
351
|
+
// or the L1 have reorged.
|
|
352
|
+
// In any case, we have to figure out how far into the past the action will take us.
|
|
353
|
+
// For simplicity here, we will simply rewind until we end in a block that is also on the chain on L1.
|
|
354
|
+
this.log.verbose(`L2 prune have occurred, unwind state`);
|
|
355
|
+
|
|
356
|
+
let tipAfterUnwind = localPendingBlockNumber;
|
|
357
|
+
while (true) {
|
|
358
|
+
const candidateBlock = await this.getBlock(Number(tipAfterUnwind));
|
|
359
|
+
if (candidateBlock === undefined) {
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const archiveAtContract = await this.rollup.read.archiveAt([BigInt(candidateBlock.number)]);
|
|
364
|
+
|
|
365
|
+
if (archiveAtContract === candidateBlock.archive.root.toString()) {
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
tipAfterUnwind--;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const blocksToUnwind = localPendingBlockNumber - tipAfterUnwind;
|
|
372
|
+
this.log.verbose(
|
|
373
|
+
`Unwinding ${blocksToUnwind} block${blocksToUnwind > 1n ? 's' : ''} from block ${localPendingBlockNumber}`,
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
await this.store.unwindBlocks(Number(localPendingBlockNumber), Number(blocksToUnwind));
|
|
377
|
+
}
|
|
311
378
|
}
|
|
312
379
|
|
|
313
380
|
this.log.debug(`Retrieving blocks from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
|
|
@@ -321,7 +388,8 @@ export class Archiver implements ArchiveSource {
|
|
|
321
388
|
);
|
|
322
389
|
|
|
323
390
|
if (retrievedBlocks.length === 0) {
|
|
324
|
-
|
|
391
|
+
// We are not calling `setBlockSynchedL1BlockNumber` because it may cause sync issues if based off infura.
|
|
392
|
+
// See further details in earlier comments.
|
|
325
393
|
this.log.verbose(`Retrieved no new blocks from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
|
|
326
394
|
return;
|
|
327
395
|
}
|
|
@@ -340,31 +408,10 @@ export class Archiver implements ArchiveSource {
|
|
|
340
408
|
.join(',')} with last processed L1 block ${lastProcessedL1BlockNumber}`,
|
|
341
409
|
);
|
|
342
410
|
|
|
343
|
-
await Promise.all(
|
|
344
|
-
retrievedBlocks.map(block => {
|
|
345
|
-
return this.store.addLogs(
|
|
346
|
-
block.data.body.noteEncryptedLogs,
|
|
347
|
-
block.data.body.encryptedLogs,
|
|
348
|
-
block.data.body.unencryptedLogs,
|
|
349
|
-
block.data.number,
|
|
350
|
-
);
|
|
351
|
-
}),
|
|
352
|
-
);
|
|
353
|
-
|
|
354
|
-
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
355
|
-
await Promise.all(
|
|
356
|
-
retrievedBlocks.map(async block => {
|
|
357
|
-
const blockLogs = block.data.body.txEffects
|
|
358
|
-
.flatMap(txEffect => (txEffect ? [txEffect.unencryptedLogs] : []))
|
|
359
|
-
.flatMap(txLog => txLog.unrollLogs());
|
|
360
|
-
await this.storeRegisteredContractClasses(blockLogs, block.data.number);
|
|
361
|
-
await this.storeDeployedContractInstances(blockLogs, block.data.number);
|
|
362
|
-
await this.storeBroadcastedIndividualFunctions(blockLogs, block.data.number);
|
|
363
|
-
}),
|
|
364
|
-
);
|
|
365
|
-
|
|
366
411
|
const timer = new Timer();
|
|
367
412
|
await this.store.addBlocks(retrievedBlocks);
|
|
413
|
+
// Important that we update AFTER inserting the blocks.
|
|
414
|
+
await updateProvenBlock();
|
|
368
415
|
this.instrumentation.processNewBlocks(
|
|
369
416
|
timer.ms() / retrievedBlocks.length,
|
|
370
417
|
retrievedBlocks.map(b => b.data),
|
|
@@ -373,73 +420,6 @@ export class Archiver implements ArchiveSource {
|
|
|
373
420
|
this.log.verbose(`Processed ${retrievedBlocks.length} new L2 blocks up to ${lastL2BlockNumber}`);
|
|
374
421
|
}
|
|
375
422
|
|
|
376
|
-
/**
|
|
377
|
-
* Extracts and stores contract classes out of ContractClassRegistered events emitted by the class registerer contract.
|
|
378
|
-
* @param allLogs - All logs emitted in a bunch of blocks.
|
|
379
|
-
*/
|
|
380
|
-
private async storeRegisteredContractClasses(allLogs: UnencryptedL2Log[], blockNum: number) {
|
|
381
|
-
const contractClasses = ContractClassRegisteredEvent.fromLogs(allLogs, ClassRegistererAddress).map(e =>
|
|
382
|
-
e.toContractClassPublic(),
|
|
383
|
-
);
|
|
384
|
-
if (contractClasses.length > 0) {
|
|
385
|
-
contractClasses.forEach(c => this.log.verbose(`Registering contract class ${c.id.toString()}`));
|
|
386
|
-
await this.store.addContractClasses(contractClasses, blockNum);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Extracts and stores contract instances out of ContractInstanceDeployed events emitted by the canonical deployer contract.
|
|
392
|
-
* @param allLogs - All logs emitted in a bunch of blocks.
|
|
393
|
-
*/
|
|
394
|
-
private async storeDeployedContractInstances(allLogs: UnencryptedL2Log[], blockNum: number) {
|
|
395
|
-
const contractInstances = ContractInstanceDeployedEvent.fromLogs(allLogs).map(e => e.toContractInstance());
|
|
396
|
-
if (contractInstances.length > 0) {
|
|
397
|
-
contractInstances.forEach(c => this.log.verbose(`Storing contract instance at ${c.address.toString()}`));
|
|
398
|
-
await this.store.addContractInstances(contractInstances, blockNum);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
private async storeBroadcastedIndividualFunctions(allLogs: UnencryptedL2Log[], _blockNum: number) {
|
|
403
|
-
// Filter out private and unconstrained function broadcast events
|
|
404
|
-
const privateFnEvents = PrivateFunctionBroadcastedEvent.fromLogs(allLogs, ClassRegistererAddress);
|
|
405
|
-
const unconstrainedFnEvents = UnconstrainedFunctionBroadcastedEvent.fromLogs(allLogs, ClassRegistererAddress);
|
|
406
|
-
|
|
407
|
-
// Group all events by contract class id
|
|
408
|
-
for (const [classIdString, classEvents] of Object.entries(
|
|
409
|
-
groupBy([...privateFnEvents, ...unconstrainedFnEvents], e => e.contractClassId.toString()),
|
|
410
|
-
)) {
|
|
411
|
-
const contractClassId = Fr.fromString(classIdString);
|
|
412
|
-
const contractClass = await this.store.getContractClass(contractClassId);
|
|
413
|
-
if (!contractClass) {
|
|
414
|
-
this.log.warn(`Skipping broadcasted functions as contract class ${contractClassId.toString()} was not found`);
|
|
415
|
-
continue;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// Split private and unconstrained functions, and filter out invalid ones
|
|
419
|
-
const allFns = classEvents.map(e => e.toFunctionWithMembershipProof());
|
|
420
|
-
const privateFns = allFns.filter(
|
|
421
|
-
(fn): fn is ExecutablePrivateFunctionWithMembershipProof => 'unconstrainedFunctionsArtifactTreeRoot' in fn,
|
|
422
|
-
);
|
|
423
|
-
const unconstrainedFns = allFns.filter(
|
|
424
|
-
(fn): fn is UnconstrainedFunctionWithMembershipProof => 'privateFunctionsArtifactTreeRoot' in fn,
|
|
425
|
-
);
|
|
426
|
-
const validPrivateFns = privateFns.filter(fn => isValidPrivateFunctionMembershipProof(fn, contractClass));
|
|
427
|
-
const validUnconstrainedFns = unconstrainedFns.filter(fn =>
|
|
428
|
-
isValidUnconstrainedFunctionMembershipProof(fn, contractClass),
|
|
429
|
-
);
|
|
430
|
-
const validFnCount = validPrivateFns.length + validUnconstrainedFns.length;
|
|
431
|
-
if (validFnCount !== allFns.length) {
|
|
432
|
-
this.log.warn(`Skipping ${allFns.length - validFnCount} invalid functions`);
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
// Store the functions in the contract class in a single operation
|
|
436
|
-
if (validFnCount > 0) {
|
|
437
|
-
this.log.verbose(`Storing ${validFnCount} functions for contract class ${contractClassId.toString()}`);
|
|
438
|
-
}
|
|
439
|
-
await this.store.addFunctions(contractClassId, validPrivateFns, validUnconstrainedFns);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
|
|
443
423
|
/**
|
|
444
424
|
* Stops the archiver.
|
|
445
425
|
* @returns A promise signalling completion of the stop process.
|
|
@@ -460,6 +440,68 @@ export class Archiver implements ArchiveSource {
|
|
|
460
440
|
return Promise.resolve(this.registryAddress);
|
|
461
441
|
}
|
|
462
442
|
|
|
443
|
+
public getL1BlockNumber(): bigint {
|
|
444
|
+
const l1BlockNumber = this.l1BlockNumber;
|
|
445
|
+
if (!l1BlockNumber) {
|
|
446
|
+
throw new Error('L1 block number not yet available. Complete an initial sync first.');
|
|
447
|
+
}
|
|
448
|
+
return l1BlockNumber;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
public getL1Timestamp(): bigint {
|
|
452
|
+
const l1Timestamp = this.l1Timestamp;
|
|
453
|
+
if (!l1Timestamp) {
|
|
454
|
+
throw new Error('L1 timestamp not yet available. Complete an initial sync first.');
|
|
455
|
+
}
|
|
456
|
+
return l1Timestamp;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
public getL2SlotNumber(): Promise<bigint> {
|
|
460
|
+
return Promise.resolve(getSlotAtTimestamp(this.getL1Timestamp(), this.l1constants));
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
public getL2EpochNumber(): Promise<bigint> {
|
|
464
|
+
return Promise.resolve(getEpochNumberAtTimestamp(this.getL1Timestamp(), this.l1constants));
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
public async getBlocksForEpoch(epochNumber: bigint): Promise<L2Block[]> {
|
|
468
|
+
const [start, end] = getSlotRangeForEpoch(epochNumber);
|
|
469
|
+
const blocks: L2Block[] = [];
|
|
470
|
+
|
|
471
|
+
// Walk the list of blocks backwards and filter by slots matching the requested epoch.
|
|
472
|
+
// We'll typically ask for blocks for a very recent epoch, so we shouldn't need an index here.
|
|
473
|
+
let block = await this.getBlock(await this.store.getSynchedL2BlockNumber());
|
|
474
|
+
const slot = (b: L2Block) => b.header.globalVariables.slotNumber.toBigInt();
|
|
475
|
+
while (block && slot(block) >= start) {
|
|
476
|
+
if (slot(block) <= end) {
|
|
477
|
+
blocks.push(block);
|
|
478
|
+
}
|
|
479
|
+
block = await this.getBlock(block.number - 1);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
return blocks.reverse();
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
public async isEpochComplete(epochNumber: bigint): Promise<boolean> {
|
|
486
|
+
// The epoch is complete if the current L2 block is the last one in the epoch (or later)
|
|
487
|
+
const header = await this.getBlockHeader('latest');
|
|
488
|
+
const slot = header?.globalVariables.slotNumber.toBigInt();
|
|
489
|
+
const [_startSlot, endSlot] = getSlotRangeForEpoch(epochNumber);
|
|
490
|
+
if (slot && slot >= endSlot) {
|
|
491
|
+
return true;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
// If not, the epoch may also be complete if the L2 slot has passed without a block
|
|
495
|
+
// We compute this based on the timestamp for the given epoch and the timestamp of the last L1 block
|
|
496
|
+
const l1Timestamp = this.getL1Timestamp();
|
|
497
|
+
const [_startTimestamp, endTimestamp] = getTimestampRangeForEpoch(epochNumber, this.l1constants);
|
|
498
|
+
|
|
499
|
+
// For this computation, we throw in a few extra seconds just for good measure,
|
|
500
|
+
// since we know the next L1 block won't be mined within this range
|
|
501
|
+
const leeway = 3n;
|
|
502
|
+
return l1Timestamp + leeway >= endTimestamp;
|
|
503
|
+
}
|
|
504
|
+
|
|
463
505
|
/**
|
|
464
506
|
* Gets up to `limit` amount of L2 blocks starting from `from`.
|
|
465
507
|
* @param from - Number of the first block to return (inclusive).
|
|
@@ -476,7 +518,7 @@ export class Archiver implements ArchiveSource {
|
|
|
476
518
|
|
|
477
519
|
/**
|
|
478
520
|
* Gets an l2 block.
|
|
479
|
-
* @param number - The block number to return
|
|
521
|
+
* @param number - The block number to return.
|
|
480
522
|
* @returns The requested L2 block.
|
|
481
523
|
*/
|
|
482
524
|
public async getBlock(number: number): Promise<L2Block | undefined> {
|
|
@@ -484,10 +526,21 @@ export class Archiver implements ArchiveSource {
|
|
|
484
526
|
if (number < 0) {
|
|
485
527
|
number = await this.store.getSynchedL2BlockNumber();
|
|
486
528
|
}
|
|
529
|
+
if (number == 0) {
|
|
530
|
+
return undefined;
|
|
531
|
+
}
|
|
487
532
|
const blocks = await this.store.getBlocks(number, 1);
|
|
488
533
|
return blocks.length === 0 ? undefined : blocks[0].data;
|
|
489
534
|
}
|
|
490
535
|
|
|
536
|
+
public async getBlockHeader(number: number | 'latest'): Promise<Header | undefined> {
|
|
537
|
+
if (number === 'latest') {
|
|
538
|
+
number = await this.store.getSynchedL2BlockNumber();
|
|
539
|
+
}
|
|
540
|
+
const headers = await this.store.getBlockHeaders(number, 1);
|
|
541
|
+
return headers.length === 0 ? undefined : headers[0];
|
|
542
|
+
}
|
|
543
|
+
|
|
491
544
|
public getTxEffect(txHash: TxHash): Promise<TxEffect | undefined> {
|
|
492
545
|
return this.store.getTxEffect(txHash);
|
|
493
546
|
}
|
|
@@ -553,9 +606,13 @@ export class Archiver implements ArchiveSource {
|
|
|
553
606
|
return this.store.getProvenL2BlockNumber();
|
|
554
607
|
}
|
|
555
608
|
|
|
609
|
+
public getProvenL2EpochNumber(): Promise<number | undefined> {
|
|
610
|
+
return this.store.getProvenL2EpochNumber();
|
|
611
|
+
}
|
|
612
|
+
|
|
556
613
|
/** Forcefully updates the last proven block number. Use for testing. */
|
|
557
|
-
public setProvenBlockNumber(
|
|
558
|
-
return this.store.setProvenL2BlockNumber(
|
|
614
|
+
public setProvenBlockNumber(blockNumber: number): Promise<void> {
|
|
615
|
+
return this.store.setProvenL2BlockNumber(blockNumber);
|
|
559
616
|
}
|
|
560
617
|
|
|
561
618
|
public getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
|
|
@@ -597,3 +654,254 @@ export class Archiver implements ArchiveSource {
|
|
|
597
654
|
return this.store.getContractArtifact(address);
|
|
598
655
|
}
|
|
599
656
|
}
|
|
657
|
+
|
|
658
|
+
enum Operation {
|
|
659
|
+
Store,
|
|
660
|
+
Delete,
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* A helper class that we use to deal with some of the logic needed when adding blocks.
|
|
665
|
+
*
|
|
666
|
+
* I would have preferred to not have this type. But it is useful for handling the logic that any
|
|
667
|
+
* store would need to include otherwise while exposing fewer functions and logic directly to the archiver.
|
|
668
|
+
*/
|
|
669
|
+
class ArchiverStoreHelper
|
|
670
|
+
implements
|
|
671
|
+
Omit<
|
|
672
|
+
ArchiverDataStore,
|
|
673
|
+
| 'addLogs'
|
|
674
|
+
| 'deleteLogs'
|
|
675
|
+
| 'addContractClasses'
|
|
676
|
+
| 'deleteContractClasses'
|
|
677
|
+
| 'addContractInstances'
|
|
678
|
+
| 'deleteContractInstances'
|
|
679
|
+
| 'addFunctions'
|
|
680
|
+
>
|
|
681
|
+
{
|
|
682
|
+
#log = createDebugLogger('aztec:archiver:block-helper');
|
|
683
|
+
|
|
684
|
+
constructor(private readonly store: ArchiverDataStore) {}
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* Extracts and stores contract classes out of ContractClassRegistered events emitted by the class registerer contract.
|
|
688
|
+
* @param allLogs - All logs emitted in a bunch of blocks.
|
|
689
|
+
*/
|
|
690
|
+
async #updateRegisteredContractClasses(allLogs: UnencryptedL2Log[], blockNum: number, operation: Operation) {
|
|
691
|
+
const contractClasses = ContractClassRegisteredEvent.fromLogs(allLogs, ClassRegistererAddress).map(e =>
|
|
692
|
+
e.toContractClassPublic(),
|
|
693
|
+
);
|
|
694
|
+
if (contractClasses.length > 0) {
|
|
695
|
+
contractClasses.forEach(c => this.#log.verbose(`Registering contract class ${c.id.toString()}`));
|
|
696
|
+
if (operation == Operation.Store) {
|
|
697
|
+
return await this.store.addContractClasses(contractClasses, blockNum);
|
|
698
|
+
} else if (operation == Operation.Delete) {
|
|
699
|
+
return await this.store.deleteContractClasses(contractClasses, blockNum);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return true;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* Extracts and stores contract instances out of ContractInstanceDeployed events emitted by the canonical deployer contract.
|
|
707
|
+
* @param allLogs - All logs emitted in a bunch of blocks.
|
|
708
|
+
*/
|
|
709
|
+
async #updateDeployedContractInstances(allLogs: UnencryptedL2Log[], blockNum: number, operation: Operation) {
|
|
710
|
+
const contractInstances = ContractInstanceDeployedEvent.fromLogs(allLogs).map(e => e.toContractInstance());
|
|
711
|
+
if (contractInstances.length > 0) {
|
|
712
|
+
contractInstances.forEach(c =>
|
|
713
|
+
this.#log.verbose(`${Operation[operation]} contract instance at ${c.address.toString()}`),
|
|
714
|
+
);
|
|
715
|
+
if (operation == Operation.Store) {
|
|
716
|
+
return await this.store.addContractInstances(contractInstances, blockNum);
|
|
717
|
+
} else if (operation == Operation.Delete) {
|
|
718
|
+
return await this.store.deleteContractInstances(contractInstances, blockNum);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return true;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Stores the functions that was broadcasted individually
|
|
726
|
+
*
|
|
727
|
+
* @dev Beware that there is not a delete variant of this, since they are added to contract classes
|
|
728
|
+
* and will be deleted as part of the class if needed.
|
|
729
|
+
*
|
|
730
|
+
* @param allLogs - The logs from the block
|
|
731
|
+
* @param _blockNum - The block number
|
|
732
|
+
* @returns
|
|
733
|
+
*/
|
|
734
|
+
async #storeBroadcastedIndividualFunctions(allLogs: UnencryptedL2Log[], _blockNum: number) {
|
|
735
|
+
// Filter out private and unconstrained function broadcast events
|
|
736
|
+
const privateFnEvents = PrivateFunctionBroadcastedEvent.fromLogs(allLogs, ClassRegistererAddress);
|
|
737
|
+
const unconstrainedFnEvents = UnconstrainedFunctionBroadcastedEvent.fromLogs(allLogs, ClassRegistererAddress);
|
|
738
|
+
|
|
739
|
+
// Group all events by contract class id
|
|
740
|
+
for (const [classIdString, classEvents] of Object.entries(
|
|
741
|
+
groupBy([...privateFnEvents, ...unconstrainedFnEvents], e => e.contractClassId.toString()),
|
|
742
|
+
)) {
|
|
743
|
+
const contractClassId = Fr.fromString(classIdString);
|
|
744
|
+
const contractClass = await this.getContractClass(contractClassId);
|
|
745
|
+
if (!contractClass) {
|
|
746
|
+
this.#log.warn(`Skipping broadcasted functions as contract class ${contractClassId.toString()} was not found`);
|
|
747
|
+
continue;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// Split private and unconstrained functions, and filter out invalid ones
|
|
751
|
+
const allFns = classEvents.map(e => e.toFunctionWithMembershipProof());
|
|
752
|
+
const privateFns = allFns.filter(
|
|
753
|
+
(fn): fn is ExecutablePrivateFunctionWithMembershipProof => 'unconstrainedFunctionsArtifactTreeRoot' in fn,
|
|
754
|
+
);
|
|
755
|
+
const unconstrainedFns = allFns.filter(
|
|
756
|
+
(fn): fn is UnconstrainedFunctionWithMembershipProof => 'privateFunctionsArtifactTreeRoot' in fn,
|
|
757
|
+
);
|
|
758
|
+
const validPrivateFns = privateFns.filter(fn => isValidPrivateFunctionMembershipProof(fn, contractClass));
|
|
759
|
+
const validUnconstrainedFns = unconstrainedFns.filter(fn =>
|
|
760
|
+
isValidUnconstrainedFunctionMembershipProof(fn, contractClass),
|
|
761
|
+
);
|
|
762
|
+
const validFnCount = validPrivateFns.length + validUnconstrainedFns.length;
|
|
763
|
+
if (validFnCount !== allFns.length) {
|
|
764
|
+
this.#log.warn(`Skipping ${allFns.length - validFnCount} invalid functions`);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// Store the functions in the contract class in a single operation
|
|
768
|
+
if (validFnCount > 0) {
|
|
769
|
+
this.#log.verbose(`Storing ${validFnCount} functions for contract class ${contractClassId.toString()}`);
|
|
770
|
+
}
|
|
771
|
+
return await this.store.addFunctions(contractClassId, validPrivateFns, validUnconstrainedFns);
|
|
772
|
+
}
|
|
773
|
+
return true;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
async addBlocks(blocks: L1Published<L2Block>[]): Promise<boolean> {
|
|
777
|
+
return [
|
|
778
|
+
this.store.addLogs(blocks.map(block => block.data)),
|
|
779
|
+
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
780
|
+
...(await Promise.all(
|
|
781
|
+
blocks.map(async block => {
|
|
782
|
+
const blockLogs = block.data.body.txEffects
|
|
783
|
+
.flatMap(txEffect => (txEffect ? [txEffect.unencryptedLogs] : []))
|
|
784
|
+
.flatMap(txLog => txLog.unrollLogs());
|
|
785
|
+
|
|
786
|
+
return (
|
|
787
|
+
await Promise.all([
|
|
788
|
+
this.#updateRegisteredContractClasses(blockLogs, block.data.number, Operation.Store),
|
|
789
|
+
this.#updateDeployedContractInstances(blockLogs, block.data.number, Operation.Store),
|
|
790
|
+
this.#storeBroadcastedIndividualFunctions(blockLogs, block.data.number),
|
|
791
|
+
])
|
|
792
|
+
).every(Boolean);
|
|
793
|
+
}),
|
|
794
|
+
)),
|
|
795
|
+
this.store.addBlocks(blocks),
|
|
796
|
+
].every(Boolean);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
async unwindBlocks(from: number, blocksToUnwind: number): Promise<boolean> {
|
|
800
|
+
const last = await this.getSynchedL2BlockNumber();
|
|
801
|
+
if (from != last) {
|
|
802
|
+
throw new Error(`Can only remove from the tip`);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// from - blocksToUnwind = the new head, so + 1 for what we need to remove
|
|
806
|
+
const blocks = await this.getBlocks(from - blocksToUnwind + 1, blocksToUnwind);
|
|
807
|
+
|
|
808
|
+
return [
|
|
809
|
+
// Unroll all logs emitted during the retrieved blocks and extract any contract classes and instances from them
|
|
810
|
+
...(await Promise.all(
|
|
811
|
+
blocks.map(async block => {
|
|
812
|
+
const blockLogs = block.data.body.txEffects
|
|
813
|
+
.flatMap(txEffect => (txEffect ? [txEffect.unencryptedLogs] : []))
|
|
814
|
+
.flatMap(txLog => txLog.unrollLogs());
|
|
815
|
+
await this.#updateRegisteredContractClasses(blockLogs, block.data.number, Operation.Delete);
|
|
816
|
+
await this.#updateDeployedContractInstances(blockLogs, block.data.number, Operation.Delete);
|
|
817
|
+
}),
|
|
818
|
+
)),
|
|
819
|
+
this.store.deleteLogs(blocks.map(b => b.data)),
|
|
820
|
+
this.store.unwindBlocks(from, blocksToUnwind),
|
|
821
|
+
].every(Boolean);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
getBlocks(from: number, limit: number): Promise<L1Published<L2Block>[]> {
|
|
825
|
+
return this.store.getBlocks(from, limit);
|
|
826
|
+
}
|
|
827
|
+
getBlockHeaders(from: number, limit: number): Promise<Header[]> {
|
|
828
|
+
return this.store.getBlockHeaders(from, limit);
|
|
829
|
+
}
|
|
830
|
+
getTxEffect(txHash: TxHash): Promise<TxEffect | undefined> {
|
|
831
|
+
return this.store.getTxEffect(txHash);
|
|
832
|
+
}
|
|
833
|
+
getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined> {
|
|
834
|
+
return this.store.getSettledTxReceipt(txHash);
|
|
835
|
+
}
|
|
836
|
+
addL1ToL2Messages(messages: DataRetrieval<InboxLeaf>): Promise<boolean> {
|
|
837
|
+
return this.store.addL1ToL2Messages(messages);
|
|
838
|
+
}
|
|
839
|
+
getL1ToL2Messages(blockNumber: bigint): Promise<Fr[]> {
|
|
840
|
+
return this.store.getL1ToL2Messages(blockNumber);
|
|
841
|
+
}
|
|
842
|
+
getL1ToL2MessageIndex(l1ToL2Message: Fr, startIndex: bigint): Promise<bigint | undefined> {
|
|
843
|
+
return this.store.getL1ToL2MessageIndex(l1ToL2Message, startIndex);
|
|
844
|
+
}
|
|
845
|
+
getLogs<TLogType extends LogType>(
|
|
846
|
+
from: number,
|
|
847
|
+
limit: number,
|
|
848
|
+
logType: TLogType,
|
|
849
|
+
): Promise<L2BlockL2Logs<FromLogType<TLogType>>[]> {
|
|
850
|
+
return this.store.getLogs(from, limit, logType);
|
|
851
|
+
}
|
|
852
|
+
getUnencryptedLogs(filter: LogFilter): Promise<GetUnencryptedLogsResponse> {
|
|
853
|
+
return this.store.getUnencryptedLogs(filter);
|
|
854
|
+
}
|
|
855
|
+
getSynchedL2BlockNumber(): Promise<number> {
|
|
856
|
+
return this.store.getSynchedL2BlockNumber();
|
|
857
|
+
}
|
|
858
|
+
getProvenL2BlockNumber(): Promise<number> {
|
|
859
|
+
return this.store.getProvenL2BlockNumber();
|
|
860
|
+
}
|
|
861
|
+
getProvenL2EpochNumber(): Promise<number | undefined> {
|
|
862
|
+
return this.store.getProvenL2EpochNumber();
|
|
863
|
+
}
|
|
864
|
+
setProvenL2BlockNumber(l2BlockNumber: number): Promise<void> {
|
|
865
|
+
return this.store.setProvenL2BlockNumber(l2BlockNumber);
|
|
866
|
+
}
|
|
867
|
+
setProvenL2EpochNumber(l2EpochNumber: number): Promise<void> {
|
|
868
|
+
return this.store.setProvenL2EpochNumber(l2EpochNumber);
|
|
869
|
+
}
|
|
870
|
+
setBlockSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<void> {
|
|
871
|
+
return this.store.setBlockSynchedL1BlockNumber(l1BlockNumber);
|
|
872
|
+
}
|
|
873
|
+
setMessageSynchedL1BlockNumber(l1BlockNumber: bigint): Promise<void> {
|
|
874
|
+
return this.store.setMessageSynchedL1BlockNumber(l1BlockNumber);
|
|
875
|
+
}
|
|
876
|
+
getSynchPoint(): Promise<ArchiverL1SynchPoint> {
|
|
877
|
+
return this.store.getSynchPoint();
|
|
878
|
+
}
|
|
879
|
+
getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
|
|
880
|
+
return this.store.getContractClass(id);
|
|
881
|
+
}
|
|
882
|
+
getContractInstance(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
|
|
883
|
+
return this.store.getContractInstance(address);
|
|
884
|
+
}
|
|
885
|
+
getContractClassIds(): Promise<Fr[]> {
|
|
886
|
+
return this.store.getContractClassIds();
|
|
887
|
+
}
|
|
888
|
+
addContractArtifact(address: AztecAddress, contract: ContractArtifact): Promise<void> {
|
|
889
|
+
return this.store.addContractArtifact(address, contract);
|
|
890
|
+
}
|
|
891
|
+
getContractArtifact(address: AztecAddress): Promise<ContractArtifact | undefined> {
|
|
892
|
+
return this.store.getContractArtifact(address);
|
|
893
|
+
}
|
|
894
|
+
getTotalL1ToL2MessageCount(): Promise<bigint> {
|
|
895
|
+
return this.store.getTotalL1ToL2MessageCount();
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
type L1RollupConstants = {
|
|
900
|
+
l1StartBlock: bigint;
|
|
901
|
+
l1GenesisTime: bigint;
|
|
902
|
+
};
|
|
903
|
+
|
|
904
|
+
const EmptyL1RollupConstants: L1RollupConstants = {
|
|
905
|
+
l1StartBlock: 0n,
|
|
906
|
+
l1GenesisTime: 0n,
|
|
907
|
+
};
|