@aztec/sequencer-client 0.0.1-commit.e6bd8901 → 0.0.1-commit.ec7ac5448
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/client/sequencer-client.d.ts +17 -7
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +63 -30
- package/dest/config.d.ts +26 -7
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +47 -33
- package/dest/global_variable_builder/global_builder.d.ts +15 -10
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +26 -26
- package/dest/global_variable_builder/index.d.ts +2 -2
- package/dest/global_variable_builder/index.d.ts.map +1 -1
- package/dest/publisher/config.d.ts +47 -17
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +121 -42
- package/dest/publisher/index.d.ts +2 -1
- package/dest/publisher/index.d.ts.map +1 -1
- package/dest/publisher/l1_tx_failed_store/factory.d.ts +11 -0
- package/dest/publisher/l1_tx_failed_store/factory.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/factory.js +22 -0
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts +59 -0
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.js +1 -0
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.d.ts +15 -0
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/file_store_failed_tx_store.js +34 -0
- package/dest/publisher/l1_tx_failed_store/index.d.ts +4 -0
- package/dest/publisher/l1_tx_failed_store/index.d.ts.map +1 -0
- package/dest/publisher/l1_tx_failed_store/index.js +2 -0
- package/dest/publisher/sequencer-publisher-factory.d.ts +11 -5
- package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.js +27 -3
- package/dest/publisher/sequencer-publisher-metrics.d.ts +1 -1
- package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-metrics.js +12 -4
- package/dest/publisher/sequencer-publisher.d.ts +75 -49
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +470 -156
- package/dest/sequencer/chain_state_overrides.d.ts +25 -0
- package/dest/sequencer/chain_state_overrides.d.ts.map +1 -0
- package/dest/sequencer/chain_state_overrides.js +39 -0
- package/dest/sequencer/checkpoint_proposal_job.d.ts +51 -13
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +414 -239
- package/dest/sequencer/checkpoint_voter.d.ts +1 -2
- package/dest/sequencer/checkpoint_voter.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_voter.js +2 -5
- package/dest/sequencer/events.d.ts +2 -1
- package/dest/sequencer/events.d.ts.map +1 -1
- package/dest/sequencer/metrics.d.ts +25 -6
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +134 -31
- package/dest/sequencer/sequencer.d.ts +44 -17
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +157 -94
- package/dest/sequencer/timetable.d.ts +17 -6
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +51 -46
- package/dest/sequencer/types.d.ts +2 -2
- package/dest/sequencer/types.d.ts.map +1 -1
- package/dest/test/index.d.ts +3 -5
- package/dest/test/index.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.d.ts +14 -11
- package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.js +63 -40
- package/dest/test/utils.d.ts +3 -3
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +5 -4
- package/package.json +27 -28
- package/src/client/sequencer-client.ts +81 -30
- package/src/config.ts +65 -43
- package/src/global_variable_builder/global_builder.ts +31 -28
- package/src/global_variable_builder/index.ts +1 -1
- package/src/publisher/config.ts +153 -43
- package/src/publisher/index.ts +3 -0
- package/src/publisher/l1_tx_failed_store/factory.ts +32 -0
- package/src/publisher/l1_tx_failed_store/failed_tx_store.ts +55 -0
- package/src/publisher/l1_tx_failed_store/file_store_failed_tx_store.ts +46 -0
- package/src/publisher/l1_tx_failed_store/index.ts +3 -0
- package/src/publisher/sequencer-publisher-factory.ts +38 -9
- package/src/publisher/sequencer-publisher-metrics.ts +7 -3
- package/src/publisher/sequencer-publisher.ts +531 -214
- package/src/sequencer/README.md +83 -13
- package/src/sequencer/chain_state_overrides.ts +87 -0
- package/src/sequencer/checkpoint_proposal_job.ts +547 -274
- package/src/sequencer/checkpoint_voter.ts +1 -12
- package/src/sequencer/events.ts +1 -1
- package/src/sequencer/metrics.ts +153 -33
- package/src/sequencer/sequencer.ts +228 -107
- package/src/sequencer/timetable.ts +70 -57
- package/src/sequencer/types.ts +1 -1
- package/src/test/index.ts +2 -4
- package/src/test/mock_checkpoint_builder.ts +84 -56
- package/src/test/utils.ts +5 -2
|
@@ -373,14 +373,14 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
|
373
373
|
var _dec, _dec1, _dec2, _dec3, _initProto;
|
|
374
374
|
import { getKzg } from '@aztec/blob-lib';
|
|
375
375
|
import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
|
|
376
|
-
import { NoCommitteeError } from '@aztec/ethereum/contracts';
|
|
376
|
+
import { NoCommitteeError, SimulationOverridesBuilder } from '@aztec/ethereum/contracts';
|
|
377
377
|
import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
|
|
378
378
|
import { merge, omit, pick } from '@aztec/foundation/collection';
|
|
379
379
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
380
380
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
381
381
|
import { createLogger } from '@aztec/foundation/log';
|
|
382
382
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
383
|
-
import {
|
|
383
|
+
import { getSlotStartBuildTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
384
384
|
import { SequencerConfigSchema } from '@aztec/stdlib/interfaces/server';
|
|
385
385
|
import { pickFromSchema } from '@aztec/stdlib/schemas';
|
|
386
386
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
@@ -450,17 +450,12 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
450
450
|
state;
|
|
451
451
|
metrics;
|
|
452
452
|
/** The last slot for which we attempted to perform our voting duties with degraded block production */ lastSlotForFallbackVote;
|
|
453
|
+
/** The last slot for which we logged "no committee" warning, to avoid spam */ lastSlotForNoCommitteeWarning;
|
|
453
454
|
/** The last slot for which we triggered a checkpoint proposal job, to prevent duplicate attempts. */ lastSlotForCheckpointProposalJob;
|
|
454
455
|
/** Last successful checkpoint proposed */ lastCheckpointProposed;
|
|
455
456
|
/** The last epoch for which we logged strategy comparison in fisherman mode. */ lastEpochForStrategyComparison;
|
|
457
|
+
/** The last checkpoint proposal job, tracked so we can await its pending L1 submission during shutdown. */ lastCheckpointProposalJob;
|
|
456
458
|
/** The maximum number of seconds that the sequencer can be into a slot to transition to a particular state. */ timetable;
|
|
457
|
-
// This shouldn't be here as this gets re-created each time we build/propose a block.
|
|
458
|
-
// But we have a number of tests that abuse/rely on this class having a permanent publisher.
|
|
459
|
-
// As long as those tests only configure a single publisher they will continue to work.
|
|
460
|
-
// This will get re-assigned every time the sequencer goes to build a new block to a publisher that is valid
|
|
461
|
-
// for the block proposer.
|
|
462
|
-
// TODO(palla/mbps): Remove this field and fix tests
|
|
463
|
-
publisher;
|
|
464
459
|
/** Config for the sequencer */ config;
|
|
465
460
|
constructor(publisherFactory, validatorClient, globalsBuilder, p2pClient, worldState, slasherClient, l2BlockSource, l1ToL2MessageSource, checkpointsBuilder, l1Constants, dateProvider, epochCache, rollupContract, config, telemetry = getTelemetryClient(), log = createLogger('sequencer')){
|
|
466
461
|
super(), this.publisherFactory = publisherFactory, this.validatorClient = validatorClient, this.globalsBuilder = globalsBuilder, this.p2pClient = p2pClient, this.worldState = worldState, this.slasherClient = slasherClient, this.l2BlockSource = l2BlockSource, this.l1ToL2MessageSource = l1ToL2MessageSource, this.checkpointsBuilder = checkpointsBuilder, this.l1Constants = l1Constants, this.dateProvider = dateProvider, this.epochCache = epochCache, this.rollupContract = rollupContract, this.telemetry = telemetry, this.log = log, this.state = (_initProto(this), SequencerState.STOPPED), this.config = DefaultSequencerConfig;
|
|
@@ -473,20 +468,21 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
473
468
|
}
|
|
474
469
|
/** Updates sequencer config by the defined values and updates the timetable */ updateConfig(config) {
|
|
475
470
|
const filteredConfig = pickFromSchema(config, SequencerConfigSchema);
|
|
476
|
-
this.log.info(`Updated sequencer config`, omit(filteredConfig, '
|
|
471
|
+
this.log.info(`Updated sequencer config`, omit(filteredConfig, 'txPublicSetupAllowListExtend'));
|
|
477
472
|
this.config = merge(this.config, filteredConfig);
|
|
473
|
+
const p2pPropagationTime = this.config.attestationPropagationTime;
|
|
478
474
|
this.timetable = new SequencerTimetable({
|
|
479
475
|
ethereumSlotDuration: this.l1Constants.ethereumSlotDuration,
|
|
480
476
|
aztecSlotDuration: this.aztecSlotDuration,
|
|
481
477
|
l1PublishingTime: this.l1PublishingTime,
|
|
482
|
-
p2pPropagationTime
|
|
478
|
+
p2pPropagationTime,
|
|
483
479
|
blockDurationMs: this.config.blockDurationMs,
|
|
484
|
-
enforce: this.config.enforceTimeTable
|
|
480
|
+
enforce: this.config.enforceTimeTable,
|
|
481
|
+
pipelining: this.epochCache.isProposerPipeliningEnabled()
|
|
485
482
|
}, this.metrics, this.log);
|
|
486
483
|
}
|
|
487
|
-
/** Initializes the sequencer (precomputes tables
|
|
484
|
+
/** Initializes the sequencer (precomputes tables). Takes about 3s. */ init() {
|
|
488
485
|
getKzg();
|
|
489
|
-
this.publisher = (await this.publisherFactory.create(undefined)).publisher;
|
|
490
486
|
}
|
|
491
487
|
/** Starts the sequencer and moves to IDLE state. */ start() {
|
|
492
488
|
this.runningPromise = new RunningPromise(this.safeWork.bind(this), this.log, this.config.sequencerPollingIntervalMS);
|
|
@@ -496,13 +492,17 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
496
492
|
this.runningPromise.start();
|
|
497
493
|
this.log.info('Started sequencer');
|
|
498
494
|
}
|
|
495
|
+
/** Triggers an immediate run of the sequencer, bypassing the polling interval. */ trigger() {
|
|
496
|
+
return this.runningPromise?.trigger();
|
|
497
|
+
}
|
|
499
498
|
/** Stops the sequencer from building blocks and moves to STOPPED state. */ async stop() {
|
|
500
499
|
this.log.info(`Stopping sequencer`);
|
|
501
500
|
this.setState(SequencerState.STOPPING, undefined, {
|
|
502
501
|
force: true
|
|
503
502
|
});
|
|
504
|
-
this.
|
|
503
|
+
await this.publisherFactory.stopAll();
|
|
505
504
|
await this.runningPromise?.stop();
|
|
505
|
+
await this.lastCheckpointProposalJob?.awaitPendingSubmission();
|
|
506
506
|
this.setState(SequencerState.STOPPED, undefined, {
|
|
507
507
|
force: true
|
|
508
508
|
});
|
|
@@ -516,7 +516,6 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
516
516
|
error: err
|
|
517
517
|
});
|
|
518
518
|
if (err instanceof SequencerTooSlowError) {
|
|
519
|
-
// TODO(palla/mbps): Add missing states
|
|
520
519
|
// Log as warn only if we had to abort halfway through the block proposal
|
|
521
520
|
const logLvl = [
|
|
522
521
|
SequencerState.INITIALIZING_CHECKPOINT,
|
|
@@ -547,22 +546,25 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
547
546
|
* - Submit checkpoint
|
|
548
547
|
*/ async work() {
|
|
549
548
|
this.setState(SequencerState.SYNCHRONIZING, undefined);
|
|
550
|
-
const { slot, ts,
|
|
549
|
+
const { slot, ts, nowSeconds, epoch } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
550
|
+
const { slot: targetSlot, epoch: targetEpoch } = this.epochCache.getTargetEpochAndSlotInNextL1Slot();
|
|
551
551
|
// Check if we are synced and it's our slot, grab a publisher, check previous block invalidation, etc
|
|
552
|
-
const checkpointProposalJob = await this.prepareCheckpointProposal(epoch,
|
|
552
|
+
const checkpointProposalJob = await this.prepareCheckpointProposal(slot, targetSlot, epoch, targetEpoch, ts, nowSeconds);
|
|
553
553
|
if (!checkpointProposalJob) {
|
|
554
554
|
return;
|
|
555
555
|
}
|
|
556
|
+
// Track the job so we can await its pending L1 submission during shutdown
|
|
557
|
+
this.lastCheckpointProposalJob = checkpointProposalJob;
|
|
556
558
|
// Execute the checkpoint proposal job
|
|
557
559
|
const checkpoint = await checkpointProposalJob.execute();
|
|
558
560
|
// Update last checkpoint proposed (currently unused)
|
|
559
561
|
if (checkpoint) {
|
|
560
562
|
this.lastCheckpointProposed = checkpoint;
|
|
561
563
|
}
|
|
562
|
-
// Log fee strategy comparison if on fisherman
|
|
563
|
-
if (this.config.fishermanMode && (this.lastEpochForStrategyComparison === undefined ||
|
|
564
|
-
this.logStrategyComparison(
|
|
565
|
-
this.lastEpochForStrategyComparison =
|
|
564
|
+
// Log fee strategy comparison if on fisherman (uses target epoch since we mirror the proposer's perspective)
|
|
565
|
+
if (this.config.fishermanMode && (this.lastEpochForStrategyComparison === undefined || targetEpoch > this.lastEpochForStrategyComparison)) {
|
|
566
|
+
this.logStrategyComparison(targetEpoch, checkpointProposalJob.getPublisher());
|
|
567
|
+
this.lastEpochForStrategyComparison = targetEpoch;
|
|
566
568
|
}
|
|
567
569
|
return checkpoint;
|
|
568
570
|
}
|
|
@@ -570,17 +572,17 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
570
572
|
* Prepares the checkpoint proposal by performing all necessary checks and setup.
|
|
571
573
|
* This is the initial step in the main loop.
|
|
572
574
|
* @returns CheckpointProposalJob if successful, undefined if we are not yet synced or are not the proposer.
|
|
573
|
-
*/ async prepareCheckpointProposal(epoch,
|
|
574
|
-
// Check we have not already processed this slot (cheapest check)
|
|
575
|
+
*/ async prepareCheckpointProposal(slot, targetSlot, epoch, targetEpoch, ts, nowSeconds) {
|
|
576
|
+
// Check we have not already processed this target slot (cheapest check)
|
|
575
577
|
// We only check this if enforce timetable is set, since we want to keep processing the same slot if we are not
|
|
576
578
|
// running against actual time (eg when we use sandbox-style automining)
|
|
577
|
-
if (this.lastSlotForCheckpointProposalJob && this.lastSlotForCheckpointProposalJob >=
|
|
578
|
-
this.log.trace(`
|
|
579
|
+
if (this.lastSlotForCheckpointProposalJob && this.lastSlotForCheckpointProposalJob >= targetSlot && this.config.enforceTimeTable) {
|
|
580
|
+
this.log.trace(`Target slot ${targetSlot} has already been processed`);
|
|
579
581
|
return undefined;
|
|
580
582
|
}
|
|
581
|
-
// But if we have already proposed for this slot,
|
|
582
|
-
if (this.lastCheckpointProposed && this.lastCheckpointProposed.header.slotNumber >=
|
|
583
|
-
this.log.trace(`Slot ${
|
|
583
|
+
// But if we have already proposed for this slot, then we definitely have to skip it, automining or not
|
|
584
|
+
if (this.lastCheckpointProposed && this.lastCheckpointProposed.header.slotNumber >= targetSlot) {
|
|
585
|
+
this.log.trace(`Slot ${targetSlot} has already been published as checkpoint ${this.lastCheckpointProposed.number}`);
|
|
584
586
|
return undefined;
|
|
585
587
|
}
|
|
586
588
|
// Check all components are synced to latest as seen by the archiver (queries all subsystems)
|
|
@@ -591,16 +593,18 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
591
593
|
if (!syncedTo) {
|
|
592
594
|
await this.tryVoteWhenSyncFails({
|
|
593
595
|
slot,
|
|
596
|
+
targetSlot,
|
|
594
597
|
ts
|
|
595
598
|
});
|
|
596
599
|
return undefined;
|
|
597
600
|
}
|
|
598
|
-
// If escape hatch is open for
|
|
601
|
+
// If escape hatch is open for the target epoch, do not start checkpoint proposal work and do not attempt invalidations.
|
|
599
602
|
// Still perform governance/slashing voting (as proposer) once per slot.
|
|
600
|
-
|
|
603
|
+
// When pipelining, we check the target epoch (slot+1's epoch) since that's the epoch we're building for.
|
|
604
|
+
const isEscapeHatchOpen = await this.epochCache.isEscapeHatchOpen(targetEpoch);
|
|
601
605
|
if (isEscapeHatchOpen) {
|
|
602
606
|
this.setState(SequencerState.PROPOSER_CHECK, slot);
|
|
603
|
-
const [canPropose, proposer] = await this.checkCanPropose(
|
|
607
|
+
const [canPropose, proposer] = await this.checkCanPropose(targetSlot);
|
|
604
608
|
if (canPropose) {
|
|
605
609
|
await this.tryVoteWhenEscapeHatchOpen({
|
|
606
610
|
slot,
|
|
@@ -618,29 +622,36 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
618
622
|
// Next checkpoint follows from the last synced one
|
|
619
623
|
const checkpointNumber = CheckpointNumber(syncedTo.checkpointNumber + 1);
|
|
620
624
|
const logCtx = {
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
syncedToL2Slot: getSlotAtTimestamp(syncedTo.l1Timestamp, this.l1Constants),
|
|
625
|
+
nowSeconds,
|
|
626
|
+
syncedToL2Slot: syncedTo.syncedL2Slot,
|
|
624
627
|
slot,
|
|
628
|
+
targetSlot,
|
|
625
629
|
slotTs: ts,
|
|
626
630
|
checkpointNumber,
|
|
627
631
|
isPendingChainValid: pick(syncedTo.pendingChainValidationStatus, 'valid', 'reason', 'invalidIndex')
|
|
628
632
|
};
|
|
629
|
-
// Check that we are a proposer for the
|
|
633
|
+
// Check that we are a proposer for the target slot.
|
|
630
634
|
this.setState(SequencerState.PROPOSER_CHECK, slot);
|
|
631
|
-
const [canPropose, proposer] = await this.checkCanPropose(
|
|
635
|
+
const [canPropose, proposer] = await this.checkCanPropose(targetSlot);
|
|
632
636
|
// If we are not a proposer check if we should invalidate an invalid checkpoint, and bail
|
|
633
637
|
if (!canPropose) {
|
|
634
638
|
await this.considerInvalidatingCheckpoint(syncedTo, slot);
|
|
635
639
|
return undefined;
|
|
636
640
|
}
|
|
637
|
-
//
|
|
638
|
-
|
|
639
|
-
|
|
641
|
+
// Guard: don't exceed 1-deep pipeline. Without a proposed checkpoint, we can only build
|
|
642
|
+
// confirmed + 1. With a proposed checkpoint, we can build confirmed + 2.
|
|
643
|
+
const confirmedCkpt = syncedTo.checkpointedCheckpointNumber;
|
|
644
|
+
if (checkpointNumber > confirmedCkpt + 2) {
|
|
645
|
+
this.log.verbose(`Skipping slot ${targetSlot}: checkpoint ${checkpointNumber} exceeds max pipeline depth (confirmed=${confirmedCkpt})`);
|
|
646
|
+
return undefined;
|
|
647
|
+
}
|
|
648
|
+
// Check that the target slot is not taken by a block already (should never happen, since only us can propose for this slot)
|
|
649
|
+
if (syncedTo.blockData && syncedTo.blockData.header.getSlot() >= targetSlot) {
|
|
650
|
+
this.log.warn(`Cannot propose block at target slot ${targetSlot} since that slot was taken by block ${syncedTo.blockNumber}`, {
|
|
640
651
|
...logCtx,
|
|
641
|
-
block: syncedTo.
|
|
652
|
+
block: syncedTo.blockData.header.toInspect()
|
|
642
653
|
});
|
|
643
|
-
this.metrics.
|
|
654
|
+
this.metrics.recordCheckpointPrecheckFailed('slot_already_taken');
|
|
644
655
|
return undefined;
|
|
645
656
|
}
|
|
646
657
|
// We now need to get ourselves a publisher.
|
|
@@ -650,37 +661,58 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
650
661
|
const proposerForPublisher = this.config.fishermanMode ? undefined : proposer;
|
|
651
662
|
const { attestorAddress, publisher } = await this.publisherFactory.create(proposerForPublisher);
|
|
652
663
|
this.log.verbose(`Created publisher at address ${publisher.getSenderAddress()} for attestor ${attestorAddress}`);
|
|
653
|
-
this.publisher = publisher;
|
|
654
664
|
// In fisherman mode, set the actual proposer's address for simulations
|
|
655
665
|
if (this.config.fishermanMode && proposer) {
|
|
656
666
|
publisher.setProposerAddressForSimulation(proposer);
|
|
657
667
|
this.log.debug(`Set proposer address ${proposer} for simulation in fisherman mode`);
|
|
658
668
|
}
|
|
659
669
|
// Prepare invalidation request if the pending chain is invalid (returns undefined if no need)
|
|
660
|
-
|
|
661
|
-
//
|
|
662
|
-
//
|
|
663
|
-
|
|
670
|
+
let invalidateCheckpoint = await publisher.simulateInvalidateCheckpoint(syncedTo.pendingChainValidationStatus);
|
|
671
|
+
// Determine the correct archive and L1 state overrides for the canProposeAt check.
|
|
672
|
+
// The L1 contract reads archives[proposedCheckpointNumber] and compares it with the provided archive.
|
|
673
|
+
// When invalidating or pipelining, the local archive may differ from L1's, so we adjust accordingly.
|
|
674
|
+
let archiveForCheck = syncedTo.archive;
|
|
675
|
+
const l1SimulationOverridesBuilder = new SimulationOverridesBuilder();
|
|
676
|
+
if (this.epochCache.isProposerPipeliningEnabled() && syncedTo.hasProposedCheckpoint) {
|
|
677
|
+
// Parent checkpoint hasn't landed on L1 yet. Override both the proposed checkpoint number
|
|
678
|
+
// and the archive at that checkpoint so L1 simulation sees the correct chain tip.
|
|
679
|
+
const parentCheckpointNumber = CheckpointNumber(checkpointNumber - 1);
|
|
680
|
+
l1SimulationOverridesBuilder.forPendingCheckpoint(parentCheckpointNumber).withPendingArchive(syncedTo.archive);
|
|
681
|
+
this.metrics.recordPipelineDepth(1);
|
|
682
|
+
this.log.verbose(`Building on top of proposed checkpoint (pending=${syncedTo.proposedCheckpointData?.checkpointNumber})`);
|
|
683
|
+
// Clear the invalidation - the proposed checkpoint should handle it.
|
|
684
|
+
invalidateCheckpoint = undefined;
|
|
685
|
+
} else if (invalidateCheckpoint) {
|
|
686
|
+
// After invalidation, L1 will roll back to checkpoint N-1. The archive at N-1 already
|
|
687
|
+
// exists on L1, so we just pass the matching archive (the lastArchive of the invalid checkpoint).
|
|
688
|
+
archiveForCheck = invalidateCheckpoint.lastArchive;
|
|
689
|
+
l1SimulationOverridesBuilder.forPendingCheckpoint(invalidateCheckpoint.forcePendingCheckpointNumber);
|
|
690
|
+
this.metrics.recordPipelineDepth(0);
|
|
691
|
+
} else {
|
|
692
|
+
this.metrics.recordPipelineDepth(0);
|
|
693
|
+
}
|
|
694
|
+
const simulationOverridesPlan = l1SimulationOverridesBuilder.build();
|
|
695
|
+
const canProposeCheck = await publisher.canProposeAt(archiveForCheck, proposer ?? EthAddress.ZERO, simulationOverridesPlan);
|
|
664
696
|
if (canProposeCheck === undefined) {
|
|
665
697
|
this.log.warn(`Cannot propose checkpoint ${checkpointNumber} at slot ${slot} due to failed rollup contract check`, logCtx);
|
|
666
698
|
this.emit('proposer-rollup-check-failed', {
|
|
667
699
|
reason: 'Rollup contract check failed',
|
|
668
700
|
slot
|
|
669
701
|
});
|
|
670
|
-
this.metrics.
|
|
702
|
+
this.metrics.recordCheckpointPrecheckFailed('rollup_contract_check_failed');
|
|
671
703
|
return undefined;
|
|
672
704
|
}
|
|
673
|
-
if (canProposeCheck.slot !==
|
|
674
|
-
this.log.warn(`Cannot propose block due to slot mismatch with rollup contract (this can be caused by a clock out of sync). Expected slot ${
|
|
705
|
+
if (canProposeCheck.slot !== targetSlot) {
|
|
706
|
+
this.log.warn(`Cannot propose block due to slot mismatch with rollup contract (this can be caused by a clock out of sync). Expected slot ${targetSlot} but got ${canProposeCheck.slot}.`, {
|
|
675
707
|
...logCtx,
|
|
676
708
|
rollup: canProposeCheck,
|
|
677
|
-
expectedSlot:
|
|
709
|
+
expectedSlot: targetSlot
|
|
678
710
|
});
|
|
679
711
|
this.emit('proposer-rollup-check-failed', {
|
|
680
712
|
reason: 'Slot mismatch',
|
|
681
713
|
slot
|
|
682
714
|
});
|
|
683
|
-
this.metrics.
|
|
715
|
+
this.metrics.recordCheckpointPrecheckFailed('slot_mismatch');
|
|
684
716
|
return undefined;
|
|
685
717
|
}
|
|
686
718
|
if (canProposeCheck.checkpointNumber !== checkpointNumber) {
|
|
@@ -693,19 +725,26 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
693
725
|
reason: 'Block mismatch',
|
|
694
726
|
slot
|
|
695
727
|
});
|
|
696
|
-
this.metrics.
|
|
728
|
+
this.metrics.recordCheckpointPrecheckFailed('block_number_mismatch');
|
|
697
729
|
return undefined;
|
|
698
730
|
}
|
|
699
|
-
this.lastSlotForCheckpointProposalJob =
|
|
700
|
-
this.
|
|
731
|
+
this.lastSlotForCheckpointProposalJob = targetSlot;
|
|
732
|
+
await this.p2pClient.prepareForSlot(targetSlot);
|
|
733
|
+
this.log.info(`Preparing checkpoint proposal ${checkpointNumber} for target slot ${targetSlot} during wall-clock slot ${slot}`, {
|
|
701
734
|
...logCtx,
|
|
702
|
-
proposer
|
|
735
|
+
proposer,
|
|
736
|
+
pipeliningEnabled: this.epochCache.isProposerPipeliningEnabled()
|
|
703
737
|
});
|
|
704
738
|
// Create and return the checkpoint proposal job
|
|
705
|
-
return this.createCheckpointProposalJob(
|
|
739
|
+
return this.createCheckpointProposalJob(slot, targetSlot, targetEpoch, checkpointNumber, syncedTo.blockNumber, proposer, publisher, attestorAddress, invalidateCheckpoint, syncedTo.proposedCheckpointData);
|
|
706
740
|
}
|
|
707
|
-
createCheckpointProposalJob(
|
|
708
|
-
return new CheckpointProposalJob(
|
|
741
|
+
createCheckpointProposalJob(slot, targetSlot, targetEpoch, checkpointNumber, syncedToBlockNumber, proposer, publisher, attestorAddress, invalidateCheckpoint, proposedCheckpointData) {
|
|
742
|
+
return new CheckpointProposalJob(slot, targetSlot, targetEpoch, checkpointNumber, syncedToBlockNumber, proposer, publisher, attestorAddress, invalidateCheckpoint, this.validatorClient, this.globalsBuilder, this.p2pClient, this.worldState, this.l1ToL2MessageSource, this.l2BlockSource, this.checkpointsBuilder, this.l2BlockSource, this.l1Constants, this.config, this.timetable, this.slasherClient, this.epochCache, this.dateProvider, this.metrics, this, this.setState.bind(this), this.tracer, this.log.getBindings(), proposedCheckpointData);
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Returns the current sequencer state.
|
|
746
|
+
*/ getState() {
|
|
747
|
+
return this.state;
|
|
709
748
|
}
|
|
710
749
|
/**
|
|
711
750
|
* Internal helper for setting the sequencer state and checks if we have enough time left in the slot to transition to the new state.
|
|
@@ -747,16 +786,15 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
747
786
|
* Returns whether all dependencies have caught up.
|
|
748
787
|
* We don't check against the previous block submitted since it may have been reorg'd out.
|
|
749
788
|
*/ async checkSync(args) {
|
|
750
|
-
// Check that the archiver
|
|
751
|
-
//
|
|
752
|
-
//
|
|
753
|
-
const
|
|
754
|
-
const { slot
|
|
755
|
-
if (
|
|
789
|
+
// Check that the archiver has fully synced the L2 slot before the one we want to propose in.
|
|
790
|
+
// The archiver reports sync progress via L1 block timestamps and synced checkpoint slots.
|
|
791
|
+
// See getSyncedL2SlotNumber for how missed L1 blocks are handled.
|
|
792
|
+
const syncedL2Slot = await this.l2BlockSource.getSyncedL2SlotNumber();
|
|
793
|
+
const { slot } = args;
|
|
794
|
+
if (syncedL2Slot === undefined || syncedL2Slot + 1 < slot) {
|
|
756
795
|
this.log.debug(`Cannot propose block at next L2 slot ${slot} due to pending sync from L1`, {
|
|
757
796
|
slot,
|
|
758
|
-
|
|
759
|
-
l1Timestamp
|
|
797
|
+
syncedL2Slot
|
|
760
798
|
});
|
|
761
799
|
return undefined;
|
|
762
800
|
}
|
|
@@ -765,22 +803,30 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
765
803
|
number: syncSummary.latestBlockNumber,
|
|
766
804
|
hash: syncSummary.latestBlockHash
|
|
767
805
|
})),
|
|
768
|
-
this.l2BlockSource.getL2Tips().then((t)=>
|
|
806
|
+
this.l2BlockSource.getL2Tips().then((t)=>({
|
|
807
|
+
proposed: t.proposed,
|
|
808
|
+
checkpointed: t.checkpointed,
|
|
809
|
+
proposedCheckpoint: t.proposedCheckpoint
|
|
810
|
+
})),
|
|
769
811
|
this.p2pClient.getStatus().then((p2p)=>p2p.syncedToL2Block),
|
|
770
|
-
this.l1ToL2MessageSource.getL2Tips().then((t)=>
|
|
771
|
-
|
|
812
|
+
this.l1ToL2MessageSource.getL2Tips().then((t)=>({
|
|
813
|
+
proposed: t.proposed,
|
|
814
|
+
checkpointed: t.checkpointed
|
|
815
|
+
})),
|
|
816
|
+
this.l2BlockSource.getPendingChainValidationStatus(),
|
|
817
|
+
this.l2BlockSource.getProposedCheckpointOnly()
|
|
772
818
|
]);
|
|
773
|
-
const [worldState,
|
|
819
|
+
const [worldState, l2Tips, p2p, l1ToL2MessageSourceTips, pendingChainValidationStatus, proposedCheckpointData] = syncedBlocks;
|
|
774
820
|
// Handle zero as a special case, since the block hash won't match across services if we're changing the prefilled data for the genesis block,
|
|
775
821
|
// as the world state can compute the new genesis block hash, but other components use the hardcoded constant.
|
|
776
822
|
// TODO(palla/mbps): Fix the above. All components should be able to handle dynamic genesis block hashes.
|
|
777
|
-
const result =
|
|
823
|
+
const result = l2Tips.proposed.number === 0 && l2Tips.checkpointed.block.number === 0 && l2Tips.checkpointed.checkpoint.number === 0 && worldState.number === 0 && p2p.number === 0 && l1ToL2MessageSourceTips.proposed.number === 0 && l1ToL2MessageSourceTips.checkpointed.block.number === 0 && l1ToL2MessageSourceTips.checkpointed.checkpoint.number === 0 || worldState.hash === l2Tips.proposed.hash && p2p.hash === l2Tips.proposed.hash && l1ToL2MessageSourceTips.proposed.hash === l2Tips.proposed.hash && l1ToL2MessageSourceTips.checkpointed.block.hash === l2Tips.checkpointed.block.hash && l1ToL2MessageSourceTips.checkpointed.checkpoint.hash === l2Tips.checkpointed.checkpoint.hash;
|
|
778
824
|
if (!result) {
|
|
779
825
|
this.log.debug(`Sequencer sync check failed`, {
|
|
780
826
|
worldState,
|
|
781
|
-
l2BlockSource,
|
|
827
|
+
l2BlockSource: l2Tips.proposed,
|
|
782
828
|
p2p,
|
|
783
|
-
|
|
829
|
+
l1ToL2MessageSourceTips
|
|
784
830
|
});
|
|
785
831
|
return undefined;
|
|
786
832
|
}
|
|
@@ -790,43 +836,52 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
790
836
|
const archive = new Fr((await this.worldState.getCommitted().getTreeInfo(MerkleTreeId.ARCHIVE)).root);
|
|
791
837
|
return {
|
|
792
838
|
checkpointNumber: CheckpointNumber.ZERO,
|
|
839
|
+
checkpointedCheckpointNumber: CheckpointNumber.ZERO,
|
|
793
840
|
blockNumber: BlockNumber.ZERO,
|
|
794
841
|
archive,
|
|
795
|
-
|
|
842
|
+
hasProposedCheckpoint: false,
|
|
843
|
+
syncedL2Slot,
|
|
796
844
|
pendingChainValidationStatus
|
|
797
845
|
};
|
|
798
846
|
}
|
|
799
|
-
const
|
|
800
|
-
if (!
|
|
847
|
+
const blockData = await this.l2BlockSource.getBlockData(blockNumber);
|
|
848
|
+
if (!blockData) {
|
|
801
849
|
// this shouldn't really happen because a moment ago we checked that all components were in sync
|
|
802
|
-
this.log.error(`Failed to get L2 block ${blockNumber} from the archiver with all components in sync`);
|
|
850
|
+
this.log.error(`Failed to get L2 block data ${blockNumber} from the archiver with all components in sync`);
|
|
803
851
|
return undefined;
|
|
804
852
|
}
|
|
853
|
+
const hasProposedCheckpoint = l2Tips.proposedCheckpoint.checkpoint.number > l2Tips.checkpointed.checkpoint.number;
|
|
805
854
|
return {
|
|
806
|
-
|
|
807
|
-
blockNumber:
|
|
808
|
-
checkpointNumber:
|
|
809
|
-
|
|
810
|
-
|
|
855
|
+
blockData,
|
|
856
|
+
blockNumber: blockData.header.getBlockNumber(),
|
|
857
|
+
checkpointNumber: blockData.checkpointNumber,
|
|
858
|
+
checkpointedCheckpointNumber: l2Tips.checkpointed.checkpoint.number,
|
|
859
|
+
archive: blockData.archive.root,
|
|
860
|
+
hasProposedCheckpoint,
|
|
861
|
+
proposedCheckpointData,
|
|
862
|
+
syncedL2Slot,
|
|
811
863
|
pendingChainValidationStatus
|
|
812
864
|
};
|
|
813
865
|
}
|
|
814
866
|
/**
|
|
815
867
|
* Checks if we are the proposer for the next slot.
|
|
816
868
|
* @returns True if we can propose, and the proposer address (undefined if anyone can propose)
|
|
817
|
-
*/ async checkCanPropose(
|
|
869
|
+
*/ async checkCanPropose(targetSlot) {
|
|
818
870
|
let proposer;
|
|
819
871
|
try {
|
|
820
|
-
proposer = await this.epochCache.getProposerAttesterAddressInSlot(
|
|
872
|
+
proposer = await this.epochCache.getProposerAttesterAddressInSlot(targetSlot);
|
|
821
873
|
} catch (e) {
|
|
822
874
|
if (e instanceof NoCommitteeError) {
|
|
823
|
-
this.
|
|
875
|
+
if (this.lastSlotForNoCommitteeWarning !== targetSlot) {
|
|
876
|
+
this.lastSlotForNoCommitteeWarning = targetSlot;
|
|
877
|
+
this.log.warn(`Cannot propose at target slot ${targetSlot} since the committee does not exist on L1`);
|
|
878
|
+
}
|
|
824
879
|
return [
|
|
825
880
|
false,
|
|
826
881
|
undefined
|
|
827
882
|
];
|
|
828
883
|
}
|
|
829
|
-
this.log.error(`Error getting proposer for slot ${
|
|
884
|
+
this.log.error(`Error getting proposer for target slot ${targetSlot}`, e);
|
|
830
885
|
return [
|
|
831
886
|
false,
|
|
832
887
|
undefined
|
|
@@ -849,7 +904,8 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
849
904
|
const validatorAddresses = this.validatorClient.getValidatorAddresses();
|
|
850
905
|
const weAreProposer = validatorAddresses.some((addr)=>addr.equals(proposer));
|
|
851
906
|
if (!weAreProposer) {
|
|
852
|
-
this.log.debug(`Cannot propose at slot ${
|
|
907
|
+
this.log.debug(`Cannot propose at target slot ${targetSlot} since we are not a proposer`, {
|
|
908
|
+
targetSlot,
|
|
853
909
|
validatorAddresses,
|
|
854
910
|
proposer
|
|
855
911
|
});
|
|
@@ -858,6 +914,10 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
858
914
|
proposer
|
|
859
915
|
];
|
|
860
916
|
}
|
|
917
|
+
this.log.info(`We are the proposer for pipeline slot ${targetSlot}`, {
|
|
918
|
+
targetSlot,
|
|
919
|
+
proposer
|
|
920
|
+
});
|
|
861
921
|
return [
|
|
862
922
|
true,
|
|
863
923
|
proposer
|
|
@@ -867,7 +927,7 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
867
927
|
* Tries to vote on slashing actions and governance when the sync check fails but we're past the max time for initializing a proposal.
|
|
868
928
|
* This allows the sequencer to participate in governance/slashing votes even when it cannot build blocks.
|
|
869
929
|
*/ async tryVoteWhenSyncFails(args) {
|
|
870
|
-
const { slot } = args;
|
|
930
|
+
const { slot, targetSlot } = args;
|
|
871
931
|
// Prevent duplicate attempts in the same slot
|
|
872
932
|
if (this.lastSlotForFallbackVote === slot) {
|
|
873
933
|
this.log.trace(`Already attempted to vote in slot ${slot} (skipping)`);
|
|
@@ -890,7 +950,7 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
890
950
|
maxAllowedTime
|
|
891
951
|
});
|
|
892
952
|
// Check if we're a proposer or proposal is open
|
|
893
|
-
const [canPropose, proposer] = await this.checkCanPropose(
|
|
953
|
+
const [canPropose, proposer] = await this.checkCanPropose(targetSlot);
|
|
894
954
|
if (!canPropose) {
|
|
895
955
|
this.log.trace(`Cannot vote in slot ${slot} since we are not a proposer`, {
|
|
896
956
|
slot,
|
|
@@ -906,8 +966,8 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
906
966
|
attestorAddress,
|
|
907
967
|
slot
|
|
908
968
|
});
|
|
909
|
-
// Enqueue governance and slashing votes
|
|
910
|
-
const voter = new CheckpointVoter(
|
|
969
|
+
// Enqueue governance and slashing votes (voter uses the target slot for L1 submission)
|
|
970
|
+
const voter = new CheckpointVoter(targetSlot, publisher, attestorAddress, this.validatorClient, this.slasherClient, this.l1Constants, this.config, this.metrics, this.log);
|
|
911
971
|
const votesPromises = voter.enqueueVotes();
|
|
912
972
|
const votes = await Promise.all(votesPromises);
|
|
913
973
|
if (votes.every((p)=>!p)) {
|
|
@@ -954,7 +1014,7 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
954
1014
|
* have the proposer try to invalidate, but if they fail, the sequencers in the committee are expected to try,
|
|
955
1015
|
* and if they fail, any sequencer will try as well.
|
|
956
1016
|
*/ async considerInvalidatingCheckpoint(syncedTo, currentSlot) {
|
|
957
|
-
const { pendingChainValidationStatus,
|
|
1017
|
+
const { pendingChainValidationStatus, syncedL2Slot } = syncedTo;
|
|
958
1018
|
if (pendingChainValidationStatus.valid) {
|
|
959
1019
|
return;
|
|
960
1020
|
}
|
|
@@ -965,7 +1025,7 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
965
1025
|
const { secondsBeforeInvalidatingBlockAsCommitteeMember, secondsBeforeInvalidatingBlockAsNonCommitteeMember } = this.config;
|
|
966
1026
|
const logData = {
|
|
967
1027
|
invalidL1Timestamp: invalidCheckpointTimestamp,
|
|
968
|
-
|
|
1028
|
+
syncedL2Slot,
|
|
969
1029
|
invalidCheckpoint: pendingChainValidationStatus.checkpoint,
|
|
970
1030
|
secondsBeforeInvalidatingBlockAsCommitteeMember,
|
|
971
1031
|
secondsBeforeInvalidatingBlockAsNonCommitteeMember,
|
|
@@ -1056,6 +1116,9 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
1056
1116
|
getValidatorAddresses() {
|
|
1057
1117
|
return this.validatorClient?.getValidatorAddresses();
|
|
1058
1118
|
}
|
|
1119
|
+
/** Updates the publisher factory's node keystore adapter after a keystore reload. */ updatePublisherNodeKeyStore(adapter) {
|
|
1120
|
+
this.publisherFactory.updateNodeKeyStore(adapter);
|
|
1121
|
+
}
|
|
1059
1122
|
getConfig() {
|
|
1060
1123
|
return this.config;
|
|
1061
1124
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
1
2
|
import type { SequencerMetrics } from './metrics.js';
|
|
2
3
|
import { SequencerState } from './utils.js';
|
|
3
|
-
export declare const MIN_EXECUTION_TIME = 2;
|
|
4
|
-
export declare const CHECKPOINT_INITIALIZATION_TIME = 1;
|
|
5
|
-
export declare const CHECKPOINT_ASSEMBLE_TIME = 1;
|
|
6
4
|
export declare class SequencerTimetable {
|
|
7
5
|
private readonly metrics?;
|
|
8
|
-
private readonly log
|
|
6
|
+
private readonly log?;
|
|
7
|
+
private readonly checkpointTiming;
|
|
9
8
|
/**
|
|
10
9
|
* How late into the slot can we be to start working. Computed as the total time needed for assembling and publishing a block,
|
|
11
10
|
* assuming an execution time equal to `minExecutionTime`, subtracted from the slot duration. This means that, if the proposer
|
|
@@ -52,6 +51,13 @@ export declare class SequencerTimetable {
|
|
|
52
51
|
readonly blockDuration: number | undefined;
|
|
53
52
|
/** Maximum number of blocks that can be built in this slot configuration */
|
|
54
53
|
readonly maxNumberOfBlocks: number;
|
|
54
|
+
/** Whether pipelining is enabled (checkpoint finalization deferred to next slot). */
|
|
55
|
+
readonly pipelining: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* How far into the target slot attestation collection can extend when pipelining.
|
|
58
|
+
* Covers validator re-execution (one block duration) plus one-way attestation return.
|
|
59
|
+
*/
|
|
60
|
+
readonly pipeliningAttestationGracePeriod: number;
|
|
55
61
|
constructor(opts: {
|
|
56
62
|
ethereumSlotDuration: number;
|
|
57
63
|
aztecSlotDuration: number;
|
|
@@ -59,7 +65,12 @@ export declare class SequencerTimetable {
|
|
|
59
65
|
p2pPropagationTime?: number;
|
|
60
66
|
blockDurationMs?: number;
|
|
61
67
|
enforce: boolean;
|
|
62
|
-
|
|
68
|
+
pipelining?: boolean;
|
|
69
|
+
}, metrics?: SequencerMetrics | undefined, log?: Logger | undefined);
|
|
70
|
+
getCheckpointAssemblyDeadline(): number;
|
|
71
|
+
getCheckpointAttestationDeadline(): number;
|
|
72
|
+
getCheckpointAttestationStartDeadline(): number;
|
|
73
|
+
getCheckpointPublishingDeadline(): number;
|
|
63
74
|
getMaxAllowedTime(state: Extract<SequencerState, SequencerState.STOPPED | SequencerState.IDLE | SequencerState.SYNCHRONIZING>): undefined;
|
|
64
75
|
getMaxAllowedTime(state: Exclude<SequencerState, SequencerState.STOPPED | SequencerState.IDLE | SequencerState.SYNCHRONIZING>): number;
|
|
65
76
|
getMaxAllowedTime(state: SequencerState): number | undefined;
|
|
@@ -87,4 +98,4 @@ export declare class SequencerTimetable {
|
|
|
87
98
|
isLastBlock: boolean;
|
|
88
99
|
};
|
|
89
100
|
}
|
|
90
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
101
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZXRhYmxlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VxdWVuY2VyL3RpbWV0YWJsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQVdwRCxPQUFPLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUNyRCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRTVDLHFCQUFhLGtCQUFrQjtJQWlGM0IsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7SUFDekIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUM7SUFqRnZCLE9BQU8sQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQW1CO0lBRXBEOzs7O09BSUc7SUFDSCxTQUFnQixrQkFBa0IsRUFBRSxNQUFNLENBQUM7SUFFM0M7Ozs7T0FJRztJQUNILFNBQWdCLG9CQUFvQixFQUFFLE1BQU0sQ0FBQztJQUU3Qzs7Ozs7T0FLRztJQUNILFNBQWdCLDBCQUEwQixFQUFFLE1BQU0sQ0FBQztJQUVuRDs7OztPQUlHO0lBQ0gsU0FBZ0IsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDO0lBRXpDOzs7T0FHRztJQUNILFNBQWdCLGdCQUFnQixFQUFFLE1BQU0sQ0FBc0I7SUFFOUQsdURBQXVEO0lBQ3ZELFNBQWdCLDRCQUE0QixFQUFFLE1BQU0sQ0FBa0M7SUFFdEYsbUdBQW1HO0lBQ25HLFNBQWdCLGtCQUFrQixFQUFFLE1BQU0sQ0FBQztJQUUzQyxtRkFBbUY7SUFDbkYsU0FBZ0Isc0JBQXNCLEVBQUUsTUFBTSxDQUE0QjtJQUUxRSx3Q0FBd0M7SUFDeEMsU0FBZ0Isb0JBQW9CLEVBQUUsTUFBTSxDQUFDO0lBRTdDLGtGQUFrRjtJQUNsRixTQUFnQixpQkFBaUIsRUFBRSxNQUFNLENBQUM7SUFFMUMsNERBQTREO0lBQzVELFNBQWdCLE9BQU8sRUFBRSxPQUFPLENBQUM7SUFFakMsb0dBQW9HO0lBQ3BHLFNBQWdCLGFBQWEsRUFBRSxNQUFNLEdBQUcsU0FBUyxDQUFDO0lBRWxELDRFQUE0RTtJQUM1RSxTQUFnQixpQkFBaUIsRUFBRSxNQUFNLENBQUM7SUFFMUMscUZBQXFGO0lBQ3JGLFNBQWdCLFVBQVUsRUFBRSxPQUFPLENBQUM7SUFFcEM7OztPQUdHO0lBQ0gsU0FBZ0IsZ0NBQWdDLEVBQUUsTUFBTSxDQUFDO0lBRXpELFlBQ0UsSUFBSSxFQUFFO1FBQ0osb0JBQW9CLEVBQUUsTUFBTSxDQUFDO1FBQzdCLGlCQUFpQixFQUFFLE1BQU0sQ0FBQztRQUMxQixnQkFBZ0IsRUFBRSxNQUFNLENBQUM7UUFDekIsa0JBQWtCLENBQUMsRUFBRSxNQUFNLENBQUM7UUFDNUIsZUFBZSxDQUFDLEVBQUUsTUFBTSxDQUFDO1FBQ3pCLE9BQU8sRUFBRSxPQUFPLENBQUM7UUFDakIsVUFBVSxDQUFDLEVBQUUsT0FBTyxDQUFDO0tBQ3RCLEVBQ2dCLE9BQU8sQ0FBQyw4QkFBa0IsRUFDMUIsR0FBRyxDQUFDLG9CQUFRLEVBd0Q5QjtJQUVNLDZCQUE2QixJQUFJLE1BQU0sQ0FFN0M7SUFFTSxnQ0FBZ0MsSUFBSSxNQUFNLENBRWhEO0lBRU0scUNBQXFDLElBQUksTUFBTSxDQUVyRDtJQUVNLCtCQUErQixJQUFJLE1BQU0sQ0FFL0M7SUFFTSxpQkFBaUIsQ0FDdEIsS0FBSyxFQUFFLE9BQU8sQ0FBQyxjQUFjLEVBQUUsY0FBYyxDQUFDLE9BQU8sR0FBRyxjQUFjLENBQUMsSUFBSSxHQUFHLGNBQWMsQ0FBQyxhQUFhLENBQUMsR0FDMUcsU0FBUyxDQUFDO0lBQ04saUJBQWlCLENBQ3RCLEtBQUssRUFBRSxPQUFPLENBQUMsY0FBYyxFQUFFLGNBQWMsQ0FBQyxPQUFPLEdBQUcsY0FBYyxDQUFDLElBQUksR0FBRyxjQUFjLENBQUMsYUFBYSxDQUFDLEdBQzFHLE1BQU0sQ0FBQztJQUNILGlCQUFpQixDQUFDLEtBQUssRUFBRSxjQUFjLEdBQUcsTUFBTSxHQUFHLFNBQVMsQ0FBQztJQTRCN0QsY0FBYyxDQUFDLFFBQVEsRUFBRSxjQUFjLEVBQUUsZUFBZSxFQUFFLE1BQU0sUUFpQnRFO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSSxpQkFBaUIsQ0FDdEIsZUFBZSxFQUFFLE1BQU0sR0FFckI7UUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDO1FBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQztRQUFDLFdBQVcsRUFBRSxJQUFJLENBQUE7S0FBRSxHQUMxRDtRQUFFLFFBQVEsRUFBRSxLQUFLLENBQUM7UUFBQyxRQUFRLEVBQUUsU0FBUyxDQUFDO1FBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQTtLQUFFLEdBQzVEO1FBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQztRQUFDLFFBQVEsRUFBRSxNQUFNLENBQUM7UUFBQyxXQUFXLEVBQUUsT0FBTyxDQUFBO0tBQUUsQ0F3RGhFO0NBQ0YifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timetable.d.ts","sourceRoot":"","sources":["../../src/sequencer/timetable.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"timetable.d.ts","sourceRoot":"","sources":["../../src/sequencer/timetable.ts"],"names":[],"mappings":"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"}
|