@aztec/archiver 0.0.1-commit.0dc957cde → 0.0.1-commit.0ec55a70b
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 +15 -9
- package/dest/archiver.d.ts.map +1 -1
- package/dest/archiver.js +85 -53
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +2 -2
- package/dest/errors.d.ts +16 -5
- package/dest/errors.d.ts.map +1 -1
- package/dest/errors.js +29 -6
- package/dest/factory.d.ts +4 -4
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +11 -9
- package/dest/index.d.ts +8 -2
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +7 -1
- package/dest/l1/calldata_retriever.d.ts +2 -1
- package/dest/l1/calldata_retriever.d.ts.map +1 -1
- package/dest/l1/calldata_retriever.js +9 -4
- package/dest/modules/contract_data_source_adapter.d.ts +25 -0
- package/dest/modules/contract_data_source_adapter.d.ts.map +1 -0
- package/dest/modules/contract_data_source_adapter.js +42 -0
- package/dest/modules/data_source_base.d.ts +16 -10
- package/dest/modules/data_source_base.d.ts.map +1 -1
- package/dest/modules/data_source_base.js +71 -60
- package/dest/modules/data_store_updater.d.ts +6 -6
- package/dest/modules/data_store_updater.d.ts.map +1 -1
- package/dest/modules/data_store_updater.js +42 -40
- package/dest/modules/l1_synchronizer.d.ts +5 -4
- package/dest/modules/l1_synchronizer.d.ts.map +1 -1
- package/dest/modules/l1_synchronizer.js +79 -54
- package/dest/modules/validation.d.ts +4 -3
- package/dest/modules/validation.d.ts.map +1 -1
- package/dest/modules/validation.js +4 -4
- package/dest/store/block_store.d.ts +58 -27
- package/dest/store/block_store.d.ts.map +1 -1
- package/dest/store/block_store.js +152 -75
- package/dest/store/contract_class_store.d.ts +17 -3
- package/dest/store/contract_class_store.d.ts.map +1 -1
- package/dest/store/contract_class_store.js +17 -1
- package/dest/store/contract_instance_store.d.ts +28 -1
- package/dest/store/contract_instance_store.d.ts.map +1 -1
- package/dest/store/contract_instance_store.js +31 -0
- package/dest/store/data_stores.d.ts +68 -0
- package/dest/store/data_stores.d.ts.map +1 -0
- package/dest/store/data_stores.js +50 -0
- package/dest/store/function_names_cache.d.ts +17 -0
- package/dest/store/function_names_cache.d.ts.map +1 -0
- package/dest/store/function_names_cache.js +30 -0
- package/dest/store/l2_tips_cache.js +1 -1
- package/dest/test/fake_l1_state.d.ts +2 -1
- package/dest/test/fake_l1_state.d.ts.map +1 -1
- package/dest/test/fake_l1_state.js +25 -8
- package/dest/test/mock_l2_block_source.d.ts +12 -3
- package/dest/test/mock_l2_block_source.d.ts.map +1 -1
- package/dest/test/mock_l2_block_source.js +24 -2
- package/dest/test/noop_l1_archiver.d.ts +4 -4
- package/dest/test/noop_l1_archiver.d.ts.map +1 -1
- package/dest/test/noop_l1_archiver.js +5 -5
- package/package.json +13 -13
- package/src/archiver.ts +91 -49
- package/src/config.ts +2 -1
- package/src/errors.ts +41 -8
- package/src/factory.ts +10 -10
- package/src/index.ts +15 -1
- package/src/l1/calldata_retriever.ts +15 -4
- package/src/modules/contract_data_source_adapter.ts +59 -0
- package/src/modules/data_source_base.ts +75 -57
- package/src/modules/data_store_updater.ts +46 -38
- package/src/modules/l1_synchronizer.ts +92 -60
- package/src/modules/validation.ts +8 -7
- package/src/store/block_store.ts +159 -80
- package/src/store/contract_class_store.ts +28 -2
- package/src/store/contract_instance_store.ts +43 -0
- package/src/store/data_stores.ts +108 -0
- package/src/store/function_names_cache.ts +37 -0
- package/src/store/l2_tips_cache.ts +1 -1
- package/src/test/fake_l1_state.ts +24 -14
- package/src/test/mock_l2_block_source.ts +23 -2
- package/src/test/noop_l1_archiver.ts +6 -6
- package/dest/store/kv_archiver_store.d.ts +0 -383
- package/dest/store/kv_archiver_store.d.ts.map +0 -1
- package/dest/store/kv_archiver_store.js +0 -501
- package/src/store/kv_archiver_store.ts +0 -728
|
@@ -377,6 +377,7 @@ import { maxBigint } from '@aztec/foundation/bigint';
|
|
|
377
377
|
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
378
378
|
import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
|
|
379
379
|
import { partition, pick } from '@aztec/foundation/collection';
|
|
380
|
+
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
380
381
|
import { createLogger } from '@aztec/foundation/log';
|
|
381
382
|
import { retryTimes } from '@aztec/foundation/retry';
|
|
382
383
|
import { count } from '@aztec/foundation/string';
|
|
@@ -389,6 +390,7 @@ import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
|
|
|
389
390
|
import { execInSpan, trackSpan } from '@aztec/telemetry-client';
|
|
390
391
|
import { InitialCheckpointNumberNotSequentialError } from '../errors.js';
|
|
391
392
|
import { getCheckpointBlobDataFromBlobs, retrieveCheckpointCalldataFromRollup, retrieveL1ToL2Message, retrieveL1ToL2Messages, retrievedToPublishedCheckpoint } from '../l1/data_retrieval.js';
|
|
393
|
+
import { getArchiverSynchPoint } from '../store/data_stores.js';
|
|
392
394
|
import { MessageStoreError } from '../store/message_store.js';
|
|
393
395
|
import { ArchiverDataStoreUpdater } from './data_store_updater.js';
|
|
394
396
|
import { validateCheckpointAttestations } from './validation.js';
|
|
@@ -401,7 +403,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
401
403
|
debugClient;
|
|
402
404
|
rollup;
|
|
403
405
|
inbox;
|
|
404
|
-
|
|
406
|
+
stores;
|
|
405
407
|
config;
|
|
406
408
|
blobClient;
|
|
407
409
|
epochCache;
|
|
@@ -439,12 +441,12 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
439
441
|
l1Timestamp;
|
|
440
442
|
updater;
|
|
441
443
|
tracer;
|
|
442
|
-
constructor(publicClient, debugClient, rollup, inbox,
|
|
444
|
+
constructor(publicClient, debugClient, rollup, inbox, stores, config, blobClient, epochCache, dateProvider, instrumentation, l1Constants, events, tracer, l2TipsCache, log = createLogger('archiver:l1-sync')){
|
|
443
445
|
this.publicClient = publicClient;
|
|
444
446
|
this.debugClient = debugClient;
|
|
445
447
|
this.rollup = rollup;
|
|
446
448
|
this.inbox = inbox;
|
|
447
|
-
this.
|
|
449
|
+
this.stores = stores;
|
|
448
450
|
this.config = config;
|
|
449
451
|
this.blobClient = blobClient;
|
|
450
452
|
this.epochCache = epochCache;
|
|
@@ -454,7 +456,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
454
456
|
this.events = events;
|
|
455
457
|
this.log = log;
|
|
456
458
|
_initProto(this);
|
|
457
|
-
this.updater = new ArchiverDataStoreUpdater(this.
|
|
459
|
+
this.updater = new ArchiverDataStoreUpdater(this.stores, l2TipsCache, {
|
|
458
460
|
rollupManaLimit: l1Constants.rollupManaLimit
|
|
459
461
|
});
|
|
460
462
|
this.tracer = tracer;
|
|
@@ -468,6 +470,12 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
468
470
|
/** Returns the last L1 timestamp that was synced. */ getL1Timestamp() {
|
|
469
471
|
return this.l1Timestamp;
|
|
470
472
|
}
|
|
473
|
+
getSignatureContext() {
|
|
474
|
+
return {
|
|
475
|
+
chainId: this.publicClient.chain.id,
|
|
476
|
+
rollupAddress: EthAddress.fromString(this.rollup.address)
|
|
477
|
+
};
|
|
478
|
+
}
|
|
471
479
|
/** Checks that the ethereum node we are connected to has a latest timestamp no more than the allowed drift. Throw if not. */ async testEthereumNodeSynced() {
|
|
472
480
|
const maxAllowedDelay = this.config.maxAllowedEthClientDriftSeconds;
|
|
473
481
|
if (maxAllowedDelay === 0) {
|
|
@@ -512,7 +520,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
512
520
|
});
|
|
513
521
|
}
|
|
514
522
|
// Load sync point for blocks defaulting to start block
|
|
515
|
-
const { blocksSynchedTo = this.l1Constants.l1StartBlock } = await this.
|
|
523
|
+
const { blocksSynchedTo = this.l1Constants.l1StartBlock } = await getArchiverSynchPoint(this.stores);
|
|
516
524
|
this.log.debug(`Starting new archiver sync iteration`, {
|
|
517
525
|
blocksSynchedTo,
|
|
518
526
|
currentL1BlockData
|
|
@@ -537,7 +545,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
537
545
|
// past it, since otherwise we'll keep downloading it and reprocessing it on every iteration until
|
|
538
546
|
// we get a valid checkpoint to advance the syncpoint.
|
|
539
547
|
if (!rollupStatus.validationResult?.valid && rollupStatus.lastL1BlockWithCheckpoint !== undefined) {
|
|
540
|
-
await this.
|
|
548
|
+
await this.stores.blocks.setSynchedL1BlockNumber(rollupStatus.lastL1BlockWithCheckpoint);
|
|
541
549
|
}
|
|
542
550
|
// And lastly we check if we are missing any checkpoints behind us due to a possible L1 reorg.
|
|
543
551
|
// We only do this if rollup cant prune on the next submission. Otherwise we will end up
|
|
@@ -574,7 +582,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
574
582
|
const finalizedCheckpointNumber = await this.rollup.getProvenCheckpointNumber({
|
|
575
583
|
blockNumber: finalizedL1BlockNumber
|
|
576
584
|
});
|
|
577
|
-
const localFinalizedCheckpointNumber = await this.
|
|
585
|
+
const localFinalizedCheckpointNumber = await this.stores.blocks.getFinalizedCheckpointNumber();
|
|
578
586
|
if (localFinalizedCheckpointNumber !== finalizedCheckpointNumber) {
|
|
579
587
|
await this.updater.setFinalizedCheckpointNumber(finalizedCheckpointNumber);
|
|
580
588
|
this.log.info(`Updated finalized chain to checkpoint ${finalizedCheckpointNumber}`, {
|
|
@@ -591,8 +599,8 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
591
599
|
}
|
|
592
600
|
/** Prune all proposed local blocks that should have been checkpointed by now. */ async pruneUncheckpointedBlocks(currentL1Timestamp) {
|
|
593
601
|
const [lastCheckpointedBlockNumber, lastProposedBlockNumber] = await Promise.all([
|
|
594
|
-
this.
|
|
595
|
-
this.
|
|
602
|
+
this.stores.blocks.getCheckpointedL2BlockNumber(),
|
|
603
|
+
this.stores.blocks.getLatestL2BlockNumber()
|
|
596
604
|
]);
|
|
597
605
|
// If there are no uncheckpointed blocks, we got nothing to do
|
|
598
606
|
if (lastProposedBlockNumber === lastCheckpointedBlockNumber) {
|
|
@@ -603,7 +611,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
603
611
|
const slotAtNextL1Block = getSlotAtNextL1Block(currentL1Timestamp, this.l1Constants);
|
|
604
612
|
const firstUncheckpointedBlockNumber = BlockNumber(lastCheckpointedBlockNumber + 1);
|
|
605
613
|
// What's the slot of the first uncheckpointed block?
|
|
606
|
-
const [firstUncheckpointedBlockHeader] = await this.
|
|
614
|
+
const [firstUncheckpointedBlockHeader] = await this.stores.blocks.getBlockHeaders(firstUncheckpointedBlockNumber, 1);
|
|
607
615
|
const firstUncheckpointedBlockSlot = firstUncheckpointedBlockHeader?.getSlot();
|
|
608
616
|
if (firstUncheckpointedBlockSlot === undefined || firstUncheckpointedBlockSlot >= slotAtNextL1Block) {
|
|
609
617
|
return;
|
|
@@ -639,7 +647,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
639
647
|
}
|
|
640
648
|
/** Checks if there'd be a reorg for the next checkpoint submission and start pruning now. */ async handleEpochPrune(provenCheckpointNumber, currentL1BlockNumber, currentL1Timestamp) {
|
|
641
649
|
const rollupCanPrune = await this.canPrune(currentL1BlockNumber, currentL1Timestamp);
|
|
642
|
-
const localPendingCheckpointNumber = await this.
|
|
650
|
+
const localPendingCheckpointNumber = await this.stores.blocks.getLatestCheckpointNumber();
|
|
643
651
|
const canPrune = localPendingCheckpointNumber > provenCheckpointNumber && rollupCanPrune;
|
|
644
652
|
if (canPrune) {
|
|
645
653
|
const timer = new Timer();
|
|
@@ -657,8 +665,8 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
657
665
|
const indices = Array.from({
|
|
658
666
|
length: checkpointsToUnwind
|
|
659
667
|
}, (_, i)=>CheckpointNumber(i + pruneFrom));
|
|
660
|
-
const checkpoints = (await asyncPool(BATCH_SIZE, indices, (idx)=>this.
|
|
661
|
-
const newBlocks = (await asyncPool(BATCH_SIZE, checkpoints, (cp)=>this.
|
|
668
|
+
const checkpoints = (await asyncPool(BATCH_SIZE, indices, (idx)=>this.stores.blocks.getCheckpointData(idx))).filter(isDefined);
|
|
669
|
+
const newBlocks = (await asyncPool(BATCH_SIZE, checkpoints, (cp)=>this.stores.blocks.getBlocksForCheckpoint(CheckpointNumber(cp.checkpointNumber)))).filter(isDefined).flat();
|
|
662
670
|
// Emit an event for listening services to react to the chain prune
|
|
663
671
|
this.events.emit(L2BlockSourceEvents.L2PruneUnproven, {
|
|
664
672
|
type: L2BlockSourceEvents.L2PruneUnproven,
|
|
@@ -667,11 +675,11 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
667
675
|
});
|
|
668
676
|
this.log.debug(`L2 prune from ${provenCheckpointNumber + 1} to ${localPendingCheckpointNumber} will occur on next checkpoint submission.`);
|
|
669
677
|
await this.updater.removeCheckpointsAfter(provenCheckpointNumber);
|
|
670
|
-
this.log.warn(`Removed ${count(checkpointsToUnwind, 'checkpoint')} after checkpoint ${provenCheckpointNumber} ` + `due to predicted reorg at L1 block ${currentL1BlockNumber}. ` + `Updated latest checkpoint is ${await this.
|
|
678
|
+
this.log.warn(`Removed ${count(checkpointsToUnwind, 'checkpoint')} after checkpoint ${provenCheckpointNumber} ` + `due to predicted reorg at L1 block ${currentL1BlockNumber}. ` + `Updated latest checkpoint is ${await this.stores.blocks.getLatestCheckpointNumber()}.`);
|
|
671
679
|
this.instrumentation.processPrune(timer.ms());
|
|
672
680
|
// TODO(palla/reorg): Do we need to set the block synched L1 block number here?
|
|
673
681
|
// Seems like the next iteration should handle this.
|
|
674
|
-
// await this.
|
|
682
|
+
// await this.stores.blocks.setSynchedL1BlockNumber(currentL1BlockNumber);
|
|
675
683
|
}
|
|
676
684
|
return {
|
|
677
685
|
rollupCanPrune
|
|
@@ -697,7 +705,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
697
705
|
const { messagesSynchedTo = {
|
|
698
706
|
l1BlockNumber: this.l1Constants.l1StartBlock,
|
|
699
707
|
l1BlockHash: this.l1Constants.l1StartBlockHash
|
|
700
|
-
} } = await this.
|
|
708
|
+
} } = await getArchiverSynchPoint(this.stores);
|
|
701
709
|
// Nothing to do if L1 block number has not moved forward
|
|
702
710
|
const currentL1BlockNumber = currentL1Block.l1BlockNumber;
|
|
703
711
|
if (currentL1BlockNumber <= messagesSynchedTo.l1BlockNumber) {
|
|
@@ -707,10 +715,10 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
707
715
|
const remoteMessagesState = await this.inbox.getState({
|
|
708
716
|
blockNumber: currentL1BlockNumber
|
|
709
717
|
});
|
|
710
|
-
const localLastMessage = await this.
|
|
718
|
+
const localLastMessage = await this.stores.messages.getLastMessage();
|
|
711
719
|
if (await this.localStateMatches(localLastMessage, remoteMessagesState)) {
|
|
712
720
|
this.log.trace(`Local L1 to L2 messages are already in sync with remote at L1 block ${currentL1BlockNumber}`);
|
|
713
|
-
await this.
|
|
721
|
+
await this.stores.messages.setMessageSyncState(currentL1Block, remoteMessagesState.treeInProgress);
|
|
714
722
|
return true;
|
|
715
723
|
}
|
|
716
724
|
// If not, then we are out of sync. Most likely there are new messages on the inbox, so we try retrieving them.
|
|
@@ -732,7 +740,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
732
740
|
// Note that, if there are no new messages to insert, but there was an L1 reorg that pruned out last messages,
|
|
733
741
|
// we'd notice by comparing our local state with the remote one again, and seeing they don't match even after
|
|
734
742
|
// our sync attempt. In this case, we also rollback our syncpoint, and trigger a retry.
|
|
735
|
-
const localLastMessageAfterSync = await this.
|
|
743
|
+
const localLastMessageAfterSync = await this.stores.messages.getLastMessage();
|
|
736
744
|
if (!await this.localStateMatches(localLastMessageAfterSync, remoteMessagesState)) {
|
|
737
745
|
this.log.warn(`Local L1 to L2 messages state does not match remote after sync attempt. Rolling back syncpoint to retry.`, {
|
|
738
746
|
localLastMessageAfterSync,
|
|
@@ -742,11 +750,11 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
742
750
|
return false;
|
|
743
751
|
}
|
|
744
752
|
// Advance the syncpoint after a successful sync
|
|
745
|
-
await this.
|
|
753
|
+
await this.stores.messages.setMessageSyncState(currentL1Block, remoteMessagesState.treeInProgress);
|
|
746
754
|
return true;
|
|
747
755
|
}
|
|
748
756
|
/** Checks if the local rolling hash and message count matches the remote state */ async localStateMatches(localLastMessage, remoteState) {
|
|
749
|
-
const localMessageCount = await this.
|
|
757
|
+
const localMessageCount = await this.stores.messages.getTotalL1ToL2MessageCount();
|
|
750
758
|
this.log.trace(`Comparing local and remote inbox state`, {
|
|
751
759
|
localMessageCount,
|
|
752
760
|
localLastMessage,
|
|
@@ -764,7 +772,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
764
772
|
this.log.trace(`Retrieving L1 to L2 messages in L1 blocks ${searchStartBlock}-${searchEndBlock}`);
|
|
765
773
|
const messages = await retrieveL1ToL2Messages(this.inbox, searchStartBlock, searchEndBlock);
|
|
766
774
|
const timer = new Timer();
|
|
767
|
-
await this.
|
|
775
|
+
await this.stores.messages.addL1ToL2Messages(messages);
|
|
768
776
|
const perMsg = timer.ms() / messages.length;
|
|
769
777
|
this.instrumentation.processNewMessages(messages.length, perMsg);
|
|
770
778
|
for (const msg of messages){
|
|
@@ -794,7 +802,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
794
802
|
let commonMsg;
|
|
795
803
|
let messagesToDelete = 0;
|
|
796
804
|
this.log.verbose(`Searching most recent common L1 to L2 message`);
|
|
797
|
-
for await (const localMsg of this.
|
|
805
|
+
for await (const localMsg of this.stores.messages.iterateL1ToL2Messages({
|
|
798
806
|
reverse: true
|
|
799
807
|
})){
|
|
800
808
|
const logCtx = {
|
|
@@ -834,7 +842,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
834
842
|
if (messagesToDelete > 0) {
|
|
835
843
|
const lastGoodIndex = commonMsg?.index;
|
|
836
844
|
this.log.warn(`Rolling back all local L1 to L2 messages after index ${lastGoodIndex ?? 'initial'}`);
|
|
837
|
-
await this.
|
|
845
|
+
await this.stores.messages.removeL1ToL2Messages(lastGoodIndex !== undefined ? lastGoodIndex + 1n : 0n);
|
|
838
846
|
}
|
|
839
847
|
// Update the syncpoint so the loop below reprocesses the changed messages. We go to the block before
|
|
840
848
|
// the last common one, so we force reprocessing it, in case new messages were added on that same L1 block
|
|
@@ -845,7 +853,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
845
853
|
l1BlockNumber: syncPointL1BlockNumber,
|
|
846
854
|
l1BlockHash: syncPointL1BlockHash
|
|
847
855
|
};
|
|
848
|
-
await this.
|
|
856
|
+
await this.stores.messages.setMessageSyncState(messagesSyncPoint, remoteTreeInProgress);
|
|
849
857
|
this.log.verbose(`Updated messages syncpoint to L1 block ${syncPointL1BlockNumber}`, {
|
|
850
858
|
...messagesSyncPoint,
|
|
851
859
|
remoteTreeInProgress
|
|
@@ -863,8 +871,8 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
863
871
|
return Buffer32.fromString(block.hash);
|
|
864
872
|
}
|
|
865
873
|
async handleCheckpoints(blocksSynchedTo, currentL1BlockNumber, initialSyncComplete) {
|
|
866
|
-
const localPendingCheckpointNumber = await this.
|
|
867
|
-
const initialValidationResult = await this.
|
|
874
|
+
const localPendingCheckpointNumber = await this.stores.blocks.getLatestCheckpointNumber();
|
|
875
|
+
const initialValidationResult = await this.stores.blocks.getPendingChainValidationStatus();
|
|
868
876
|
const { provenCheckpointNumber, provenArchive, pendingCheckpointNumber, pendingArchive, archiveOfMyCheckpoint: archiveForLocalPendingCheckpointNumber } = await execInSpan(this.tracer, 'Archiver.getRollupStatus', ()=>this.rollup.status(localPendingCheckpointNumber, {
|
|
869
877
|
blockNumber: currentL1BlockNumber
|
|
870
878
|
}));
|
|
@@ -887,7 +895,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
887
895
|
// we need to set it to zero. This is an edge case because we dont have a checkpoint zero (initial checkpoint is one),
|
|
888
896
|
// so localCheckpointForDestinationProvenCheckpointNumber would not be found below.
|
|
889
897
|
if (provenCheckpointNumber === 0) {
|
|
890
|
-
const localProvenCheckpointNumber = await this.
|
|
898
|
+
const localProvenCheckpointNumber = await this.stores.blocks.getProvenCheckpointNumber();
|
|
891
899
|
if (localProvenCheckpointNumber !== provenCheckpointNumber) {
|
|
892
900
|
await this.updater.setProvenCheckpointNumber(provenCheckpointNumber);
|
|
893
901
|
this.log.info(`Rolled back proven chain to checkpoint ${provenCheckpointNumber}`, {
|
|
@@ -895,16 +903,16 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
895
903
|
});
|
|
896
904
|
}
|
|
897
905
|
}
|
|
898
|
-
const localCheckpointForDestinationProvenCheckpointNumber = await this.
|
|
906
|
+
const localCheckpointForDestinationProvenCheckpointNumber = await this.stores.blocks.getCheckpointData(provenCheckpointNumber);
|
|
899
907
|
// Sanity check. I've hit what seems to be a state where the proven checkpoint is set to a value greater than the latest
|
|
900
908
|
// synched checkpoint when requesting L2Tips from the archiver. This is the only place where the proven checkpoint is set.
|
|
901
|
-
const synched = await this.
|
|
909
|
+
const synched = await this.stores.blocks.getLatestCheckpointNumber();
|
|
902
910
|
if (localCheckpointForDestinationProvenCheckpointNumber && synched < localCheckpointForDestinationProvenCheckpointNumber.checkpointNumber) {
|
|
903
911
|
this.log.error(`Hit local checkpoint greater than last synched checkpoint: ${localCheckpointForDestinationProvenCheckpointNumber.checkpointNumber} > ${synched}`);
|
|
904
912
|
}
|
|
905
913
|
this.log.trace(`Local checkpoint for remote proven checkpoint ${provenCheckpointNumber} is ${localCheckpointForDestinationProvenCheckpointNumber?.archive.root.toString() ?? 'undefined'}`);
|
|
906
914
|
if (localCheckpointForDestinationProvenCheckpointNumber && provenArchive.equals(localCheckpointForDestinationProvenCheckpointNumber.archive.root)) {
|
|
907
|
-
const localProvenCheckpointNumber = await this.
|
|
915
|
+
const localProvenCheckpointNumber = await this.stores.blocks.getProvenCheckpointNumber();
|
|
908
916
|
if (localProvenCheckpointNumber !== provenCheckpointNumber) {
|
|
909
917
|
await this.updater.setProvenCheckpointNumber(provenCheckpointNumber);
|
|
910
918
|
this.log.info(`Updated proven chain to checkpoint ${provenCheckpointNumber}`, {
|
|
@@ -929,7 +937,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
929
937
|
// If we have 0 checkpoints locally and there are no checkpoints onchain there is nothing to do.
|
|
930
938
|
const noCheckpoints = localPendingCheckpointNumber === 0 && pendingCheckpointNumber === 0;
|
|
931
939
|
if (noCheckpoints) {
|
|
932
|
-
await this.
|
|
940
|
+
await this.stores.blocks.setSynchedL1BlockNumber(currentL1BlockNumber);
|
|
933
941
|
this.log.debug(`No checkpoints to retrieve from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}, no checkpoints on chain`);
|
|
934
942
|
return rollupStatus;
|
|
935
943
|
}
|
|
@@ -937,7 +945,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
937
945
|
// Related to the L2 reorgs of the pending chain. We are only interested in actually addressing a reorg if there
|
|
938
946
|
// are any state that could be impacted by it. If we have no checkpoints, there is no impact.
|
|
939
947
|
if (localPendingCheckpointNumber > 0) {
|
|
940
|
-
const localPendingCheckpoint = await this.
|
|
948
|
+
const localPendingCheckpoint = await this.stores.blocks.getCheckpointData(localPendingCheckpointNumber);
|
|
941
949
|
if (localPendingCheckpoint === undefined) {
|
|
942
950
|
throw new Error(`Missing checkpoint ${localPendingCheckpointNumber}`);
|
|
943
951
|
}
|
|
@@ -951,7 +959,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
951
959
|
// However, in the re-org scenario, our L1 node is temporarily lying to us and we end up potentially missing checkpoints.
|
|
952
960
|
// We must only set this block number based on actually retrieved logs.
|
|
953
961
|
// TODO(#8621): Tackle this properly when we handle L1 Re-orgs.
|
|
954
|
-
// await this.
|
|
962
|
+
// await this.stores.blocks.setSynchedL1BlockNumber(currentL1BlockNumber);
|
|
955
963
|
this.log.debug(`No checkpoints to retrieve from ${blocksSynchedTo + 1n} to ${currentL1BlockNumber}`);
|
|
956
964
|
return rollupStatus;
|
|
957
965
|
}
|
|
@@ -968,7 +976,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
968
976
|
});
|
|
969
977
|
let tipAfterUnwind = localPendingCheckpointNumber;
|
|
970
978
|
while(true){
|
|
971
|
-
const candidateCheckpoint = await this.
|
|
979
|
+
const candidateCheckpoint = await this.stores.blocks.getCheckpointData(tipAfterUnwind);
|
|
972
980
|
if (candidateCheckpoint === undefined) {
|
|
973
981
|
break;
|
|
974
982
|
}
|
|
@@ -984,7 +992,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
984
992
|
}
|
|
985
993
|
const checkpointsToRemove = localPendingCheckpointNumber - tipAfterUnwind;
|
|
986
994
|
await this.updater.removeCheckpointsAfter(CheckpointNumber(tipAfterUnwind));
|
|
987
|
-
this.log.warn(`Removed ${count(checkpointsToRemove, 'checkpoint')} after checkpoint ${tipAfterUnwind} ` + `due to mismatched checkpoint hashes at L1 block ${currentL1BlockNumber}. ` + `Updated L2 latest checkpoint is ${await this.
|
|
995
|
+
this.log.warn(`Removed ${count(checkpointsToRemove, 'checkpoint')} after checkpoint ${tipAfterUnwind} ` + `due to mismatched checkpoint hashes at L1 block ${currentL1BlockNumber}. ` + `Updated L2 latest checkpoint is ${await this.stores.blocks.getLatestCheckpointNumber()}.`);
|
|
988
996
|
}
|
|
989
997
|
}
|
|
990
998
|
// Retrieve checkpoints in batches. Each batch is estimated to accommodate up to 'blockBatchSize' L1 blocks,
|
|
@@ -1009,11 +1017,13 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1009
1017
|
searchStartBlock,
|
|
1010
1018
|
searchEndBlock
|
|
1011
1019
|
});
|
|
1012
|
-
// Check if the last checkpoint matches
|
|
1013
|
-
// We only check the last one
|
|
1014
|
-
//
|
|
1020
|
+
// Check if the last checkpoint matches a local pending entry (so we can skip blob fetch).
|
|
1021
|
+
// We only check the last one; if it matches, the blob fetch is skipped for that entry.
|
|
1022
|
+
// TODO(palla/pipelining): We may have more than a single checkpoint to promote
|
|
1015
1023
|
const lastCalldataCheckpoint = calldataCheckpoints[calldataCheckpoints.length - 1];
|
|
1016
|
-
const
|
|
1024
|
+
const promoteResult = await this.tryBuildPublishedCheckpointFromProposed(lastCalldataCheckpoint);
|
|
1025
|
+
const checkpointToPromote = promoteResult && !('diverged' in promoteResult) ? promoteResult : undefined;
|
|
1026
|
+
const evictProposedFrom = promoteResult && 'diverged' in promoteResult ? promoteResult.fromCheckpointNumber : undefined;
|
|
1017
1027
|
// Then fetch blobs in parallel and build the full published checkpoints
|
|
1018
1028
|
const toFetchBlobs = checkpointToPromote ? calldataCheckpoints.slice(0, -1) : calldataCheckpoints;
|
|
1019
1029
|
const blobFetched = await asyncPool(10, toFetchBlobs, async (checkpoint)=>retrievedToPublishedCheckpoint({
|
|
@@ -1030,7 +1040,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1030
1040
|
for (const published of publishedCheckpoints){
|
|
1031
1041
|
const validationResult = this.config.skipValidateCheckpointAttestations ? {
|
|
1032
1042
|
valid: true
|
|
1033
|
-
} : await validateCheckpointAttestations(published, this.epochCache, this.l1Constants, this.log);
|
|
1043
|
+
} : await validateCheckpointAttestations(published, this.epochCache, this.l1Constants, this.getSignatureContext(), this.log);
|
|
1034
1044
|
// Only update the validation result if it has changed, so we can keep track of the first invalid checkpoint
|
|
1035
1045
|
// in case there is a sequence of more than one invalid checkpoint, as we need to invalidate the first one.
|
|
1036
1046
|
// There is an exception though: if a checkpoint is invalidated and replaced with another invalid checkpoint,
|
|
@@ -1055,7 +1065,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1055
1065
|
// Check the inHash of the checkpoint against the l1->l2 messages.
|
|
1056
1066
|
// The messages should've been synced up to the currentL1BlockNumber and must be available for the published
|
|
1057
1067
|
// checkpoints we just retrieved.
|
|
1058
|
-
const l1ToL2Messages = await this.
|
|
1068
|
+
const l1ToL2Messages = await this.stores.messages.getL1ToL2Messages(published.checkpoint.number);
|
|
1059
1069
|
const computedInHash = computeInHashFromL1ToL2Messages(l1ToL2Messages);
|
|
1060
1070
|
const publishedInHash = published.checkpoint.header.inHash;
|
|
1061
1071
|
if (!computedInHash.equals(publishedInHash)) {
|
|
@@ -1092,7 +1102,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1092
1102
|
l1: lastCalldataCheckpoint.l1,
|
|
1093
1103
|
attestations: lastCalldataCheckpoint.attestations,
|
|
1094
1104
|
checkpoint: maybeValidCheckpointToPromote
|
|
1095
|
-
})));
|
|
1105
|
+
}, evictProposedFrom)));
|
|
1096
1106
|
if (checkpointsToAdd.length > 0) {
|
|
1097
1107
|
this.instrumentation.processNewCheckpointedBlocks(processDuration / checkpointsToAdd.length, checkpointsToAdd.flatMap((c)=>c.checkpoint.blocks));
|
|
1098
1108
|
}
|
|
@@ -1117,9 +1127,9 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1117
1127
|
} catch (err) {
|
|
1118
1128
|
if (err instanceof InitialCheckpointNumberNotSequentialError) {
|
|
1119
1129
|
const { previousCheckpointNumber, newCheckpointNumber } = err;
|
|
1120
|
-
const previousCheckpoint = previousCheckpointNumber ? await this.
|
|
1130
|
+
const previousCheckpoint = previousCheckpointNumber ? await this.stores.blocks.getCheckpointData(CheckpointNumber(previousCheckpointNumber)) : undefined;
|
|
1121
1131
|
const updatedL1SyncPoint = previousCheckpoint?.l1.blockNumber ?? this.l1Constants.l1StartBlock;
|
|
1122
|
-
await this.
|
|
1132
|
+
await this.stores.blocks.setSynchedL1BlockNumber(updatedL1SyncPoint);
|
|
1123
1133
|
this.log.warn(`Attempting to insert checkpoint ${newCheckpointNumber} with previous block ${previousCheckpointNumber}. Rolling back L1 sync point to ${updatedL1SyncPoint} to try and fetch the missing blocks.`, {
|
|
1124
1134
|
previousCheckpointNumber,
|
|
1125
1135
|
newCheckpointNumber,
|
|
@@ -1150,9 +1160,20 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1150
1160
|
lastL1BlockWithCheckpoint
|
|
1151
1161
|
};
|
|
1152
1162
|
}
|
|
1153
|
-
/**
|
|
1154
|
-
|
|
1155
|
-
|
|
1163
|
+
/**
|
|
1164
|
+
* Checks if a specific checkpoint matches a local pending entry, and if so, loads local data to build
|
|
1165
|
+
* a synthetic published checkpoint (skipping blob fetch).
|
|
1166
|
+
*
|
|
1167
|
+
* Returns { diverged: true, fromCheckpointNumber } when the L1 checkpoint does NOT match local pending
|
|
1168
|
+
* data for that number, so the caller can evict the entire pending suffix >= fromCheckpointNumber
|
|
1169
|
+
* (those entries chain off the now-invalid local state) within the same addCheckpoints transaction.
|
|
1170
|
+
*/ async tryBuildPublishedCheckpointFromProposed(calldataCheckpoint) {
|
|
1171
|
+
if (this.config.skipPromoteProposedCheckpointDuringL1Sync || !calldataCheckpoint) {
|
|
1172
|
+
return undefined;
|
|
1173
|
+
}
|
|
1174
|
+
// Look up the specific pending entry for the checkpoint being mined, not just the tip
|
|
1175
|
+
const proposed = await this.stores.blocks.getProposedCheckpointByNumber(calldataCheckpoint.checkpointNumber);
|
|
1176
|
+
if (!proposed) {
|
|
1156
1177
|
return undefined;
|
|
1157
1178
|
}
|
|
1158
1179
|
if (!proposed.header.equals(calldataCheckpoint.header) || !proposed.archive.root.equals(calldataCheckpoint.archiveRoot)) {
|
|
@@ -1164,13 +1185,17 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1164
1185
|
calldataHeader: calldataCheckpoint.header.toInspect(),
|
|
1165
1186
|
calldataArchiveRoot: calldataCheckpoint.archiveRoot.toString()
|
|
1166
1187
|
});
|
|
1167
|
-
|
|
1188
|
+
// Return a divergence signal so the caller can evict pending >= this number
|
|
1189
|
+
return {
|
|
1190
|
+
diverged: true,
|
|
1191
|
+
fromCheckpointNumber: proposed.checkpointNumber
|
|
1192
|
+
};
|
|
1168
1193
|
}
|
|
1169
1194
|
this.log.debug(`Building published checkpoint from proposed ${calldataCheckpoint.checkpointNumber} (skipping blob fetch)`, {
|
|
1170
1195
|
proposedHeader: proposed.header.toInspect(),
|
|
1171
1196
|
proposedArchiveRoot: proposed.archive.root.toString()
|
|
1172
1197
|
});
|
|
1173
|
-
const blocks = await this.
|
|
1198
|
+
const blocks = await this.stores.blocks.getBlocks(BlockNumber(proposed.startBlock), proposed.blockCount);
|
|
1174
1199
|
if (blocks.length !== proposed.blockCount) {
|
|
1175
1200
|
this.log.warn(`Local proposed checkpoint ${proposed.checkpointNumber} has wrong block count (expected ${proposed.blockCount} blocks starting at ${proposed.startBlock} but got ${blocks.length})`, {
|
|
1176
1201
|
proposedCheckpointNumber: proposed.checkpointNumber,
|
|
@@ -1199,7 +1224,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1199
1224
|
const { lastRetrievedCheckpoint, pendingCheckpointNumber } = status;
|
|
1200
1225
|
// Compare the last checkpoint we have (either retrieved in this round or loaded from store) with what the
|
|
1201
1226
|
// rollup contract told us was the latest one (pinned at the currentL1BlockNumber).
|
|
1202
|
-
const latestLocalCheckpointNumber = lastRetrievedCheckpoint?.checkpoint.number ?? await this.
|
|
1227
|
+
const latestLocalCheckpointNumber = lastRetrievedCheckpoint?.checkpoint.number ?? await this.stores.blocks.getLatestCheckpointNumber();
|
|
1203
1228
|
if (latestLocalCheckpointNumber < pendingCheckpointNumber) {
|
|
1204
1229
|
// Here we have consumed all logs until the `currentL1Block` we pinned at the beginning of the archiver loop,
|
|
1205
1230
|
// but still haven't reached the pending checkpoint according to the call to the rollup contract.
|
|
@@ -1212,7 +1237,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1212
1237
|
latestLocalCheckpointArchive = lastRetrievedCheckpoint.checkpoint.archive.root.toString();
|
|
1213
1238
|
targetL1BlockNumber = lastRetrievedCheckpoint.l1.blockNumber;
|
|
1214
1239
|
} else if (latestLocalCheckpointNumber > 0) {
|
|
1215
|
-
const checkpoint = await this.
|
|
1240
|
+
const checkpoint = await this.stores.blocks.getRangeOfCheckpoints(latestLocalCheckpointNumber, 1).then(([c])=>c);
|
|
1216
1241
|
latestLocalCheckpointArchive = checkpoint.archive.root.toString();
|
|
1217
1242
|
targetL1BlockNumber = checkpoint.l1.blockNumber;
|
|
1218
1243
|
}
|
|
@@ -1223,7 +1248,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1223
1248
|
currentL1BlockNumber,
|
|
1224
1249
|
...status
|
|
1225
1250
|
});
|
|
1226
|
-
await this.
|
|
1251
|
+
await this.stores.blocks.setSynchedL1BlockNumber(targetL1BlockNumber);
|
|
1227
1252
|
} else {
|
|
1228
1253
|
this.log.trace(`No new checkpoints behind L1 sync point to retrieve.`, {
|
|
1229
1254
|
latestLocalCheckpointNumber,
|
|
@@ -1232,7 +1257,7 @@ _dec = trackSpan('Archiver.syncFromL1'), _dec1 = trackSpan('Archiver.handleEpoch
|
|
|
1232
1257
|
}
|
|
1233
1258
|
}
|
|
1234
1259
|
async getCheckpointHeader(number) {
|
|
1235
|
-
const checkpoint = await this.
|
|
1260
|
+
const checkpoint = await this.stores.blocks.getCheckpointData(number);
|
|
1236
1261
|
if (!checkpoint) {
|
|
1237
1262
|
return undefined;
|
|
1238
1263
|
}
|
|
@@ -3,15 +3,16 @@ import type { Logger } from '@aztec/foundation/log';
|
|
|
3
3
|
import { type AttestationInfo, type ValidateCheckpointResult } from '@aztec/stdlib/block';
|
|
4
4
|
import type { PublishedCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
5
5
|
import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
6
|
+
import { type CoordinationSignatureContext } from '@aztec/stdlib/p2p';
|
|
6
7
|
export type { ValidateCheckpointResult };
|
|
7
8
|
/**
|
|
8
9
|
* Extracts attestation information from a published checkpoint.
|
|
9
10
|
* Returns info for each attestation, preserving array indices.
|
|
10
11
|
*/
|
|
11
|
-
export declare function getAttestationInfoFromPublishedCheckpoint({ checkpoint, attestations }: PublishedCheckpoint): AttestationInfo[];
|
|
12
|
+
export declare function getAttestationInfoFromPublishedCheckpoint({ checkpoint, attestations }: PublishedCheckpoint, signatureContext: CoordinationSignatureContext): AttestationInfo[];
|
|
12
13
|
/**
|
|
13
14
|
* Validates the attestations submitted for the given checkpoint.
|
|
14
15
|
* Returns true if the attestations are valid and sufficient, false otherwise.
|
|
15
16
|
*/
|
|
16
|
-
export declare function validateCheckpointAttestations(publishedCheckpoint: PublishedCheckpoint, epochCache: EpochCache, constants: Pick<L1RollupConstants, 'epochDuration'>, logger?: Logger): Promise<ValidateCheckpointResult>;
|
|
17
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
17
|
+
export declare function validateCheckpointAttestations(publishedCheckpoint: PublishedCheckpoint, epochCache: EpochCache, constants: Pick<L1RollupConstants, 'epochDuration'>, signatureContext: CoordinationSignatureContext, logger?: Logger): Promise<ValidateCheckpointResult>;
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGlvbi5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21vZHVsZXMvdmFsaWRhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUdyRCxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNwRCxPQUFPLEVBQ0wsS0FBSyxlQUFlLEVBRXBCLEtBQUssd0JBQXdCLEVBRTlCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNwRSxPQUFPLEVBQUUsS0FBSyxpQkFBaUIsRUFBaUMsTUFBTSw2QkFBNkIsQ0FBQztBQUNwRyxPQUFPLEVBQW9CLEtBQUssNEJBQTRCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUV4RixZQUFZLEVBQUUsd0JBQXdCLEVBQUUsQ0FBQztBQUV6Qzs7O0dBR0c7QUFDSCx3QkFBZ0IseUNBQXlDLENBQ3ZELEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxFQUFFLG1CQUFtQixFQUNqRCxnQkFBZ0IsRUFBRSw0QkFBNEIsR0FDN0MsZUFBZSxFQUFFLENBR25CO0FBRUQ7OztHQUdHO0FBQ0gsd0JBQXNCLDhCQUE4QixDQUNsRCxtQkFBbUIsRUFBRSxtQkFBbUIsRUFDeEMsVUFBVSxFQUFFLFVBQVUsRUFDdEIsU0FBUyxFQUFFLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxlQUFlLENBQUMsRUFDbkQsZ0JBQWdCLEVBQUUsNEJBQTRCLEVBQzlDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sR0FDZCxPQUFPLENBQUMsd0JBQXdCLENBQUMsQ0EyRm5DIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/modules/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,wBAAwB,EAE9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,KAAK,iBAAiB,EAAiC,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/modules/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,wBAAwB,EAE9B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EAAE,KAAK,iBAAiB,EAAiC,MAAM,6BAA6B,CAAC;AACpG,OAAO,EAAoB,KAAK,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAExF,YAAY,EAAE,wBAAwB,EAAE,CAAC;AAEzC;;;GAGG;AACH,wBAAgB,yCAAyC,CACvD,EAAE,UAAU,EAAE,YAAY,EAAE,EAAE,mBAAmB,EACjD,gBAAgB,EAAE,4BAA4B,GAC7C,eAAe,EAAE,CAGnB;AAED;;;GAGG;AACH,wBAAsB,8BAA8B,CAClD,mBAAmB,EAAE,mBAAmB,EACxC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,EACnD,gBAAgB,EAAE,4BAA4B,EAC9C,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,wBAAwB,CAAC,CA2FnC"}
|
|
@@ -5,15 +5,15 @@ import { ConsensusPayload } from '@aztec/stdlib/p2p';
|
|
|
5
5
|
/**
|
|
6
6
|
* Extracts attestation information from a published checkpoint.
|
|
7
7
|
* Returns info for each attestation, preserving array indices.
|
|
8
|
-
*/ export function getAttestationInfoFromPublishedCheckpoint({ checkpoint, attestations }) {
|
|
9
|
-
const payload = ConsensusPayload.fromCheckpoint(checkpoint);
|
|
8
|
+
*/ export function getAttestationInfoFromPublishedCheckpoint({ checkpoint, attestations }, signatureContext) {
|
|
9
|
+
const payload = ConsensusPayload.fromCheckpoint(checkpoint, signatureContext);
|
|
10
10
|
return getAttestationInfoFromPayload(payload, attestations);
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* Validates the attestations submitted for the given checkpoint.
|
|
14
14
|
* Returns true if the attestations are valid and sufficient, false otherwise.
|
|
15
|
-
*/ export async function validateCheckpointAttestations(publishedCheckpoint, epochCache, constants, logger) {
|
|
16
|
-
const attestorInfos = getAttestationInfoFromPublishedCheckpoint(publishedCheckpoint);
|
|
15
|
+
*/ export async function validateCheckpointAttestations(publishedCheckpoint, epochCache, constants, signatureContext, logger) {
|
|
16
|
+
const attestorInfos = getAttestationInfoFromPublishedCheckpoint(publishedCheckpoint, signatureContext);
|
|
17
17
|
const attestors = compactArray(attestorInfos.map((info)=>'address' in info ? info.address : undefined));
|
|
18
18
|
const { checkpoint, attestations } = publishedCheckpoint;
|
|
19
19
|
const headerHash = checkpoint.header.hash();
|