@aztec/archiver 0.0.1-commit.2f68f620 → 0.0.1-commit.3100065
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 -3
- package/dest/archiver.d.ts +22 -4
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +79 -35
- package/dest/config.d.ts +5 -4
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +27 -5
- package/dest/factory.d.ts +8 -2
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +37 -3
- package/dest/l1/calldata_retriever.d.ts +8 -1
- package/dest/l1/calldata_retriever.d.ts.map +1 -1
- package/dest/l1/calldata_retriever.js +7 -6
- package/dest/l1/data_retrieval.d.ts +7 -2
- package/dest/l1/data_retrieval.d.ts.map +1 -1
- package/dest/modules/contract_data_source_adapter.d.ts +2 -2
- package/dest/modules/contract_data_source_adapter.d.ts.map +1 -1
- package/dest/modules/contract_data_source_adapter.js +1 -9
- package/dest/modules/data_source_base.d.ts +2 -3
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +9 -35
- package/dest/modules/data_store_updater.d.ts +1 -1
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +11 -5
- package/dest/modules/instrumentation.d.ts +9 -1
- package/dest/modules/instrumentation.d.ts.map +1 -1
- package/dest/modules/instrumentation.js +23 -2
- package/dest/modules/l1_synchronizer.d.ts +3 -3
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +78 -41
- package/dest/modules/validation.d.ts +29 -7
- package/dest/modules/validation.d.ts.map +1 -1
- package/dest/modules/validation.js +31 -13
- package/dest/store/block_store.d.ts +20 -11
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +43 -25
- package/dest/store/contract_class_store.d.ts +1 -1
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +19 -1
- package/dest/store/contract_instance_store.d.ts +1 -1
- package/dest/store/contract_instance_store.d.ts.map +1 -1
- package/dest/store/contract_instance_store.js +18 -1
- package/dest/store/log_store.d.ts +1 -1
- package/dest/store/log_store.d.ts.map +1 -1
- package/dest/store/log_store.js +3 -3
- package/dest/store/log_store_codec.d.ts +9 -1
- package/dest/store/log_store_codec.d.ts.map +1 -1
- package/dest/store/log_store_codec.js +9 -0
- package/dest/test/fake_l1_state.js +3 -3
- package/dest/test/mock_l1_to_l2_message_source.d.ts +1 -1
- package/dest/test/mock_l1_to_l2_message_source.d.ts.map +1 -1
- package/dest/test/mock_l1_to_l2_message_source.js +1 -2
- package/dest/test/mock_l2_block_source.d.ts +1 -4
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +8 -22
- package/dest/test/mock_structs.d.ts +1 -1
- package/dest/test/mock_structs.d.ts.map +1 -1
- package/dest/test/mock_structs.js +2 -2
- package/dest/test/noop_l1_archiver.d.ts +7 -3
- package/dest/test/noop_l1_archiver.d.ts.map +1 -1
- package/dest/test/noop_l1_archiver.js +9 -6
- package/package.json +14 -13
- package/src/archiver.ts +107 -41
- package/src/config.ts +34 -9
- package/src/factory.ts +46 -4
- package/src/l1/calldata_retriever.ts +13 -6
- package/src/l1/data_retrieval.ts +8 -1
- package/src/modules/contract_data_source_adapter.ts +1 -10
- package/src/modules/data_source_base.ts +9 -38
- package/src/modules/data_store_updater.ts +15 -5
- package/src/modules/instrumentation.ts +15 -2
- package/src/modules/l1_synchronizer.ts +120 -57
- package/src/modules/validation.ts +71 -15
- package/src/store/block_store.ts +42 -31
- package/src/store/contract_class_store.ts +19 -1
- package/src/store/contract_instance_store.ts +18 -1
- package/src/store/log_store.ts +3 -2
- package/src/store/log_store_codec.ts +11 -0
- package/src/test/fake_l1_state.ts +3 -3
- package/src/test/mock_l1_to_l2_message_source.ts +0 -1
- package/src/test/mock_l2_block_source.ts +8 -22
- package/src/test/mock_structs.ts +5 -2
- package/src/test/noop_l1_archiver.ts +15 -5
|
@@ -2,6 +2,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
2
2
|
import { toArray } from '@aztec/foundation/iterable';
|
|
3
3
|
import { BufferReader, numToUInt8, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
4
4
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
5
|
+
import { isProtocolContractClass } from '@aztec/protocol-contracts';
|
|
5
6
|
import type {
|
|
6
7
|
ContractClassPublic,
|
|
7
8
|
ContractClassPublicWithBlockNumber,
|
|
@@ -49,7 +50,19 @@ export class ContractClassStore {
|
|
|
49
50
|
): Promise<void> {
|
|
50
51
|
await this.db.transactionAsync(async () => {
|
|
51
52
|
const key = contractClass.id.toString();
|
|
52
|
-
|
|
53
|
+
const existing = await this.#contractClasses.getAsync(key);
|
|
54
|
+
if (existing !== undefined) {
|
|
55
|
+
// Protocol contracts are preloaded at block 0, so a later on-chain (re-)publish of a bundled
|
|
56
|
+
// protocol class id is valid and must be a no-op. Keep the existing block-0 entry untouched
|
|
57
|
+
// (do not bump its block number) so it survives reorgs of the publishing block.
|
|
58
|
+
if (isProtocolContractClass(contractClass.id)) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// An L1 reorg can re-present an already-stored checkpoint, replaying this class at the same
|
|
62
|
+
// block; treat that as a no-op. A duplicate at a different block still signals double-processing.
|
|
63
|
+
if (deserializeContractClassPublic(existing).l2BlockNumber === blockNumber) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
53
66
|
throw new Error(`Contract class ${key} already exists, cannot add again at block ${blockNumber}`);
|
|
54
67
|
}
|
|
55
68
|
await this.#contractClasses.set(
|
|
@@ -61,6 +74,11 @@ export class ContractClassStore {
|
|
|
61
74
|
}
|
|
62
75
|
|
|
63
76
|
async deleteContractClass(contractClass: ContractClassPublic, blockNumber: number): Promise<void> {
|
|
77
|
+
// Protocol contracts are preloaded at block 0 and must never be deleted, even when the block that
|
|
78
|
+
// (re-)published them on-chain is unwound by a reorg.
|
|
79
|
+
if (isProtocolContractClass(contractClass.id)) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
64
82
|
const restoredContractClass = await this.#contractClasses.getAsync(contractClass.id.toString());
|
|
65
83
|
if (restoredContractClass && deserializeContractClassPublic(restoredContractClass).l2BlockNumber >= blockNumber) {
|
|
66
84
|
await this.db.transactionAsync(async () => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
2
2
|
import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
|
|
3
|
+
import { isProtocolContract } from '@aztec/protocol-contracts';
|
|
3
4
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
4
5
|
import {
|
|
5
6
|
type ContractInstanceUpdateWithAddress,
|
|
@@ -72,8 +73,19 @@ export class ContractInstanceStore {
|
|
|
72
73
|
return this.db.transactionAsync(async () => {
|
|
73
74
|
const key = contractInstance.address.toString();
|
|
74
75
|
if (await this.#contractInstances.hasAsync(key)) {
|
|
76
|
+
// Protocol contracts are preloaded at block 0, so a later on-chain (re-)publish of a bundled
|
|
77
|
+
// protocol instance is valid and must be a no-op. Keep the existing block-0 entry untouched.
|
|
78
|
+
if (isProtocolContract(contractInstance.address)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const existingBlockNumber = await this.#contractInstancePublishedAt.getAsync(key);
|
|
82
|
+
// An L1 reorg can re-present an already-stored checkpoint, replaying this instance at the same
|
|
83
|
+
// block; treat that as a no-op. A duplicate at a different block still signals double-processing.
|
|
84
|
+
if (existingBlockNumber === blockNumber) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
75
87
|
throw new Error(
|
|
76
|
-
`Contract instance at ${key} already exists (deployed at block ${
|
|
88
|
+
`Contract instance at ${key} already exists (deployed at block ${existingBlockNumber}), cannot add again at block ${blockNumber}`,
|
|
77
89
|
);
|
|
78
90
|
}
|
|
79
91
|
await this.#contractInstances.set(key, new SerializableContractInstance(contractInstance).toBuffer());
|
|
@@ -82,6 +94,11 @@ export class ContractInstanceStore {
|
|
|
82
94
|
}
|
|
83
95
|
|
|
84
96
|
deleteContractInstance(contractInstance: ContractInstanceWithAddress): Promise<void> {
|
|
97
|
+
// Protocol contracts are preloaded at block 0 and must never be deleted, even when the block that
|
|
98
|
+
// (re-)published them on-chain is unwound by a reorg.
|
|
99
|
+
if (isProtocolContract(contractInstance.address)) {
|
|
100
|
+
return Promise.resolve();
|
|
101
|
+
}
|
|
85
102
|
return this.db.transactionAsync(async () => {
|
|
86
103
|
await this.#contractInstances.delete(contractInstance.address.toString());
|
|
87
104
|
await this.#contractInstancePublishedAt.delete(contractInstance.address.toString());
|
package/src/store/log_store.ts
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
endOfTxRange,
|
|
27
27
|
fieldHex,
|
|
28
28
|
incKey,
|
|
29
|
+
tagHexForLog,
|
|
29
30
|
} from './log_store_codec.js';
|
|
30
31
|
|
|
31
32
|
/**
|
|
@@ -100,7 +101,7 @@ export class LogStore {
|
|
|
100
101
|
let publicLogIndexWithinTx = 0;
|
|
101
102
|
|
|
102
103
|
for (const log of txEffect.privateLogs) {
|
|
103
|
-
const tagHex =
|
|
104
|
+
const tagHex = tagHexForLog(log.fields);
|
|
104
105
|
const key = encodeKey(tagHex, blockNumber, txIndexWithinBlock, privateLogIndexWithinTx);
|
|
105
106
|
const value = encodeValue({
|
|
106
107
|
txHash,
|
|
@@ -115,7 +116,7 @@ export class LogStore {
|
|
|
115
116
|
|
|
116
117
|
for (const log of txEffect.publicLogs) {
|
|
117
118
|
const contractHex = fieldHex(log.contractAddress);
|
|
118
|
-
const tagHex =
|
|
119
|
+
const tagHex = tagHexForLog(log.fields);
|
|
119
120
|
const key = encodeKey(
|
|
120
121
|
encodePublicPrefix(contractHex, tagHex),
|
|
121
122
|
blockNumber,
|
|
@@ -37,6 +37,17 @@ export function fieldHex(value: Fr | { toString: () => string }): string {
|
|
|
37
37
|
return value.toString().slice(2);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Tag prefix for a log: the hex of its first field, or the empty string when the log carries no fields.
|
|
42
|
+
* A protocol-valid public log can have zero fields (e.g. a raw AVM `EMITPUBLICLOG` with `logSize = 0`),
|
|
43
|
+
* which has no tag to index by. Encoding it under the empty tag keeps it retrievable via the per-block
|
|
44
|
+
* read (and droppable on reorg) while never matching a real 64-hex-char tag query — instead of reading
|
|
45
|
+
* `fields[0]` off an empty array and aborting the whole block-ingestion transaction.
|
|
46
|
+
*/
|
|
47
|
+
export function tagHexForLog(fields: Fr[]): string {
|
|
48
|
+
return fields.length > 0 ? fieldHex(fields[0]) : '';
|
|
49
|
+
}
|
|
50
|
+
|
|
40
51
|
/** Encodes a number as 8-char zero-padded lowercase hex (matches a u32 big-endian byte buffer's lex order). */
|
|
41
52
|
export function u32Hex(n: number): string {
|
|
42
53
|
return n.toString(16).padStart(NUMERIC_HEX_LEN, '0');
|
|
@@ -682,7 +682,7 @@ export class FakeL1State {
|
|
|
682
682
|
getHashedSignaturePayloadTypedData(attestationsAndSigners),
|
|
683
683
|
);
|
|
684
684
|
|
|
685
|
-
const
|
|
685
|
+
const verbatimAttestations = attestationsAndSigners.getPackedAttestations();
|
|
686
686
|
|
|
687
687
|
const rollupInput = encodeFunctionData({
|
|
688
688
|
abi: RollupAbi,
|
|
@@ -693,7 +693,7 @@ export class FakeL1State {
|
|
|
693
693
|
archive,
|
|
694
694
|
oracleInput: { feeAssetPriceModifier: 0n },
|
|
695
695
|
},
|
|
696
|
-
|
|
696
|
+
verbatimAttestations,
|
|
697
697
|
attestationsAndSigners.getSigners().map(signer => signer.toString()),
|
|
698
698
|
attestationsAndSignersSignature.toViemSignature(),
|
|
699
699
|
blobInput,
|
|
@@ -716,7 +716,7 @@ export class FakeL1State {
|
|
|
716
716
|
|
|
717
717
|
// Compute attestationsHash (same logic as CalldataRetriever)
|
|
718
718
|
const attestationsHash = Buffer32.fromString(
|
|
719
|
-
keccak256(encodeAbiParameters([this.getCommitteeAttestationsStructDef()], [
|
|
719
|
+
keccak256(encodeAbiParameters([this.getCommitteeAttestationsStructDef()], [verbatimAttestations])),
|
|
720
720
|
);
|
|
721
721
|
|
|
722
722
|
// Compute payloadDigest (same logic as CalldataRetriever)
|
|
@@ -55,7 +55,6 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
55
55
|
private provenBlockNumber: number = 0;
|
|
56
56
|
private finalizedBlockNumber: number = 0;
|
|
57
57
|
private checkpointedBlockNumber: number = 0;
|
|
58
|
-
private proposedCheckpointBlockNumber: number = 0;
|
|
59
58
|
|
|
60
59
|
private initialHeader: BlockHeader = BlockHeader.empty();
|
|
61
60
|
private initialHeaderHash: BlockHash = GENESIS_BLOCK_HEADER_HASH;
|
|
@@ -164,7 +163,6 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
164
163
|
});
|
|
165
164
|
// Keep tip numbers consistent with remaining blocks.
|
|
166
165
|
this.checkpointedBlockNumber = Math.min(this.checkpointedBlockNumber, maxBlockNum);
|
|
167
|
-
this.proposedCheckpointBlockNumber = Math.min(this.proposedCheckpointBlockNumber, maxBlockNum);
|
|
168
166
|
this.provenBlockNumber = Math.min(this.provenBlockNumber, maxBlockNum);
|
|
169
167
|
this.finalizedBlockNumber = Math.min(this.finalizedBlockNumber, maxBlockNum);
|
|
170
168
|
this.log.verbose(`Removed ${numBlocks} blocks from the mock L2 block source`);
|
|
@@ -181,17 +179,9 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
181
179
|
this.finalizedBlockNumber = finalizedBlockNumber;
|
|
182
180
|
}
|
|
183
181
|
|
|
184
|
-
public setProposedCheckpointBlockNumber(blockNumber: number) {
|
|
185
|
-
this.proposedCheckpointBlockNumber = blockNumber;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
182
|
public setCheckpointedBlockNumber(checkpointedBlockNumber: number) {
|
|
189
183
|
const prevCheckpointed = this.checkpointedBlockNumber;
|
|
190
184
|
this.checkpointedBlockNumber = checkpointedBlockNumber;
|
|
191
|
-
// Proposed checkpoint is always at least as advanced as checkpointed
|
|
192
|
-
if (this.proposedCheckpointBlockNumber < checkpointedBlockNumber) {
|
|
193
|
-
this.proposedCheckpointBlockNumber = checkpointedBlockNumber;
|
|
194
|
-
}
|
|
195
185
|
// Auto-create single-block checkpoints for newly checkpointed blocks that don't have one yet.
|
|
196
186
|
// This handles blocks added via addProposedBlocks that are now being marked as checkpointed.
|
|
197
187
|
const newCheckpoints: Checkpoint[] = [];
|
|
@@ -255,10 +245,6 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
255
245
|
return block ? block.header.globalVariables.blockNumber : undefined;
|
|
256
246
|
}
|
|
257
247
|
|
|
258
|
-
public getProposedCheckpointL2BlockNumber() {
|
|
259
|
-
return Promise.resolve(BlockNumber(this.proposedCheckpointBlockNumber));
|
|
260
|
-
}
|
|
261
|
-
|
|
262
248
|
public getCheckpoint(query: CheckpointQuery): Promise<PublishedCheckpoint | undefined> {
|
|
263
249
|
const checkpoint = this.resolveCheckpointQuery(query);
|
|
264
250
|
if (!checkpoint) {
|
|
@@ -337,6 +323,13 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
337
323
|
if ('from' in query) {
|
|
338
324
|
return this.checkpointList.slice(query.from - 1, query.from - 1 + query.limit);
|
|
339
325
|
}
|
|
326
|
+
if ('fromSlot' in query) {
|
|
327
|
+
const matching = this.checkpointList.filter(c =>
|
|
328
|
+
query.reverse ? c.header.slotNumber <= query.fromSlot : c.header.slotNumber >= query.fromSlot,
|
|
329
|
+
);
|
|
330
|
+
const nearestFirst = query.reverse ? matching.reverse() : matching;
|
|
331
|
+
return nearestFirst.slice(0, query.limit);
|
|
332
|
+
}
|
|
340
333
|
return this.getCheckpointsInEpoch(query.epoch);
|
|
341
334
|
}
|
|
342
335
|
|
|
@@ -373,19 +366,17 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
373
366
|
}
|
|
374
367
|
|
|
375
368
|
async getL2Tips(): Promise<L2Tips> {
|
|
376
|
-
const [latest, proven, finalized, checkpointed
|
|
369
|
+
const [latest, proven, finalized, checkpointed] = [
|
|
377
370
|
await this.getBlockNumber(),
|
|
378
371
|
this.provenBlockNumber,
|
|
379
372
|
this.finalizedBlockNumber,
|
|
380
373
|
this.checkpointedBlockNumber,
|
|
381
|
-
await this.getProposedCheckpointL2BlockNumber(),
|
|
382
374
|
] as const;
|
|
383
375
|
|
|
384
376
|
const latestBlock = this.l2Blocks[latest - 1];
|
|
385
377
|
const provenBlock = this.l2Blocks[proven - 1];
|
|
386
378
|
const finalizedBlock = this.l2Blocks[finalized - 1];
|
|
387
379
|
const checkpointedBlock = this.l2Blocks[checkpointed - 1];
|
|
388
|
-
const proposedCheckpointBlock = this.l2Blocks[proposedCheckpoint - 1];
|
|
389
380
|
|
|
390
381
|
// For genesis tips (block number 0) report the dynamic initial header hash so consumers
|
|
391
382
|
// running L2BlockStream against this mock agree at block 0 with their local tip store.
|
|
@@ -413,10 +404,6 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
413
404
|
number: BlockNumber(checkpointed),
|
|
414
405
|
hash: await tipHash(checkpointedBlock, checkpointed),
|
|
415
406
|
};
|
|
416
|
-
const proposedCheckpointBlockId = {
|
|
417
|
-
number: BlockNumber(proposedCheckpoint),
|
|
418
|
-
hash: await tipHash(proposedCheckpointBlock, proposedCheckpoint),
|
|
419
|
-
};
|
|
420
407
|
|
|
421
408
|
const makeTipId = (blockId: typeof latestBlockId) => {
|
|
422
409
|
const checkpointNumber = this.findCheckpointNumberForBlock(blockId.number) ?? CheckpointNumber(0);
|
|
@@ -435,7 +422,6 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
435
422
|
checkpointed: makeTipId(checkpointedBlockId),
|
|
436
423
|
proven: makeTipId(provenBlockId),
|
|
437
424
|
finalized: makeTipId(finalizedBlockId),
|
|
438
|
-
proposedCheckpoint: makeTipId(proposedCheckpointBlockId),
|
|
439
425
|
};
|
|
440
426
|
}
|
|
441
427
|
|
package/src/test/mock_structs.ts
CHANGED
|
@@ -269,7 +269,10 @@ export function makePublicLogTag(blockNumber: number, txIndex: number, logIndex:
|
|
|
269
269
|
}
|
|
270
270
|
|
|
271
271
|
/** Creates a PublicLog with fields derived from the tag. */
|
|
272
|
-
export function makePublicLog(
|
|
272
|
+
export function makePublicLog(
|
|
273
|
+
tag: Tag,
|
|
274
|
+
contractAddress: AztecAddress = AztecAddress.fromNumberUnsafe(543254),
|
|
275
|
+
): PublicLog {
|
|
273
276
|
return PublicLog.from({
|
|
274
277
|
contractAddress,
|
|
275
278
|
fields: new Array(10).fill(null).map((_, i) => (!i ? tag.value : new Fr(tag.value.toBigInt() + BigInt(i)))),
|
|
@@ -281,7 +284,7 @@ export function makePublicLogs(
|
|
|
281
284
|
blockNumber: number,
|
|
282
285
|
txIndex: number,
|
|
283
286
|
numLogsPerTx: number,
|
|
284
|
-
contractAddress: AztecAddress = AztecAddress.
|
|
287
|
+
contractAddress: AztecAddress = AztecAddress.fromNumberUnsafe(543254),
|
|
285
288
|
): PublicLog[] {
|
|
286
289
|
return times(numLogsPerTx, logIndex => {
|
|
287
290
|
const tag = makePublicLogTag(blockNumber, txIndex, logIndex);
|
|
@@ -7,7 +7,7 @@ import { Fr } from '@aztec/foundation/curves/bn254';
|
|
|
7
7
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
8
8
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
9
9
|
import type { FunctionsOf } from '@aztec/foundation/types';
|
|
10
|
-
import type { ArchiverEmitter, BlockHash } from '@aztec/stdlib/block';
|
|
10
|
+
import type { ArchiverEmitter, BlockHash, L2Block } from '@aztec/stdlib/block';
|
|
11
11
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
12
12
|
import type { BlockHeader } from '@aztec/stdlib/tx';
|
|
13
13
|
import { type TelemetryClient, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
|
|
@@ -21,6 +21,10 @@ import type { ArchiverL1Synchronizer } from '../modules/l1_synchronizer.js';
|
|
|
21
21
|
import type { ArchiverDataStores } from '../store/data_stores.js';
|
|
22
22
|
import { L2TipsCache } from '../store/l2_tips_cache.js';
|
|
23
23
|
|
|
24
|
+
type NoopL1ArchiverConfigOverrides = Partial<{
|
|
25
|
+
skipOrphanProposedBlockPruning: boolean;
|
|
26
|
+
}>;
|
|
27
|
+
|
|
24
28
|
/** Noop L1 synchronizer for testing without L1 connectivity. */
|
|
25
29
|
class NoopL1Synchronizer implements FunctionsOf<ArchiverL1Synchronizer> {
|
|
26
30
|
public readonly tracer: Tracer;
|
|
@@ -39,8 +43,8 @@ class NoopL1Synchronizer implements FunctionsOf<ArchiverL1Synchronizer> {
|
|
|
39
43
|
testEthereumNodeSynced(): Promise<void> {
|
|
40
44
|
return Promise.resolve();
|
|
41
45
|
}
|
|
42
|
-
syncFromL1(_initialSyncComplete: boolean): Promise<
|
|
43
|
-
return Promise.resolve();
|
|
46
|
+
syncFromL1(_initialSyncComplete: boolean): Promise<L2Block[]> {
|
|
47
|
+
return Promise.resolve([]);
|
|
44
48
|
}
|
|
45
49
|
}
|
|
46
50
|
|
|
@@ -58,6 +62,7 @@ export class NoopL1Archiver extends Archiver {
|
|
|
58
62
|
initialBlockHash: BlockHash,
|
|
59
63
|
l2TipsCache: L2TipsCache,
|
|
60
64
|
dateProvider: DateProvider = new DateProvider(),
|
|
65
|
+
configOverrides: NoopL1ArchiverConfigOverrides = {},
|
|
61
66
|
) {
|
|
62
67
|
// Create mocks for L1 clients
|
|
63
68
|
const publicClient = mock<ViemPublicClient>();
|
|
@@ -93,8 +98,11 @@ export class NoopL1Archiver extends Archiver {
|
|
|
93
98
|
maxAllowedEthClientDriftSeconds: 300,
|
|
94
99
|
ethereumAllowNoDebugHosts: true, // Skip trace validation
|
|
95
100
|
skipHistoricalLogsCheck: true, // Skip historical logs validation
|
|
96
|
-
|
|
97
|
-
|
|
101
|
+
checkpointProposalSyncGrace: 4,
|
|
102
|
+
orphanPruneNoProposalTolerance: 1,
|
|
103
|
+
skipOrphanProposedBlockPruning: true,
|
|
104
|
+
blockDuration: 2,
|
|
105
|
+
...configOverrides,
|
|
98
106
|
},
|
|
99
107
|
blobClient,
|
|
100
108
|
instrumentation,
|
|
@@ -128,6 +136,7 @@ export async function createNoopL1Archiver(
|
|
|
128
136
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
129
137
|
initialHeader: BlockHeader,
|
|
130
138
|
dateProvider?: DateProvider,
|
|
139
|
+
configOverrides?: NoopL1ArchiverConfigOverrides,
|
|
131
140
|
): Promise<NoopL1Archiver> {
|
|
132
141
|
const instrumentation = await ArchiverInstrumentation.new(telemetry, () => dataStores.db.estimateSize());
|
|
133
142
|
// Mirror the production factory: precompute the dynamic genesis block hash from the injected
|
|
@@ -144,5 +153,6 @@ export async function createNoopL1Archiver(
|
|
|
144
153
|
initialBlockHash,
|
|
145
154
|
l2TipsCache,
|
|
146
155
|
dateProvider,
|
|
156
|
+
configOverrides,
|
|
147
157
|
);
|
|
148
158
|
}
|