@aztec/archiver 5.0.0-rc.2 → 5.0.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/dest/archiver.d.ts +1 -1
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +28 -5
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +5 -0
- package/dest/factory.d.ts +8 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +31 -0
- 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/data_source_base.d.ts +1 -2
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +8 -25
- 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 +4 -3
- 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 +16 -2
- package/dest/modules/validation.d.ts +12 -8
- package/dest/modules/validation.d.ts.map +1 -1
- package/dest/modules/validation.js +4 -11
- package/dest/store/block_store.d.ts +13 -3
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +32 -4
- 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 +7 -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 +7 -1
- package/dest/test/fake_l1_state.js +3 -3
- package/dest/test/mock_l2_block_source.d.ts +1 -1
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +5 -0
- package/dest/test/noop_l1_archiver.d.ts +1 -1
- package/dest/test/noop_l1_archiver.d.ts.map +1 -1
- package/dest/test/noop_l1_archiver.js +1 -1
- package/package.json +14 -13
- package/src/archiver.ts +32 -6
- package/src/config.ts +8 -0
- package/src/factory.ts +34 -0
- package/src/l1/calldata_retriever.ts +13 -6
- package/src/l1/data_retrieval.ts +6 -0
- package/src/modules/data_source_base.ts +8 -26
- package/src/modules/data_store_updater.ts +4 -3
- package/src/modules/instrumentation.ts +15 -2
- package/src/modules/l1_synchronizer.ts +29 -4
- package/src/modules/validation.ts +15 -18
- package/src/store/block_store.ts +31 -5
- package/src/store/contract_class_store.ts +7 -1
- package/src/store/contract_instance_store.ts +7 -1
- package/src/test/fake_l1_state.ts +3 -3
- package/src/test/mock_l2_block_source.ts +7 -0
- package/src/test/noop_l1_archiver.ts +3 -3
|
@@ -16,7 +16,12 @@ import { retryTimes } from '@aztec/foundation/retry';
|
|
|
16
16
|
import { count } from '@aztec/foundation/string';
|
|
17
17
|
import { DateProvider, Timer, elapsed } from '@aztec/foundation/timer';
|
|
18
18
|
import { isDefined, isErrorClass } from '@aztec/foundation/types';
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
type ArchiverEmitter,
|
|
21
|
+
type L2Block,
|
|
22
|
+
L2BlockSourceEvents,
|
|
23
|
+
type ValidateCheckpointResult,
|
|
24
|
+
} from '@aztec/stdlib/block';
|
|
20
25
|
import {
|
|
21
26
|
Checkpoint,
|
|
22
27
|
type CheckpointData,
|
|
@@ -57,6 +62,8 @@ type RollupStatus = {
|
|
|
57
62
|
lastRetrievedCheckpoint?: PublishedCheckpoint;
|
|
58
63
|
/** Last checkpoint observed on L1 across both valid and rejected entries on this iteration */
|
|
59
64
|
lastSeenCheckpoint?: { checkpointNumber: CheckpointNumber; l1: L1PublishedData };
|
|
65
|
+
/** Blocks added while handling checkpoints this iteration, for the aggregate block source update event. */
|
|
66
|
+
blocksAdded: L2Block[];
|
|
60
67
|
};
|
|
61
68
|
|
|
62
69
|
/**
|
|
@@ -145,7 +152,9 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
145
152
|
}
|
|
146
153
|
|
|
147
154
|
@trackSpan('Archiver.syncFromL1')
|
|
148
|
-
public async syncFromL1(initialSyncComplete: boolean): Promise<
|
|
155
|
+
public async syncFromL1(initialSyncComplete: boolean): Promise<L2Block[]> {
|
|
156
|
+
const blocksAdded: L2Block[] = [];
|
|
157
|
+
|
|
149
158
|
// In between the various calls to L1, the block number can move meaning some of the following
|
|
150
159
|
// calls will return data for blocks that were not present during earlier calls. To combat this
|
|
151
160
|
// we ensure that all data retrieval methods only retrieve data up to the currentBlockNumber
|
|
@@ -158,7 +167,7 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
158
167
|
|
|
159
168
|
if (this.l1BlockHash && currentL1BlockHash.equals(this.l1BlockHash)) {
|
|
160
169
|
this.log.trace(`No new L1 blocks since last sync at L1 block ${this.l1BlockNumber}`);
|
|
161
|
-
return;
|
|
170
|
+
return blocksAdded;
|
|
162
171
|
}
|
|
163
172
|
|
|
164
173
|
// Log at error if the latest L1 block timestamp is too old
|
|
@@ -196,6 +205,7 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
196
205
|
// First we retrieve new checkpoints and L2 blocks and store them in the DB. This will also update the
|
|
197
206
|
// pending chain validation status, proven checkpoint number, and synched L1 block number.
|
|
198
207
|
const rollupStatus = await this.handleCheckpoints(blocksSynchedTo, currentL1BlockNumber, initialSyncComplete);
|
|
208
|
+
blocksAdded.push(...rollupStatus.blocksAdded);
|
|
199
209
|
|
|
200
210
|
// Then we try pruning uncheckpointed blocks if a new slot was mined without checkpoints
|
|
201
211
|
await this.pruneUncheckpointedBlocks(currentL1Timestamp);
|
|
@@ -237,6 +247,8 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
237
247
|
l1TimestampAtStart: currentL1Timestamp,
|
|
238
248
|
l1BlockNumberAtEnd,
|
|
239
249
|
});
|
|
250
|
+
|
|
251
|
+
return blocksAdded;
|
|
240
252
|
}
|
|
241
253
|
|
|
242
254
|
/** Updates the finalized checkpoint using the pre-fetched finalized L1 block from the current sync iteration. */
|
|
@@ -267,7 +279,7 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
267
279
|
}
|
|
268
280
|
|
|
269
281
|
/** Prune all proposed local blocks that should have been checkpointed by now. */
|
|
270
|
-
private async pruneUncheckpointedBlocks(currentL1Timestamp: bigint) {
|
|
282
|
+
private async pruneUncheckpointedBlocks(currentL1Timestamp: bigint): Promise<void> {
|
|
271
283
|
const [lastCheckpointedBlockNumber, lastProposedBlockNumber] = await Promise.all([
|
|
272
284
|
this.stores.blocks.getCheckpointedL2BlockNumber(),
|
|
273
285
|
this.stores.blocks.getLatestL2BlockNumber(),
|
|
@@ -302,6 +314,7 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
302
314
|
|
|
303
315
|
const prunedBlocks = await this.updater.removeUncheckpointedBlocksAfter(lastCheckpointedBlockNumber);
|
|
304
316
|
if (prunedBlocks.length > 0) {
|
|
317
|
+
this.instrumentation.recordPrune('uncheckpointed');
|
|
305
318
|
this.events.emit(L2BlockSourceEvents.L2PruneUncheckpointed, {
|
|
306
319
|
type: L2BlockSourceEvents.L2PruneUncheckpointed,
|
|
307
320
|
slotNumber: firstUncheckpointedBlockSlot,
|
|
@@ -622,6 +635,7 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
622
635
|
currentL1BlockNumber: bigint,
|
|
623
636
|
initialSyncComplete: boolean,
|
|
624
637
|
): Promise<RollupStatus> {
|
|
638
|
+
const blocksAdded: L2Block[] = [];
|
|
625
639
|
const localPendingCheckpointNumber = await this.stores.blocks.getLatestCheckpointNumber();
|
|
626
640
|
const initialValidationResult: ValidateCheckpointResult | undefined =
|
|
627
641
|
await this.stores.blocks.getPendingChainValidationStatus();
|
|
@@ -640,6 +654,7 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
640
654
|
pendingCheckpointNumber,
|
|
641
655
|
pendingArchive: pendingArchive.toString(),
|
|
642
656
|
validationResult: initialValidationResult,
|
|
657
|
+
blocksAdded,
|
|
643
658
|
};
|
|
644
659
|
this.log.trace(`Retrieved rollup status at current L1 block ${currentL1BlockNumber}.`, {
|
|
645
660
|
localPendingCheckpointNumber,
|
|
@@ -782,6 +797,9 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
782
797
|
|
|
783
798
|
const checkpointsToRemove = localPendingCheckpointNumber - tipAfterUnwind;
|
|
784
799
|
await this.updater.removeCheckpointsAfter(CheckpointNumber(tipAfterUnwind));
|
|
800
|
+
if (checkpointsToRemove > 0) {
|
|
801
|
+
this.instrumentation.recordPrune('l1_mismatch');
|
|
802
|
+
}
|
|
785
803
|
|
|
786
804
|
this.log.warn(
|
|
787
805
|
`Removed ${count(checkpointsToRemove, 'checkpoint')} after checkpoint ${tipAfterUnwind} ` +
|
|
@@ -1067,6 +1085,11 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
1067
1085
|
);
|
|
1068
1086
|
}
|
|
1069
1087
|
|
|
1088
|
+
// Record blocks newly fetched from L1 checkpoint payloads as added. The promoted checkpoint (if any) is
|
|
1089
|
+
// excluded: its blocks were already in local archiver storage (added via the proposed-block path) so the
|
|
1090
|
+
// block stream does not need them re-downloaded.
|
|
1091
|
+
blocksAdded.push(...checkpointsToAdd.flatMap(c => c.checkpoint.blocks));
|
|
1092
|
+
|
|
1070
1093
|
// If blocks were pruned due to conflict with L1 checkpoints, emit event
|
|
1071
1094
|
if (result.prunedBlocks && result.prunedBlocks.length > 0) {
|
|
1072
1095
|
const prunedCheckpointNumber = result.prunedBlocks[0].checkpointNumber;
|
|
@@ -1077,6 +1100,8 @@ export class ArchiverL1Synchronizer implements Traceable {
|
|
|
1077
1100
|
{ prunedBlocks: result.prunedBlocks.map(b => b.toBlockInfo()), prunedSlotNumber, prunedCheckpointNumber },
|
|
1078
1101
|
);
|
|
1079
1102
|
|
|
1103
|
+
this.instrumentation.recordPrune('l1_conflict');
|
|
1104
|
+
|
|
1080
1105
|
// Emit event for listening services to react to the prune.
|
|
1081
1106
|
// Note: slotNumber comes from the first pruned block. If pruned blocks theoretically spanned multiple slots,
|
|
1082
1107
|
// only one slot number would be reported (though in practice all blocks in a checkpoint span a single slot).
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { EpochCache } from '@aztec/epoch-cache';
|
|
2
|
+
import type { ViemCommitteeAttestations } from '@aztec/ethereum/contracts';
|
|
2
3
|
import { type CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
3
4
|
import { compactArray } from '@aztec/foundation/collection';
|
|
4
5
|
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
@@ -29,22 +30,6 @@ export function getAttestationInfoFromPublishedCheckpoint(
|
|
|
29
30
|
return getAttestationInfoFromPayload(payload, attestations);
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
/**
|
|
33
|
-
* Validates the attestations of a checkpoint already retrieved (with its blocks) from blobs.
|
|
34
|
-
* Returns true if the attestations are valid and sufficient, false otherwise.
|
|
35
|
-
*/
|
|
36
|
-
export function validateCheckpointAttestations(
|
|
37
|
-
publishedCheckpoint: PublishedCheckpoint,
|
|
38
|
-
epochCache: EpochCache,
|
|
39
|
-
constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
40
|
-
signatureContext: CoordinationSignatureContext,
|
|
41
|
-
logger?: Logger,
|
|
42
|
-
): Promise<ValidateCheckpointResult> {
|
|
43
|
-
const { checkpoint, attestations } = publishedCheckpoint;
|
|
44
|
-
const payload = ConsensusPayload.fromCheckpoint(checkpoint, signatureContext);
|
|
45
|
-
return validateAttestations(payload, attestations, checkpoint.toCheckpointInfo(), epochCache, constants, logger);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
33
|
/** The subset of a calldata-only checkpoint needed to validate its committee attestations. */
|
|
49
34
|
export type CalldataCheckpointForAttestations = {
|
|
50
35
|
checkpointNumber: CheckpointNumber;
|
|
@@ -52,6 +37,8 @@ export type CalldataCheckpointForAttestations = {
|
|
|
52
37
|
feeAssetPriceModifier: bigint;
|
|
53
38
|
header: CheckpointHeader;
|
|
54
39
|
attestations: CommitteeAttestation[];
|
|
40
|
+
/** The exact packed attestations tuple from L1 calldata, carried verbatim for byte-faithful invalidation. */
|
|
41
|
+
verbatimAttestations: ViemCommitteeAttestations;
|
|
55
42
|
};
|
|
56
43
|
|
|
57
44
|
/**
|
|
@@ -80,7 +67,15 @@ export function validateCheckpointAttestationsFromCalldata(
|
|
|
80
67
|
checkpointNumber: checkpoint.checkpointNumber,
|
|
81
68
|
timestamp: checkpoint.header.timestamp,
|
|
82
69
|
};
|
|
83
|
-
return validateAttestations(
|
|
70
|
+
return validateAttestations(
|
|
71
|
+
payload,
|
|
72
|
+
checkpoint.attestations,
|
|
73
|
+
checkpoint.verbatimAttestations,
|
|
74
|
+
checkpointInfo,
|
|
75
|
+
epochCache,
|
|
76
|
+
constants,
|
|
77
|
+
logger,
|
|
78
|
+
);
|
|
84
79
|
}
|
|
85
80
|
|
|
86
81
|
/**
|
|
@@ -88,9 +83,10 @@ export function validateCheckpointAttestationsFromCalldata(
|
|
|
88
83
|
* independent of whether the checkpoint's blocks have been decoded from blobs. Returns true if the
|
|
89
84
|
* attestations are valid and sufficient, false otherwise.
|
|
90
85
|
*/
|
|
91
|
-
async function validateAttestations(
|
|
86
|
+
export async function validateAttestations(
|
|
92
87
|
payload: ConsensusPayload,
|
|
93
88
|
attestations: CommitteeAttestation[],
|
|
89
|
+
verbatimAttestations: ViemCommitteeAttestations,
|
|
94
90
|
checkpointInfo: CheckpointInfo,
|
|
95
91
|
epochCache: EpochCache,
|
|
96
92
|
constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
@@ -137,6 +133,7 @@ async function validateAttestations(
|
|
|
137
133
|
epoch,
|
|
138
134
|
attestors,
|
|
139
135
|
attestations,
|
|
136
|
+
verbatimAttestations,
|
|
140
137
|
});
|
|
141
138
|
|
|
142
139
|
for (let i = 0; i < attestorInfos.length; i++) {
|
package/src/store/block_store.ts
CHANGED
|
@@ -306,12 +306,18 @@ export class BlockStore {
|
|
|
306
306
|
|
|
307
307
|
/**
|
|
308
308
|
* Append new checkpoints to the store's list.
|
|
309
|
+
* Checkpoints at the start of the batch that are already stored (e.g. re-included by an L1 reorg)
|
|
310
|
+
* are accepted if their archive root matches: their L1 metadata is updated but they are not
|
|
311
|
+
* re-inserted, and they are excluded from the returned array.
|
|
309
312
|
* @param checkpoints - The L2 checkpoints to be added to the store.
|
|
310
|
-
* @returns
|
|
313
|
+
* @returns The checkpoints that were actually inserted (excluding already-stored ones).
|
|
311
314
|
*/
|
|
312
|
-
async addCheckpoints(
|
|
315
|
+
async addCheckpoints(
|
|
316
|
+
checkpoints: PublishedCheckpoint[],
|
|
317
|
+
opts: { force?: boolean } = {},
|
|
318
|
+
): Promise<PublishedCheckpoint[]> {
|
|
313
319
|
if (checkpoints.length === 0) {
|
|
314
|
-
return
|
|
320
|
+
return [];
|
|
315
321
|
}
|
|
316
322
|
|
|
317
323
|
return await this.db.transactionAsync(async () => {
|
|
@@ -324,7 +330,7 @@ export class BlockStore {
|
|
|
324
330
|
if (!opts.force && firstCheckpointNumber <= previousCheckpointNumber) {
|
|
325
331
|
checkpoints = await this.skipOrUpdateAlreadyStoredCheckpoints(checkpoints, previousCheckpointNumber);
|
|
326
332
|
if (checkpoints.length === 0) {
|
|
327
|
-
return
|
|
333
|
+
return [];
|
|
328
334
|
}
|
|
329
335
|
// Re-check sequentiality after skipping
|
|
330
336
|
const newFirstNumber = checkpoints[0].checkpoint.number;
|
|
@@ -387,7 +393,7 @@ export class BlockStore {
|
|
|
387
393
|
}
|
|
388
394
|
|
|
389
395
|
await this.advanceSynchedL1BlockNumber(checkpoints[checkpoints.length - 1].l1.blockNumber);
|
|
390
|
-
return
|
|
396
|
+
return checkpoints;
|
|
391
397
|
});
|
|
392
398
|
}
|
|
393
399
|
|
|
@@ -621,6 +627,26 @@ export class BlockStore {
|
|
|
621
627
|
return checkpoints;
|
|
622
628
|
}
|
|
623
629
|
|
|
630
|
+
/**
|
|
631
|
+
* Returns up to `limit` checkpoints anchored at `fromSlot`, ordered nearest-first, walking the slot index.
|
|
632
|
+
* With `reverse`, takes the checkpoints at or before `fromSlot` (descending by slot); otherwise the
|
|
633
|
+
* checkpoints at or after it (ascending). `limit: 1, reverse: true` yields the latest checkpoint at or
|
|
634
|
+
* before the slot in a single range scan.
|
|
635
|
+
*/
|
|
636
|
+
async getCheckpointsBySlot(fromSlot: SlotNumber, limit: number, reverse: boolean): Promise<CheckpointData[]> {
|
|
637
|
+
// The KV range bounds are direction-dependent: forward is [start, end), reverse is (start, end], so a
|
|
638
|
+
// reverse scan uses `end: fromSlot` (inclusive) with no +1 to include the checkpoint at fromSlot itself.
|
|
639
|
+
const range = reverse ? { end: fromSlot, reverse: true, limit } : { start: fromSlot, limit };
|
|
640
|
+
const result: CheckpointData[] = [];
|
|
641
|
+
for await (const [, checkpointNumber] of this.#slotToCheckpoint.entriesAsync(range)) {
|
|
642
|
+
const checkpointStorage = await this.#checkpoints.getAsync(checkpointNumber);
|
|
643
|
+
if (checkpointStorage) {
|
|
644
|
+
result.push(this.checkpointDataFromCheckpointStorage(checkpointStorage));
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return result;
|
|
648
|
+
}
|
|
649
|
+
|
|
624
650
|
/** Returns checkpoint data for all checkpoints whose slot falls within the given range (inclusive). */
|
|
625
651
|
async getCheckpointDataForSlotRange(startSlot: SlotNumber, endSlot: SlotNumber): Promise<CheckpointData[]> {
|
|
626
652
|
const result: CheckpointData[] = [];
|
|
@@ -50,13 +50,19 @@ export class ContractClassStore {
|
|
|
50
50
|
): Promise<void> {
|
|
51
51
|
await this.db.transactionAsync(async () => {
|
|
52
52
|
const key = contractClass.id.toString();
|
|
53
|
-
|
|
53
|
+
const existing = await this.#contractClasses.getAsync(key);
|
|
54
|
+
if (existing !== undefined) {
|
|
54
55
|
// Protocol contracts are preloaded at block 0, so a later on-chain (re-)publish of a bundled
|
|
55
56
|
// protocol class id is valid and must be a no-op. Keep the existing block-0 entry untouched
|
|
56
57
|
// (do not bump its block number) so it survives reorgs of the publishing block.
|
|
57
58
|
if (isProtocolContractClass(contractClass.id)) {
|
|
58
59
|
return;
|
|
59
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
|
+
}
|
|
60
66
|
throw new Error(`Contract class ${key} already exists, cannot add again at block ${blockNumber}`);
|
|
61
67
|
}
|
|
62
68
|
await this.#contractClasses.set(
|
|
@@ -78,8 +78,14 @@ export class ContractInstanceStore {
|
|
|
78
78
|
if (isProtocolContract(contractInstance.address)) {
|
|
79
79
|
return;
|
|
80
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
|
+
}
|
|
81
87
|
throw new Error(
|
|
82
|
-
`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}`,
|
|
83
89
|
);
|
|
84
90
|
}
|
|
85
91
|
await this.#contractInstances.set(key, new SerializableContractInstance(contractInstance).toBuffer());
|
|
@@ -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)
|
|
@@ -323,6 +323,13 @@ export class MockL2BlockSource implements L2BlockSource, ContractDataSource {
|
|
|
323
323
|
if ('from' in query) {
|
|
324
324
|
return this.checkpointList.slice(query.from - 1, query.from - 1 + query.limit);
|
|
325
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
|
+
}
|
|
326
333
|
return this.getCheckpointsInEpoch(query.epoch);
|
|
327
334
|
}
|
|
328
335
|
|
|
@@ -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';
|
|
@@ -43,8 +43,8 @@ class NoopL1Synchronizer implements FunctionsOf<ArchiverL1Synchronizer> {
|
|
|
43
43
|
testEthereumNodeSynced(): Promise<void> {
|
|
44
44
|
return Promise.resolve();
|
|
45
45
|
}
|
|
46
|
-
syncFromL1(_initialSyncComplete: boolean): Promise<
|
|
47
|
-
return Promise.resolve();
|
|
46
|
+
syncFromL1(_initialSyncComplete: boolean): Promise<L2Block[]> {
|
|
47
|
+
return Promise.resolve([]);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|