@aztec/sequencer-client 0.0.1-commit.5de5ca79e → 0.0.1-commit.6201a7b05
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 +6 -1
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +11 -17
- package/dest/config.d.ts +1 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +13 -12
- package/dest/global_variable_builder/fee_predictor.d.ts +37 -0
- package/dest/global_variable_builder/fee_predictor.d.ts.map +1 -0
- package/dest/global_variable_builder/fee_predictor.js +128 -0
- package/dest/global_variable_builder/fee_provider.d.ts +21 -0
- package/dest/global_variable_builder/fee_provider.d.ts.map +1 -0
- package/dest/global_variable_builder/fee_provider.js +58 -0
- package/dest/global_variable_builder/global_builder.d.ts +15 -14
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +16 -51
- package/dest/global_variable_builder/index.d.ts +4 -2
- package/dest/global_variable_builder/index.d.ts.map +1 -1
- package/dest/global_variable_builder/index.js +2 -0
- package/dest/publisher/config.d.ts +13 -1
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +19 -4
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts +3 -4
- package/dest/publisher/l1_tx_failed_store/failed_tx_store.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.d.ts +3 -5
- package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.js +2 -3
- package/dest/publisher/sequencer-publisher.d.ts +48 -42
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +119 -111
- 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 +41 -11
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +525 -149
- package/dest/sequencer/checkpoint_proposal_job_metrics.d.ts +34 -0
- package/dest/sequencer/checkpoint_proposal_job_metrics.d.ts.map +1 -0
- package/dest/sequencer/checkpoint_proposal_job_metrics.js +72 -0
- 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 +6 -1
- package/dest/sequencer/events.d.ts.map +1 -1
- package/dest/sequencer/metrics.d.ts +9 -10
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +34 -20
- package/dest/sequencer/sequencer.d.ts +27 -7
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +106 -28
- package/dest/sequencer/timetable.d.ts +14 -1
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +45 -36
- package/dest/test/utils.d.ts +1 -1
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +7 -6
- package/package.json +27 -27
- package/src/client/sequencer-client.ts +16 -24
- package/src/config.ts +13 -11
- package/src/global_variable_builder/README.md +44 -0
- package/src/global_variable_builder/fee_predictor.ts +172 -0
- package/src/global_variable_builder/fee_provider.ts +75 -0
- package/src/global_variable_builder/global_builder.ts +26 -63
- package/src/global_variable_builder/index.ts +3 -1
- package/src/publisher/config.ts +38 -4
- package/src/publisher/l1_tx_failed_store/failed_tx_store.ts +3 -1
- package/src/publisher/sequencer-publisher-factory.ts +3 -6
- package/src/publisher/sequencer-publisher.ts +183 -159
- package/src/sequencer/README.md +82 -13
- package/src/sequencer/chain_state_overrides.ts +87 -0
- package/src/sequencer/checkpoint_proposal_job.ts +616 -167
- package/src/sequencer/checkpoint_proposal_job_metrics.ts +128 -0
- package/src/sequencer/checkpoint_voter.ts +1 -12
- package/src/sequencer/events.ts +5 -0
- package/src/sequencer/metrics.ts +43 -24
- package/src/sequencer/sequencer.ts +148 -32
- package/src/sequencer/timetable.ts +57 -45
- package/src/test/utils.ts +28 -10
|
@@ -373,7 +373,7 @@ 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';
|
|
@@ -388,6 +388,7 @@ import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-clie
|
|
|
388
388
|
import EventEmitter from 'node:events';
|
|
389
389
|
import { DefaultSequencerConfig } from '../config.js';
|
|
390
390
|
import { CheckpointProposalJob } from './checkpoint_proposal_job.js';
|
|
391
|
+
import { CheckpointProposalJobMetrics } from './checkpoint_proposal_job_metrics.js';
|
|
391
392
|
import { CheckpointVoter } from './checkpoint_voter.js';
|
|
392
393
|
import { SequencerInterruptedError, SequencerTooSlowError } from './errors.js';
|
|
393
394
|
import { SequencerMetrics } from './metrics.js';
|
|
@@ -448,34 +449,48 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
448
449
|
}
|
|
449
450
|
runningPromise;
|
|
450
451
|
state;
|
|
452
|
+
stateSlotNumber;
|
|
453
|
+
stateEnteredAtMs;
|
|
451
454
|
metrics;
|
|
455
|
+
checkpointProposalJobMetrics;
|
|
456
|
+
stateLog;
|
|
452
457
|
/** The last slot for which we attempted to perform our voting duties with degraded block production */ lastSlotForFallbackVote;
|
|
453
458
|
/** The last slot for which we logged "no committee" warning, to avoid spam */ lastSlotForNoCommitteeWarning;
|
|
454
459
|
/** The last slot for which we triggered a checkpoint proposal job, to prevent duplicate attempts. */ lastSlotForCheckpointProposalJob;
|
|
455
460
|
/** Last successful checkpoint proposed */ lastCheckpointProposed;
|
|
456
461
|
/** The last epoch for which we logged strategy comparison in fisherman mode. */ lastEpochForStrategyComparison;
|
|
462
|
+
/** The last checkpoint proposal job, tracked so we can await its pending L1 submission during shutdown. */ lastCheckpointProposalJob;
|
|
457
463
|
/** The maximum number of seconds that the sequencer can be into a slot to transition to a particular state. */ timetable;
|
|
458
464
|
/** Config for the sequencer */ config;
|
|
465
|
+
signatureContext;
|
|
459
466
|
constructor(publisherFactory, validatorClient, globalsBuilder, p2pClient, worldState, slasherClient, l2BlockSource, l1ToL2MessageSource, checkpointsBuilder, l1Constants, dateProvider, epochCache, rollupContract, config, telemetry = getTelemetryClient(), log = createLogger('sequencer')){
|
|
460
|
-
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;
|
|
467
|
+
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.stateEnteredAtMs = performance.now(), this.config = DefaultSequencerConfig;
|
|
468
|
+
this.stateLog = log.createChild('state');
|
|
461
469
|
// Add [FISHERMAN] prefix to logger if in fisherman mode
|
|
462
470
|
if (config.fishermanMode) {
|
|
463
471
|
this.log = log.createChild('[FISHERMAN]');
|
|
464
472
|
}
|
|
473
|
+
this.signatureContext = {
|
|
474
|
+
chainId: config.l1ChainId,
|
|
475
|
+
rollupAddress: config.l1Contracts.rollupAddress
|
|
476
|
+
};
|
|
465
477
|
this.metrics = new SequencerMetrics(telemetry, this.rollupContract, 'Sequencer');
|
|
478
|
+
this.checkpointProposalJobMetrics = new CheckpointProposalJobMetrics(telemetry);
|
|
466
479
|
this.updateConfig(config);
|
|
467
480
|
}
|
|
468
481
|
/** Updates sequencer config by the defined values and updates the timetable */ updateConfig(config) {
|
|
469
482
|
const filteredConfig = pickFromSchema(config, SequencerConfigSchema);
|
|
470
483
|
this.log.info(`Updated sequencer config`, omit(filteredConfig, 'txPublicSetupAllowListExtend'));
|
|
471
484
|
this.config = merge(this.config, filteredConfig);
|
|
485
|
+
const p2pPropagationTime = this.config.attestationPropagationTime;
|
|
472
486
|
this.timetable = new SequencerTimetable({
|
|
473
487
|
ethereumSlotDuration: this.l1Constants.ethereumSlotDuration,
|
|
474
488
|
aztecSlotDuration: this.aztecSlotDuration,
|
|
475
489
|
l1PublishingTime: this.l1PublishingTime,
|
|
476
|
-
p2pPropagationTime
|
|
490
|
+
p2pPropagationTime,
|
|
477
491
|
blockDurationMs: this.config.blockDurationMs,
|
|
478
|
-
enforce: this.config.enforceTimeTable
|
|
492
|
+
enforce: this.config.enforceTimeTable,
|
|
493
|
+
pipelining: this.epochCache.isProposerPipeliningEnabled()
|
|
479
494
|
}, this.metrics, this.log);
|
|
480
495
|
}
|
|
481
496
|
/** Initializes the sequencer (precomputes tables). Takes about 3s. */ init() {
|
|
@@ -489,13 +504,17 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
489
504
|
this.runningPromise.start();
|
|
490
505
|
this.log.info('Started sequencer');
|
|
491
506
|
}
|
|
507
|
+
/** Triggers an immediate run of the sequencer, bypassing the polling interval. */ trigger() {
|
|
508
|
+
return this.runningPromise?.trigger();
|
|
509
|
+
}
|
|
492
510
|
/** Stops the sequencer from building blocks and moves to STOPPED state. */ async stop() {
|
|
493
511
|
this.log.info(`Stopping sequencer`);
|
|
494
512
|
this.setState(SequencerState.STOPPING, undefined, {
|
|
495
513
|
force: true
|
|
496
514
|
});
|
|
497
|
-
this.publisherFactory.
|
|
515
|
+
await this.publisherFactory.stopAll();
|
|
498
516
|
await this.runningPromise?.stop();
|
|
517
|
+
await this.lastCheckpointProposalJob?.awaitPendingSubmission();
|
|
499
518
|
this.setState(SequencerState.STOPPED, undefined, {
|
|
500
519
|
force: true
|
|
501
520
|
});
|
|
@@ -546,6 +565,8 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
546
565
|
if (!checkpointProposalJob) {
|
|
547
566
|
return;
|
|
548
567
|
}
|
|
568
|
+
// Track the job so we can await its pending L1 submission during shutdown
|
|
569
|
+
this.lastCheckpointProposalJob = checkpointProposalJob;
|
|
549
570
|
// Execute the checkpoint proposal job
|
|
550
571
|
const checkpoint = await checkpointProposalJob.execute();
|
|
551
572
|
// Update last checkpoint proposed (currently unused)
|
|
@@ -629,6 +650,13 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
629
650
|
await this.considerInvalidatingCheckpoint(syncedTo, slot);
|
|
630
651
|
return undefined;
|
|
631
652
|
}
|
|
653
|
+
// Guard: don't exceed 1-deep pipeline. Without a proposed checkpoint, we can only build
|
|
654
|
+
// confirmed + 1. With a proposed checkpoint, we can build confirmed + 2.
|
|
655
|
+
const confirmedCkpt = syncedTo.checkpointedCheckpointNumber;
|
|
656
|
+
if (checkpointNumber > confirmedCkpt + 2) {
|
|
657
|
+
this.log.verbose(`Skipping slot ${targetSlot}: checkpoint ${checkpointNumber} exceeds max pipeline depth (confirmed=${confirmedCkpt})`);
|
|
658
|
+
return undefined;
|
|
659
|
+
}
|
|
632
660
|
// Check that the target slot is not taken by a block already (should never happen, since only us can propose for this slot)
|
|
633
661
|
if (syncedTo.blockData && syncedTo.blockData.header.getSlot() >= targetSlot) {
|
|
634
662
|
this.log.warn(`Cannot propose block at target slot ${targetSlot} since that slot was taken by block ${syncedTo.blockNumber}`, {
|
|
@@ -651,12 +679,32 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
651
679
|
this.log.debug(`Set proposer address ${proposer} for simulation in fisherman mode`);
|
|
652
680
|
}
|
|
653
681
|
// Prepare invalidation request if the pending chain is invalid (returns undefined if no need)
|
|
654
|
-
|
|
655
|
-
//
|
|
656
|
-
//
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
682
|
+
let invalidateCheckpoint = await publisher.simulateInvalidateCheckpoint(syncedTo.pendingChainValidationStatus);
|
|
683
|
+
// Determine the correct archive and L1 state overrides for the canProposeAt check.
|
|
684
|
+
// The L1 contract reads archives[proposedCheckpointNumber] and compares it with the provided archive.
|
|
685
|
+
// When invalidating or pipelining, the local archive may differ from L1's, so we adjust accordingly.
|
|
686
|
+
let archiveForCheck = syncedTo.archive;
|
|
687
|
+
const l1SimulationOverridesBuilder = new SimulationOverridesBuilder();
|
|
688
|
+
if (this.epochCache.isProposerPipeliningEnabled() && syncedTo.hasProposedCheckpoint) {
|
|
689
|
+
// Parent checkpoint hasn't landed on L1 yet. Override both the proposed checkpoint number
|
|
690
|
+
// and the archive at that checkpoint so L1 simulation sees the correct chain tip.
|
|
691
|
+
const parentCheckpointNumber = CheckpointNumber(checkpointNumber - 1);
|
|
692
|
+
l1SimulationOverridesBuilder.forPendingCheckpoint(parentCheckpointNumber).withPendingArchive(syncedTo.archive);
|
|
693
|
+
this.metrics.recordPipelineDepth(syncedTo.checkpointNumber - syncedTo.checkpointedCheckpointNumber);
|
|
694
|
+
this.log.verbose(`Building on top of proposed checkpoint (pending=${syncedTo.proposedCheckpointData?.checkpointNumber})`);
|
|
695
|
+
// Clear the invalidation - the proposed checkpoint should handle it.
|
|
696
|
+
invalidateCheckpoint = undefined;
|
|
697
|
+
} else if (invalidateCheckpoint) {
|
|
698
|
+
// After invalidation, L1 will roll back to checkpoint N-1. The archive at N-1 already
|
|
699
|
+
// exists on L1, so we just pass the matching archive (the lastArchive of the invalid checkpoint).
|
|
700
|
+
archiveForCheck = invalidateCheckpoint.lastArchive;
|
|
701
|
+
l1SimulationOverridesBuilder.forPendingCheckpoint(invalidateCheckpoint.forcePendingCheckpointNumber);
|
|
702
|
+
this.metrics.recordPipelineDepth(0);
|
|
703
|
+
} else {
|
|
704
|
+
this.metrics.recordPipelineDepth(0);
|
|
705
|
+
}
|
|
706
|
+
const simulationOverridesPlan = l1SimulationOverridesBuilder.build();
|
|
707
|
+
const canProposeCheck = await publisher.canProposeAt(archiveForCheck, proposer ?? EthAddress.ZERO, simulationOverridesPlan);
|
|
660
708
|
if (canProposeCheck === undefined) {
|
|
661
709
|
this.log.warn(`Cannot propose checkpoint ${checkpointNumber} at slot ${slot} due to failed rollup contract check`, logCtx);
|
|
662
710
|
this.emit('proposer-rollup-check-failed', {
|
|
@@ -700,10 +748,10 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
700
748
|
pipeliningEnabled: this.epochCache.isProposerPipeliningEnabled()
|
|
701
749
|
});
|
|
702
750
|
// Create and return the checkpoint proposal job
|
|
703
|
-
return this.createCheckpointProposalJob(slot, targetSlot,
|
|
751
|
+
return this.createCheckpointProposalJob(slot, targetSlot, targetEpoch, checkpointNumber, syncedTo.blockNumber, proposer, publisher, attestorAddress, invalidateCheckpoint, syncedTo.proposedCheckpointData);
|
|
704
752
|
}
|
|
705
|
-
createCheckpointProposalJob(slot, targetSlot,
|
|
706
|
-
return new CheckpointProposalJob(slot, targetSlot,
|
|
753
|
+
createCheckpointProposalJob(slot, targetSlot, targetEpoch, checkpointNumber, syncedToBlockNumber, proposer, publisher, attestorAddress, invalidateCheckpoint, proposedCheckpointData) {
|
|
754
|
+
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.signatureContext, this.config, this.timetable, this.slasherClient, this.epochCache, this.dateProvider, this.metrics, this.checkpointProposalJobMetrics.createRecorder(), this, this.setState.bind(this), this.tracer, this.log.getBindings(), proposedCheckpointData);
|
|
707
755
|
}
|
|
708
756
|
/**
|
|
709
757
|
* Returns the current sequencer state.
|
|
@@ -729,21 +777,37 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
729
777
|
secondsIntoSlot = this.getSecondsIntoSlot(slotNumber);
|
|
730
778
|
this.timetable.assertTimeLeft(proposedState, secondsIntoSlot);
|
|
731
779
|
}
|
|
780
|
+
const oldState = this.state;
|
|
781
|
+
const oldStateSlotNumber = this.stateSlotNumber;
|
|
782
|
+
const stateChanged = proposedState !== oldState;
|
|
783
|
+
const transitionAtMs = performance.now();
|
|
784
|
+
const stateDurationMs = transitionAtMs - this.stateEnteredAtMs;
|
|
732
785
|
const boringStates = [
|
|
733
786
|
SequencerState.IDLE,
|
|
734
787
|
SequencerState.SYNCHRONIZING
|
|
735
788
|
];
|
|
736
|
-
const logLevel = boringStates.includes(proposedState) && boringStates.includes(
|
|
737
|
-
this.
|
|
789
|
+
const logLevel = boringStates.includes(proposedState) && boringStates.includes(oldState) ? 'trace' : 'debug';
|
|
790
|
+
this.stateLog[logLevel](`Transitioning from ${oldState} to ${proposedState}`, {
|
|
791
|
+
oldState,
|
|
792
|
+
newState: proposedState,
|
|
738
793
|
slotNumber,
|
|
739
|
-
|
|
794
|
+
stateSlotNumber: oldStateSlotNumber,
|
|
795
|
+
secondsIntoSlot,
|
|
796
|
+
...stateChanged && {
|
|
797
|
+
stateDurationMs: Math.ceil(stateDurationMs)
|
|
798
|
+
}
|
|
740
799
|
});
|
|
741
800
|
this.emit('state-changed', {
|
|
742
|
-
oldState
|
|
801
|
+
oldState,
|
|
743
802
|
newState: proposedState,
|
|
744
803
|
secondsIntoSlot,
|
|
745
804
|
slot: slotNumber
|
|
746
805
|
});
|
|
806
|
+
if (stateChanged) {
|
|
807
|
+
this.metrics.recordStateDuration(stateDurationMs, oldState);
|
|
808
|
+
this.stateEnteredAtMs = transitionAtMs;
|
|
809
|
+
this.stateSlotNumber = slotNumber;
|
|
810
|
+
}
|
|
747
811
|
this.state = proposedState;
|
|
748
812
|
}
|
|
749
813
|
/**
|
|
@@ -751,8 +815,8 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
751
815
|
* We don't check against the previous block submitted since it may have been reorg'd out.
|
|
752
816
|
*/ async checkSync(args) {
|
|
753
817
|
// Check that the archiver has fully synced the L2 slot before the one we want to propose in.
|
|
754
|
-
//
|
|
755
|
-
//
|
|
818
|
+
// The archiver reports sync progress via L1 block timestamps and synced checkpoint slots.
|
|
819
|
+
// See getSyncedL2SlotNumber for how missed L1 blocks are handled.
|
|
756
820
|
const syncedL2Slot = await this.l2BlockSource.getSyncedL2SlotNumber();
|
|
757
821
|
const { slot } = args;
|
|
758
822
|
if (syncedL2Slot === undefined || syncedL2Slot + 1 < slot) {
|
|
@@ -767,22 +831,30 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
767
831
|
number: syncSummary.latestBlockNumber,
|
|
768
832
|
hash: syncSummary.latestBlockHash
|
|
769
833
|
})),
|
|
770
|
-
this.l2BlockSource.getL2Tips().then((t)=>
|
|
834
|
+
this.l2BlockSource.getL2Tips().then((t)=>({
|
|
835
|
+
proposed: t.proposed,
|
|
836
|
+
checkpointed: t.checkpointed,
|
|
837
|
+
proposedCheckpoint: t.proposedCheckpoint
|
|
838
|
+
})),
|
|
771
839
|
this.p2pClient.getStatus().then((p2p)=>p2p.syncedToL2Block),
|
|
772
|
-
this.l1ToL2MessageSource.getL2Tips().then((t)=>
|
|
773
|
-
|
|
840
|
+
this.l1ToL2MessageSource.getL2Tips().then((t)=>({
|
|
841
|
+
proposed: t.proposed,
|
|
842
|
+
checkpointed: t.checkpointed
|
|
843
|
+
})),
|
|
844
|
+
this.l2BlockSource.getPendingChainValidationStatus(),
|
|
845
|
+
this.l2BlockSource.getLastProposedCheckpoint()
|
|
774
846
|
]);
|
|
775
|
-
const [worldState,
|
|
847
|
+
const [worldState, l2Tips, p2p, l1ToL2MessageSourceTips, pendingChainValidationStatus, proposedCheckpointData] = syncedBlocks;
|
|
776
848
|
// 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,
|
|
777
849
|
// as the world state can compute the new genesis block hash, but other components use the hardcoded constant.
|
|
778
850
|
// TODO(palla/mbps): Fix the above. All components should be able to handle dynamic genesis block hashes.
|
|
779
|
-
const result =
|
|
851
|
+
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;
|
|
780
852
|
if (!result) {
|
|
781
853
|
this.log.debug(`Sequencer sync check failed`, {
|
|
782
854
|
worldState,
|
|
783
|
-
l2BlockSource,
|
|
855
|
+
l2BlockSource: l2Tips.proposed,
|
|
784
856
|
p2p,
|
|
785
|
-
|
|
857
|
+
l1ToL2MessageSourceTips
|
|
786
858
|
});
|
|
787
859
|
return undefined;
|
|
788
860
|
}
|
|
@@ -792,8 +864,10 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
792
864
|
const archive = new Fr((await this.worldState.getCommitted().getTreeInfo(MerkleTreeId.ARCHIVE)).root);
|
|
793
865
|
return {
|
|
794
866
|
checkpointNumber: CheckpointNumber.ZERO,
|
|
867
|
+
checkpointedCheckpointNumber: CheckpointNumber.ZERO,
|
|
795
868
|
blockNumber: BlockNumber.ZERO,
|
|
796
869
|
archive,
|
|
870
|
+
hasProposedCheckpoint: false,
|
|
797
871
|
syncedL2Slot,
|
|
798
872
|
pendingChainValidationStatus
|
|
799
873
|
};
|
|
@@ -804,11 +878,15 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
804
878
|
this.log.error(`Failed to get L2 block data ${blockNumber} from the archiver with all components in sync`);
|
|
805
879
|
return undefined;
|
|
806
880
|
}
|
|
881
|
+
const hasProposedCheckpoint = l2Tips.proposedCheckpoint.checkpoint.number > l2Tips.checkpointed.checkpoint.number;
|
|
807
882
|
return {
|
|
808
883
|
blockData,
|
|
809
884
|
blockNumber: blockData.header.getBlockNumber(),
|
|
810
885
|
checkpointNumber: blockData.checkpointNumber,
|
|
886
|
+
checkpointedCheckpointNumber: l2Tips.checkpointed.checkpoint.number,
|
|
811
887
|
archive: blockData.archive.root,
|
|
888
|
+
hasProposedCheckpoint,
|
|
889
|
+
proposedCheckpointData,
|
|
812
890
|
syncedL2Slot,
|
|
813
891
|
pendingChainValidationStatus
|
|
814
892
|
};
|
|
@@ -864,7 +942,7 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
|
|
|
864
942
|
proposer
|
|
865
943
|
];
|
|
866
944
|
}
|
|
867
|
-
this.log.
|
|
945
|
+
this.log.info(`We are the proposer for pipeline slot ${targetSlot}`, {
|
|
868
946
|
targetSlot,
|
|
869
947
|
proposer
|
|
870
948
|
});
|
|
@@ -4,6 +4,7 @@ import { SequencerState } from './utils.js';
|
|
|
4
4
|
export declare class SequencerTimetable {
|
|
5
5
|
private readonly metrics?;
|
|
6
6
|
private readonly log?;
|
|
7
|
+
private readonly checkpointTiming;
|
|
7
8
|
/**
|
|
8
9
|
* How late into the slot can we be to start working. Computed as the total time needed for assembling and publishing a block,
|
|
9
10
|
* assuming an execution time equal to `minExecutionTime`, subtracted from the slot duration. This means that, if the proposer
|
|
@@ -50,6 +51,13 @@ export declare class SequencerTimetable {
|
|
|
50
51
|
readonly blockDuration: number | undefined;
|
|
51
52
|
/** Maximum number of blocks that can be built in this slot configuration */
|
|
52
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;
|
|
53
61
|
constructor(opts: {
|
|
54
62
|
ethereumSlotDuration: number;
|
|
55
63
|
aztecSlotDuration: number;
|
|
@@ -57,7 +65,12 @@ export declare class SequencerTimetable {
|
|
|
57
65
|
p2pPropagationTime?: number;
|
|
58
66
|
blockDurationMs?: number;
|
|
59
67
|
enforce: boolean;
|
|
68
|
+
pipelining?: boolean;
|
|
60
69
|
}, metrics?: SequencerMetrics | undefined, log?: Logger | undefined);
|
|
70
|
+
getCheckpointAssemblyDeadline(): number;
|
|
71
|
+
getCheckpointAttestationDeadline(): number;
|
|
72
|
+
getCheckpointAttestationStartDeadline(): number;
|
|
73
|
+
getCheckpointPublishingDeadline(): number;
|
|
61
74
|
getMaxAllowedTime(state: Extract<SequencerState, SequencerState.STOPPED | SequencerState.IDLE | SequencerState.SYNCHRONIZING>): undefined;
|
|
62
75
|
getMaxAllowedTime(state: Exclude<SequencerState, SequencerState.STOPPED | SequencerState.IDLE | SequencerState.SYNCHRONIZING>): number;
|
|
63
76
|
getMaxAllowedTime(state: SequencerState): number | undefined;
|
|
@@ -85,4 +98,4 @@ export declare class SequencerTimetable {
|
|
|
85
98
|
isLastBlock: boolean;
|
|
86
99
|
};
|
|
87
100
|
}
|
|
88
|
-
//# 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":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"timetable.d.ts","sourceRoot":"","sources":["../../src/sequencer/timetable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAWpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,qBAAa,kBAAkB;IAiF3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;IAjFvB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IAEpD;;;;OAIG;IACH,SAAgB,kBAAkB,EAAE,MAAM,CAAC;IAE3C;;;;OAIG;IACH,SAAgB,oBAAoB,EAAE,MAAM,CAAC;IAE7C;;;;;OAKG;IACH,SAAgB,0BAA0B,EAAE,MAAM,CAAC;IAEnD;;;;OAIG;IACH,SAAgB,gBAAgB,EAAE,MAAM,CAAC;IAEzC;;;OAGG;IACH,SAAgB,gBAAgB,EAAE,MAAM,CAAsB;IAE9D,uDAAuD;IACvD,SAAgB,4BAA4B,EAAE,MAAM,CAAkC;IAEtF,mGAAmG;IACnG,SAAgB,kBAAkB,EAAE,MAAM,CAAC;IAE3C,mFAAmF;IACnF,SAAgB,sBAAsB,EAAE,MAAM,CAA4B;IAE1E,wCAAwC;IACxC,SAAgB,oBAAoB,EAAE,MAAM,CAAC;IAE7C,kFAAkF;IAClF,SAAgB,iBAAiB,EAAE,MAAM,CAAC;IAE1C,4DAA4D;IAC5D,SAAgB,OAAO,EAAE,OAAO,CAAC;IAEjC,oGAAoG;IACpG,SAAgB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAElD,4EAA4E;IAC5E,SAAgB,iBAAiB,EAAE,MAAM,CAAC;IAE1C,qFAAqF;IACrF,SAAgB,UAAU,EAAE,OAAO,CAAC;IAEpC;;;OAGG;IACH,SAAgB,gCAAgC,EAAE,MAAM,CAAC;IAEzD,YACE,IAAI,EAAE;QACJ,oBAAoB,EAAE,MAAM,CAAC;QAC7B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,gBAAgB,EAAE,MAAM,CAAC;QACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,EACgB,OAAO,CAAC,8BAAkB,EAC1B,GAAG,CAAC,oBAAQ,EAwD9B;IAEM,6BAA6B,IAAI,MAAM,CAE7C;IAEM,gCAAgC,IAAI,MAAM,CAEhD;IAEM,qCAAqC,IAAI,MAAM,CAErD;IAEM,+BAA+B,IAAI,MAAM,CAE/C;IAEM,iBAAiB,CACtB,KAAK,EAAE,OAAO,CAAC,cAAc,EAAE,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,IAAI,GAAG,cAAc,CAAC,aAAa,CAAC,GAC1G,SAAS,CAAC;IACN,iBAAiB,CACtB,KAAK,EAAE,OAAO,CAAC,cAAc,EAAE,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,IAAI,GAAG,cAAc,CAAC,aAAa,CAAC,GAC1G,MAAM,CAAC;IACH,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC;IA4B7D,cAAc,CAAC,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,QAiBtE;IAED;;;;;;;;OAQG;IACI,iBAAiB,CACtB,eAAe,EAAE,MAAM,GAErB;QAAE,QAAQ,EAAE,IAAI,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAC;QAAC,WAAW,EAAE,IAAI,CAAA;KAAE,GAC1D;QAAE,QAAQ,EAAE,KAAK,CAAC;QAAC,QAAQ,EAAE,SAAS,CAAC;QAAC,WAAW,EAAE,KAAK,CAAA;KAAE,GAC5D;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,CAwDhE;CACF"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { CHECKPOINT_ASSEMBLE_TIME, CHECKPOINT_INITIALIZATION_TIME, DEFAULT_P2P_PROPAGATION_TIME, MIN_EXECUTION_TIME } from '@aztec/stdlib/timetable';
|
|
1
|
+
import { CHECKPOINT_ASSEMBLE_TIME, CHECKPOINT_INITIALIZATION_TIME, DEFAULT_P2P_PROPAGATION_TIME, MIN_EXECUTION_TIME, createCheckpointTimingModel } from '@aztec/stdlib/timetable';
|
|
2
2
|
import { SequencerTooSlowError } from './errors.js';
|
|
3
3
|
import { SequencerState } from './utils.js';
|
|
4
4
|
export class SequencerTimetable {
|
|
5
5
|
metrics;
|
|
6
6
|
log;
|
|
7
|
+
checkpointTiming;
|
|
7
8
|
/**
|
|
8
9
|
* How late into the slot can we be to start working. Computed as the total time needed for assembling and publishing a block,
|
|
9
10
|
* assuming an execution time equal to `minExecutionTime`, subtracted from the slot duration. This means that, if the proposer
|
|
@@ -37,6 +38,11 @@ export class SequencerTimetable {
|
|
|
37
38
|
/** Whether assertTimeLeft will throw if not enough time. */ enforce;
|
|
38
39
|
/** Duration per block when building multiple blocks per slot (undefined = single block per slot) */ blockDuration;
|
|
39
40
|
/** Maximum number of blocks that can be built in this slot configuration */ maxNumberOfBlocks;
|
|
41
|
+
/** Whether pipelining is enabled (checkpoint finalization deferred to next slot). */ pipelining;
|
|
42
|
+
/**
|
|
43
|
+
* How far into the target slot attestation collection can extend when pipelining.
|
|
44
|
+
* Covers validator re-execution (one block duration) plus one-way attestation return.
|
|
45
|
+
*/ pipeliningAttestationGracePeriod;
|
|
40
46
|
constructor(opts, metrics, log){
|
|
41
47
|
this.metrics = metrics;
|
|
42
48
|
this.log = log;
|
|
@@ -46,40 +52,28 @@ export class SequencerTimetable {
|
|
|
46
52
|
this.ethereumSlotDuration = opts.ethereumSlotDuration;
|
|
47
53
|
this.aztecSlotDuration = opts.aztecSlotDuration;
|
|
48
54
|
this.l1PublishingTime = opts.l1PublishingTime;
|
|
49
|
-
this.p2pPropagationTime = opts.p2pPropagationTime ?? DEFAULT_P2P_PROPAGATION_TIME;
|
|
50
55
|
this.blockDuration = opts.blockDurationMs ? opts.blockDurationMs / 1000 : undefined;
|
|
51
56
|
this.enforce = opts.enforce;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
this.pipelining = opts.pipelining ?? false;
|
|
58
|
+
this.checkpointTiming = createCheckpointTimingModel({
|
|
59
|
+
aztecSlotDuration: this.aztecSlotDuration,
|
|
60
|
+
ethereumSlotDuration: this.ethereumSlotDuration,
|
|
61
|
+
blockDuration: this.blockDuration,
|
|
62
|
+
l1PublishingTime: this.l1PublishingTime,
|
|
63
|
+
p2pPropagationTime: opts.p2pPropagationTime ?? DEFAULT_P2P_PROPAGATION_TIME,
|
|
64
|
+
pipelining: this.pipelining
|
|
65
|
+
});
|
|
66
|
+
this.p2pPropagationTime = this.checkpointTiming.p2pPropagationTime;
|
|
67
|
+
this.checkpointAssembleTime = this.checkpointTiming.checkpointAssembleTime;
|
|
68
|
+
this.checkpointInitializationTime = this.checkpointTiming.checkpointInitializationTime;
|
|
69
|
+
this.minExecutionTime = this.checkpointTiming.minExecutionTime;
|
|
63
70
|
// Calculate initialization offset - estimate of time needed for sync + proposer check
|
|
64
71
|
// This is the baseline for all sub-slot deadlines
|
|
65
|
-
this.initializationOffset = this.checkpointInitializationTime;
|
|
66
|
-
|
|
67
|
-
this.
|
|
68
|
-
this.
|
|
69
|
-
|
|
70
|
-
if (!this.blockDuration) {
|
|
71
|
-
this.maxNumberOfBlocks = 1; // Single block per slot
|
|
72
|
-
} else {
|
|
73
|
-
const timeReservedAtEnd = this.blockDuration + // Last sub-slot for validator re-execution
|
|
74
|
-
this.checkpointFinalizationTime; // Checkpoint finalization
|
|
75
|
-
const timeAvailableForBlocks = this.aztecSlotDuration - this.initializationOffset - timeReservedAtEnd;
|
|
76
|
-
this.maxNumberOfBlocks = Math.floor(timeAvailableForBlocks / this.blockDuration);
|
|
77
|
-
}
|
|
78
|
-
// Minimum work to do within a slot for building a block with the minimum time for execution and publishing its checkpoint
|
|
79
|
-
const minWorkToDo = this.initializationOffset + this.minExecutionTime * 2 + // Execution and reexecution
|
|
80
|
-
this.checkpointFinalizationTime;
|
|
81
|
-
const initializeDeadline = this.aztecSlotDuration - minWorkToDo;
|
|
82
|
-
this.initializeDeadline = initializeDeadline;
|
|
72
|
+
this.initializationOffset = this.checkpointTiming.checkpointInitializationTime;
|
|
73
|
+
this.checkpointFinalizationTime = this.checkpointTiming.checkpointFinalizationTime;
|
|
74
|
+
this.pipeliningAttestationGracePeriod = this.checkpointTiming.pipeliningAttestationGracePeriod;
|
|
75
|
+
this.maxNumberOfBlocks = this.checkpointTiming.calculateMaxBlocksPerSlot();
|
|
76
|
+
this.initializeDeadline = this.checkpointTiming.initializeDeadline;
|
|
83
77
|
this.log?.info(`Sequencer timetable initialized with ${this.maxNumberOfBlocks} blocks per slot (${this.enforce ? 'enforced' : 'not enforced'})`, {
|
|
84
78
|
ethereumSlotDuration: this.ethereumSlotDuration,
|
|
85
79
|
aztecSlotDuration: this.aztecSlotDuration,
|
|
@@ -90,14 +84,28 @@ export class SequencerTimetable {
|
|
|
90
84
|
blockAssembleTime: this.checkpointAssembleTime,
|
|
91
85
|
initializeDeadline: this.initializeDeadline,
|
|
92
86
|
enforce: this.enforce,
|
|
93
|
-
|
|
87
|
+
pipelining: this.pipelining,
|
|
88
|
+
pipeliningAttestationGracePeriod: this.pipeliningAttestationGracePeriod,
|
|
89
|
+
minWorkToDo: this.checkpointTiming.minimumBuildSlotWork,
|
|
94
90
|
blockDuration: this.blockDuration,
|
|
95
91
|
maxNumberOfBlocks: this.maxNumberOfBlocks
|
|
96
92
|
});
|
|
97
|
-
if (initializeDeadline <= 0) {
|
|
98
|
-
throw new Error(`Block proposal initialize deadline cannot be negative (got ${initializeDeadline} from total time needed ${
|
|
93
|
+
if (this.initializeDeadline <= 0) {
|
|
94
|
+
throw new Error(`Block proposal initialize deadline cannot be negative (got ${this.initializeDeadline} from total time needed ${this.checkpointTiming.minimumBuildSlotWork} and a slot duration of ${this.aztecSlotDuration}).`);
|
|
99
95
|
}
|
|
100
96
|
}
|
|
97
|
+
getCheckpointAssemblyDeadline() {
|
|
98
|
+
return this.checkpointTiming.checkpointAssemblyDeadline;
|
|
99
|
+
}
|
|
100
|
+
getCheckpointAttestationDeadline() {
|
|
101
|
+
return this.checkpointTiming.checkpointAttestationDeadline;
|
|
102
|
+
}
|
|
103
|
+
getCheckpointAttestationStartDeadline() {
|
|
104
|
+
return this.checkpointTiming.checkpointAttestationStartDeadline;
|
|
105
|
+
}
|
|
106
|
+
getCheckpointPublishingDeadline() {
|
|
107
|
+
return this.checkpointTiming.checkpointPublishingDeadline;
|
|
108
|
+
}
|
|
101
109
|
getMaxAllowedTime(state) {
|
|
102
110
|
switch(state){
|
|
103
111
|
case SequencerState.STOPPED:
|
|
@@ -113,10 +121,11 @@ export class SequencerTimetable {
|
|
|
113
121
|
case SequencerState.WAITING_UNTIL_NEXT_BLOCK:
|
|
114
122
|
return this.initializeDeadline + this.checkpointInitializationTime;
|
|
115
123
|
case SequencerState.ASSEMBLING_CHECKPOINT:
|
|
124
|
+
return this.getCheckpointAssemblyDeadline();
|
|
116
125
|
case SequencerState.COLLECTING_ATTESTATIONS:
|
|
117
|
-
return this.
|
|
126
|
+
return this.getCheckpointAttestationStartDeadline();
|
|
118
127
|
case SequencerState.PUBLISHING_CHECKPOINT:
|
|
119
|
-
return this.
|
|
128
|
+
return this.getCheckpointPublishingDeadline();
|
|
120
129
|
default:
|
|
121
130
|
{
|
|
122
131
|
const _exhaustiveCheck = state;
|
package/dest/test/utils.d.ts
CHANGED
|
@@ -50,4 +50,4 @@ export declare function setupTxsAndBlock(p2p: MockProxy<P2P>, globalVariables: G
|
|
|
50
50
|
txs: Tx[];
|
|
51
51
|
block: L2Block;
|
|
52
52
|
}>;
|
|
53
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUM1RSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzVELE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV0QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxxQkFBcUIsRUFBRSxrQkFBa0IsRUFBb0IsTUFBTSxtQkFBbUIsQ0FBQztBQU8vRyxPQUFPLEVBQWUsZUFBZSxFQUFFLEtBQUssRUFBRSxFQUFvQyxNQUFNLGtCQUFrQixDQUFDO0FBRTNHLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBR3BELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBRTdGOztHQUVHO0FBQ0gsd0JBQXNCLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FNckU7QUFFRDs7R0FFRztBQUNILHdCQUFzQixTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLGVBQWUsRUFBRSxlQUFlLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQWdCN0Y7QUFFRDs7R0FFRztBQUNILHdCQUFnQixjQUFjLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUluRTtBQUVEOztHQUVHO0FBQ0gsd0JBQXVCLGNBQWMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcscUJBQXFCLENBQUMsRUFBRSxDQUFDLENBSW5GO0FBRUQ7O0dBRUc7QUFDSCx3QkFBZ0Isb0JBQW9CLENBQUMsTUFBTSxFQUFFLGVBQWUsR0FBRyxvQkFBb0IsRUFBRSxDQUdwRjtBQXVCRDs7R0FFRztBQUNILHdCQUFnQixtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEdBQUcsYUFBYSxDQVd2RjtBQUVEOztHQUVHO0FBQ0gsd0JBQWdCLHdCQUF3QixDQUN0QyxLQUFLLEVBQUUsT0FBTyxFQUNkLG1CQUFtQixFQUFFLFNBQVMsRUFDOUIsY0FBYyxDQUFDLEVBQUUsU0FBUyxFQUMxQixxQkFBcUIsR0FBRSxNQUFXLEdBQ2pDLGtCQUFrQixDQWdCcEI7QUFFRDs7OztHQUlHO0FBQ0gsd0JBQWdCLDJCQUEyQixDQUN6QyxLQUFLLEVBQUUsT0FBTyxFQUNkLFNBQVMsRUFBRSxTQUFTLEVBQ3BCLE1BQU0sRUFBRSxVQUFVLEVBQ2xCLHFCQUFxQixHQUFFLE1BQVcsR0FDakMscUJBQXFCLENBYXZCO0FBRUQ7OztHQUdHO0FBQ0gsd0JBQXNCLGdCQUFnQixDQUNwQyxHQUFHLEVBQUUsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUNuQixlQUFlLEVBQUUsZUFBZSxFQUNoQyxPQUFPLEVBQUUsTUFBTSxFQUNmLE9BQU8sRUFBRSxFQUFFLEdBQ1YsT0FBTyxDQUFDO0lBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQTtDQUFFLENBQUMsQ0FLeEMifQ==
|
package/dest/test/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAoB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAoB,MAAM,mBAAmB,CAAC;AAO/G,OAAO,EAAe,eAAe,EAAE,KAAK,EAAE,EAAoC,MAAM,kBAAkB,CAAC;AAE3G,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAE7F;;GAEG;AACH,wBAAsB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAMrE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB7F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,IAAI,CAInE;AAED;;GAEG;AACH,wBAAuB,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,qBAAqB,CAAC,EAAE,CAAC,CAInF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,oBAAoB,EAAE,CAGpF;AAuBD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,aAAa,CAWvF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,mBAAmB,EAAE,SAAS,EAC9B,cAAc,CAAC,EAAE,SAAS,EAC1B,qBAAqB,GAAE,MAAW,GACjC,kBAAkB,CAgBpB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,UAAU,EAClB,qBAAqB,GAAE,MAAW,GACjC,qBAAqB,CAavB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,EACnB,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,EAAE,GACV,OAAO,CAAC;IAAE,GAAG,EAAE,EAAE,EAAE,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAKxC"}
|
package/dest/test/utils.js
CHANGED
|
@@ -7,7 +7,7 @@ import { PublicDataWrite } from '@aztec/stdlib/avm';
|
|
|
7
7
|
import { CommitteeAttestation, L2Block } from '@aztec/stdlib/block';
|
|
8
8
|
import { BlockProposal, CheckpointAttestation, CheckpointProposal, ConsensusPayload } from '@aztec/stdlib/p2p';
|
|
9
9
|
import { CheckpointHeader } from '@aztec/stdlib/rollup';
|
|
10
|
-
import { makeAppendOnlyTreeSnapshot, mockTxForRollup } from '@aztec/stdlib/testing';
|
|
10
|
+
import { TEST_COORDINATION_SIGNATURE_CONTEXT, makeAppendOnlyTreeSnapshot, mockTxForRollup } from '@aztec/stdlib/testing';
|
|
11
11
|
import { BlockHeader, makeProcessedTxFromPrivateOnlyTx } from '@aztec/stdlib/tx';
|
|
12
12
|
// Re-export mock classes from their dedicated file
|
|
13
13
|
export { MockCheckpointBuilder, MockCheckpointsBuilder } from './mock_checkpoint_builder.js';
|
|
@@ -64,14 +64,14 @@ export { MockCheckpointBuilder, MockCheckpointsBuilder } from './mock_checkpoint
|
|
|
64
64
|
* Creates a block proposal from a block and signature
|
|
65
65
|
*/ export function createBlockProposal(block, signature) {
|
|
66
66
|
const txHashes = block.body.txEffects.map((tx)=>tx.txHash);
|
|
67
|
-
return new BlockProposal(block.header, block.indexWithinCheckpoint, Fr.ZERO, block.archive.root, txHashes, signature);
|
|
67
|
+
return new BlockProposal(block.header, block.indexWithinCheckpoint, Fr.ZERO, block.archive.root, txHashes, signature, TEST_COORDINATION_SIGNATURE_CONTEXT);
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
70
70
|
* Creates a checkpoint proposal from a block and signature
|
|
71
71
|
*/ export function createCheckpointProposal(block, checkpointSignature, blockSignature, feeAssetPriceModifier = 0n) {
|
|
72
72
|
const txHashes = block.body.txEffects.map((tx)=>tx.txHash);
|
|
73
73
|
const checkpointHeader = createCheckpointHeaderFromBlock(block);
|
|
74
|
-
return new CheckpointProposal(checkpointHeader, block.archive.root, feeAssetPriceModifier, checkpointSignature, {
|
|
74
|
+
return new CheckpointProposal(checkpointHeader, block.archive.root, feeAssetPriceModifier, checkpointSignature, TEST_COORDINATION_SIGNATURE_CONTEXT, {
|
|
75
75
|
blockHeader: block.header,
|
|
76
76
|
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
77
77
|
txHashes,
|
|
@@ -84,10 +84,11 @@ export { MockCheckpointBuilder, MockCheckpointsBuilder } from './mock_checkpoint
|
|
|
84
84
|
* In production, the sender is recovered from the signature.
|
|
85
85
|
*/ export function createCheckpointAttestation(block, signature, sender, feeAssetPriceModifier = 0n) {
|
|
86
86
|
const checkpointHeader = createCheckpointHeaderFromBlock(block);
|
|
87
|
-
const payload = new ConsensusPayload(checkpointHeader, block.archive.root, feeAssetPriceModifier);
|
|
87
|
+
const payload = new ConsensusPayload(checkpointHeader, block.archive.root, feeAssetPriceModifier, TEST_COORDINATION_SIGNATURE_CONTEXT);
|
|
88
88
|
const attestation = new CheckpointAttestation(payload, signature, signature);
|
|
89
|
-
//
|
|
90
|
-
attestation.
|
|
89
|
+
// Bypass signature recovery for testing since we use random signatures
|
|
90
|
+
attestation.getSender = ()=>sender;
|
|
91
|
+
attestation.getProposer = ()=>sender;
|
|
91
92
|
return attestation;
|
|
92
93
|
}
|
|
93
94
|
/**
|