@aztec/sequencer-client 0.0.1-commit.88c5703d4 → 0.0.1-commit.88e6f9396
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 +1 -13
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +21 -67
- package/dest/config.d.ts +3 -3
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +2 -4
- package/dest/publisher/sequencer-publisher.d.ts +6 -4
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +13 -7
- package/dest/sequencer/checkpoint_proposal_job.d.ts +12 -4
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +122 -73
- package/dest/sequencer/events.d.ts +2 -1
- package/dest/sequencer/events.d.ts.map +1 -1
- package/dest/sequencer/metrics.d.ts +5 -1
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +11 -0
- package/dest/sequencer/sequencer.d.ts +5 -5
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +57 -45
- package/dest/test/mock_checkpoint_builder.d.ts +4 -8
- package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
- package/package.json +27 -27
- package/src/client/sequencer-client.ts +28 -86
- package/src/config.ts +4 -3
- package/src/publisher/sequencer-publisher.ts +17 -9
- package/src/sequencer/checkpoint_proposal_job.ts +164 -82
- package/src/sequencer/events.ts +1 -1
- package/src/sequencer/metrics.ts +14 -0
- package/src/sequencer/sequencer.ts +82 -51
- package/src/test/mock_checkpoint_builder.ts +3 -3
|
@@ -446,7 +446,7 @@ import { Timer } from '@aztec/foundation/timer';
|
|
|
446
446
|
import { isErrorClass, unfreeze } from '@aztec/foundation/types';
|
|
447
447
|
import { CommitteeAttestationsAndSigners, MaliciousCommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
448
448
|
import { validateCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
449
|
-
import { getSlotStartBuildTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
449
|
+
import { getSlotStartBuildTimestamp, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
450
450
|
import { Gas } from '@aztec/stdlib/gas';
|
|
451
451
|
import { InsufficientValidTxsError } from '@aztec/stdlib/interfaces/server';
|
|
452
452
|
import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
|
|
@@ -462,7 +462,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
462
462
|
return {
|
|
463
463
|
// nullish operator needed for tests
|
|
464
464
|
[Attributes.COINBASE]: this.validatorClient.getCoinbaseForAttestor(this.attestorAddress)?.toString(),
|
|
465
|
-
[Attributes.SLOT_NUMBER]: this.
|
|
465
|
+
[Attributes.SLOT_NUMBER]: this.targetSlot
|
|
466
466
|
};
|
|
467
467
|
}), _dec2 = trackSpan('CheckpointProposalJob.buildBlocksForCheckpoint'), _dec3 = trackSpan('CheckpointProposalJob.waitUntilNextSubslot'), _dec4 = trackSpan('CheckpointProposalJob.buildSingleBlock'), _dec5 = trackSpan('CheckpointProposalJob.waitForMinTxs'), _dec6 = trackSpan('CheckpointProposalJob.waitForAttestations'), _dec7 = trackSpan('CheckpointProposalJob.waitUntilTimeInSlot');
|
|
468
468
|
/**
|
|
@@ -471,8 +471,10 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
471
471
|
* as well as enqueueing votes for slashing and governance proposals. This class is created from
|
|
472
472
|
* the Sequencer once the check for being the proposer for the slot has succeeded.
|
|
473
473
|
*/ export class CheckpointProposalJob {
|
|
474
|
-
|
|
475
|
-
|
|
474
|
+
slotNow;
|
|
475
|
+
targetSlot;
|
|
476
|
+
epochNow;
|
|
477
|
+
targetEpoch;
|
|
476
478
|
checkpointNumber;
|
|
477
479
|
syncedToBlockNumber;
|
|
478
480
|
proposer;
|
|
@@ -542,10 +544,12 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
542
544
|
], []));
|
|
543
545
|
}
|
|
544
546
|
log;
|
|
545
|
-
constructor(
|
|
547
|
+
constructor(slotNow, targetSlot, epochNow, targetEpoch, checkpointNumber, syncedToBlockNumber, // TODO(palla/mbps): Can we remove the proposer in favor of attestorAddress? Need to check fisherman-node flows.
|
|
546
548
|
proposer, publisher, attestorAddress, invalidateCheckpoint, validatorClient, globalsBuilder, p2pClient, worldState, l1ToL2MessageSource, l2BlockSource, checkpointsBuilder, blockSink, l1Constants, config, timetable, slasherClient, epochCache, dateProvider, metrics, eventEmitter, setStateFn, tracer, bindings){
|
|
547
|
-
this.
|
|
548
|
-
this.
|
|
549
|
+
this.slotNow = slotNow;
|
|
550
|
+
this.targetSlot = targetSlot;
|
|
551
|
+
this.epochNow = epochNow;
|
|
552
|
+
this.targetEpoch = targetEpoch;
|
|
549
553
|
this.checkpointNumber = checkpointNumber;
|
|
550
554
|
this.syncedToBlockNumber = syncedToBlockNumber;
|
|
551
555
|
this.proposer = proposer;
|
|
@@ -573,9 +577,15 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
573
577
|
_initProto(this);
|
|
574
578
|
this.log = createLogger('sequencer:checkpoint-proposal', {
|
|
575
579
|
...bindings,
|
|
576
|
-
instanceId: `slot-${
|
|
580
|
+
instanceId: `slot-${this.slotNow}`
|
|
577
581
|
});
|
|
578
582
|
}
|
|
583
|
+
/** The wall-clock slot during which the proposer builds. */ get slot() {
|
|
584
|
+
return this.slotNow;
|
|
585
|
+
}
|
|
586
|
+
/** The wall-clock epoch. */ get epoch() {
|
|
587
|
+
return this.epochNow;
|
|
588
|
+
}
|
|
579
589
|
/**
|
|
580
590
|
* Executes the checkpoint proposal job.
|
|
581
591
|
* Returns the published checkpoint if successful, undefined otherwise.
|
|
@@ -583,7 +593,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
583
593
|
// Enqueue governance and slashing votes (returns promises that will be awaited later)
|
|
584
594
|
// In fisherman mode, we simulate slashing but don't actually publish to L1
|
|
585
595
|
// These are constant for the whole slot, so we only enqueue them once
|
|
586
|
-
const votesPromises = new CheckpointVoter(this.
|
|
596
|
+
const votesPromises = new CheckpointVoter(this.targetSlot, this.publisher, this.attestorAddress, this.validatorClient, this.slasherClient, this.l1Constants, this.config, this.metrics, this.log).enqueueVotes();
|
|
587
597
|
// Build and propose the checkpoint. This will enqueue the request on the publisher if a checkpoint is built.
|
|
588
598
|
const checkpoint = await this.proposeCheckpoint();
|
|
589
599
|
// Wait until the voting promises have resolved, so all requests are enqueued (not sent)
|
|
@@ -596,6 +606,24 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
596
606
|
await this.handleCheckpointEndAsFisherman(checkpoint);
|
|
597
607
|
return;
|
|
598
608
|
}
|
|
609
|
+
// If pipelining, wait until the submission slot so L1 recognizes the pipelined proposer
|
|
610
|
+
if (this.epochCache.isProposerPipeliningEnabled()) {
|
|
611
|
+
const submissionSlotTimestamp = getTimestampForSlot(this.targetSlot, this.l1Constants) - BigInt(this.l1Constants.ethereumSlotDuration);
|
|
612
|
+
this.log.info(`Waiting until submission slot ${this.targetSlot} for L1 submission`, {
|
|
613
|
+
slot: this.slot,
|
|
614
|
+
submissionSlot: this.targetSlot,
|
|
615
|
+
submissionSlotTimestamp
|
|
616
|
+
});
|
|
617
|
+
await sleepUntil(new Date(Number(submissionSlotTimestamp) * 1000), this.dateProvider.nowAsDate());
|
|
618
|
+
// After waking, verify the parent checkpoint wasn't pruned during the sleep.
|
|
619
|
+
// We check L1's pending tip directly instead of canProposeAt, which also validates the proposer
|
|
620
|
+
// identity and would fail because the timestamp resolves to a different slot's proposer.
|
|
621
|
+
const l1Tips = await this.publisher.rollupContract.getTips();
|
|
622
|
+
if (l1Tips.pending < this.checkpointNumber - 1) {
|
|
623
|
+
this.log.warn(`Parent checkpoint was pruned during pipelining sleep (L1 pending=${l1Tips.pending}, expected>=${this.checkpointNumber - 1}), skipping L1 submission for checkpoint ${this.checkpointNumber}`);
|
|
624
|
+
return undefined;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
599
627
|
// Then send everything to L1
|
|
600
628
|
const l1Response = await this.publisher.sendRequests();
|
|
601
629
|
const proposedAction = l1Response?.successfulActions.find((a)=>a === 'propose');
|
|
@@ -627,19 +655,26 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
627
655
|
const coinbase = this.validatorClient.getCoinbaseForAttestor(this.attestorAddress);
|
|
628
656
|
const feeRecipient = this.validatorClient.getFeeRecipientForAttestor(this.attestorAddress);
|
|
629
657
|
// Start the checkpoint
|
|
630
|
-
this.setStateFn(SequencerState.INITIALIZING_CHECKPOINT, this.
|
|
631
|
-
this.
|
|
658
|
+
this.setStateFn(SequencerState.INITIALIZING_CHECKPOINT, this.targetSlot);
|
|
659
|
+
this.log.info(`Starting checkpoint proposal`, {
|
|
660
|
+
buildSlot: this.slot,
|
|
661
|
+
submissionSlot: this.targetSlot,
|
|
662
|
+
pipelining: this.epochCache.isProposerPipeliningEnabled(),
|
|
663
|
+
proposer: this.proposer?.toString(),
|
|
664
|
+
coinbase: coinbase.toString()
|
|
665
|
+
});
|
|
666
|
+
this.metrics.incOpenSlot(this.targetSlot, this.proposer?.toString() ?? 'unknown');
|
|
632
667
|
// Enqueues checkpoint invalidation (constant for the whole slot)
|
|
633
668
|
if (this.invalidateCheckpoint && !this.config.skipInvalidateBlockAsProposer) {
|
|
634
669
|
this.publisher.enqueueInvalidateCheckpoint(this.invalidateCheckpoint);
|
|
635
670
|
}
|
|
636
671
|
// Create checkpoint builder for the slot
|
|
637
|
-
const checkpointGlobalVariables = await this.globalsBuilder.buildCheckpointGlobalVariables(coinbase, feeRecipient, this.
|
|
672
|
+
const checkpointGlobalVariables = await this.globalsBuilder.buildCheckpointGlobalVariables(coinbase, feeRecipient, this.targetSlot);
|
|
638
673
|
// Collect L1 to L2 messages for the checkpoint and compute their hash
|
|
639
674
|
const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(this.checkpointNumber);
|
|
640
675
|
const inHash = computeInHashFromL1ToL2Messages(l1ToL2Messages);
|
|
641
676
|
// Collect the out hashes of all the checkpoints before this one in the same epoch
|
|
642
|
-
const previousCheckpointOutHashes = (await this.l2BlockSource.getCheckpointsDataForEpoch(this.
|
|
677
|
+
const previousCheckpointOutHashes = (await this.l2BlockSource.getCheckpointsDataForEpoch(this.targetEpoch)).filter((c)=>c.checkpointNumber < this.checkpointNumber).map((c)=>c.checkpointOutHash);
|
|
643
678
|
// Get the fee asset price modifier from the oracle
|
|
644
679
|
const feeAssetPriceModifier = await this.publisher.getFeeAssetPriceModifier();
|
|
645
680
|
const fork = _ts_add_disposable_resource(env, await this.worldState.fork(this.syncedToBlockNumber, {
|
|
@@ -674,18 +709,18 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
674
709
|
throw err;
|
|
675
710
|
}
|
|
676
711
|
if (blocksInCheckpoint.length === 0) {
|
|
677
|
-
this.log.warn(`No blocks were built for slot ${this.
|
|
678
|
-
slot: this.
|
|
712
|
+
this.log.warn(`No blocks were built for slot ${this.targetSlot}`, {
|
|
713
|
+
slot: this.targetSlot
|
|
679
714
|
});
|
|
680
715
|
this.eventEmitter.emit('checkpoint-empty', {
|
|
681
|
-
slot: this.
|
|
716
|
+
slot: this.targetSlot
|
|
682
717
|
});
|
|
683
718
|
return undefined;
|
|
684
719
|
}
|
|
685
720
|
const minBlocksForCheckpoint = this.config.minBlocksForCheckpoint;
|
|
686
721
|
if (minBlocksForCheckpoint !== undefined && blocksInCheckpoint.length < minBlocksForCheckpoint) {
|
|
687
722
|
this.log.warn(`Checkpoint has fewer blocks than minimum (${blocksInCheckpoint.length} < ${minBlocksForCheckpoint}), skipping proposal`, {
|
|
688
|
-
slot: this.
|
|
723
|
+
slot: this.targetSlot,
|
|
689
724
|
blocksBuilt: blocksInCheckpoint.length,
|
|
690
725
|
minBlocksForCheckpoint
|
|
691
726
|
});
|
|
@@ -693,9 +728,10 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
693
728
|
}
|
|
694
729
|
// Assemble and broadcast the checkpoint proposal, including the last block that was not
|
|
695
730
|
// broadcasted yet, and wait to collect the committee attestations.
|
|
696
|
-
this.setStateFn(SequencerState.ASSEMBLING_CHECKPOINT, this.
|
|
731
|
+
this.setStateFn(SequencerState.ASSEMBLING_CHECKPOINT, this.targetSlot);
|
|
697
732
|
const checkpoint = await checkpointBuilder.completeCheckpoint();
|
|
698
|
-
// Final validation
|
|
733
|
+
// Final validation: per-block limits are only checked if the operator set them explicitly.
|
|
734
|
+
// Otherwise, checkpoint-level budgets were already enforced by the redistribution logic.
|
|
699
735
|
try {
|
|
700
736
|
validateCheckpoint(checkpoint, {
|
|
701
737
|
rollupManaLimit: this.l1Constants.rollupManaLimit,
|
|
@@ -714,8 +750,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
714
750
|
this.metrics.recordCheckpointBuild(checkpointBuildTimer.ms(), blocksInCheckpoint.length, checkpoint.getStats().txCount, Number(checkpoint.header.totalManaUsed.toBigInt()));
|
|
715
751
|
// Do not collect attestations nor publish to L1 in fisherman mode
|
|
716
752
|
if (this.config.fishermanMode) {
|
|
717
|
-
this.log.info(`Built checkpoint for slot ${this.
|
|
718
|
-
slot: this.
|
|
753
|
+
this.log.info(`Built checkpoint for slot ${this.targetSlot} with ${blocksInCheckpoint.length} blocks. ` + `Skipping proposal in fisherman mode.`, {
|
|
754
|
+
slot: this.targetSlot,
|
|
719
755
|
checkpoint: checkpoint.header.toInspect(),
|
|
720
756
|
blocksBuilt: blocksInCheckpoint.length
|
|
721
757
|
});
|
|
@@ -732,7 +768,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
732
768
|
const proposal = await this.validatorClient.createCheckpointProposal(checkpoint.header, checkpoint.archive.root, feeAssetPriceModifier, lastBlock, this.proposer, checkpointProposalOptions);
|
|
733
769
|
const blockProposedAt = this.dateProvider.now();
|
|
734
770
|
await this.p2pClient.broadcastCheckpointProposal(proposal);
|
|
735
|
-
this.setStateFn(SequencerState.COLLECTING_ATTESTATIONS, this.
|
|
771
|
+
this.setStateFn(SequencerState.COLLECTING_ATTESTATIONS, this.targetSlot);
|
|
736
772
|
const attestations = await this.waitForAttestations(proposal);
|
|
737
773
|
const blockAttestedAt = this.dateProvider.now();
|
|
738
774
|
this.metrics.recordCheckpointAttestationDelay(blockAttestedAt - blockProposedAt);
|
|
@@ -740,7 +776,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
740
776
|
const signer = this.proposer ?? this.publisher.getSenderAddress();
|
|
741
777
|
let attestationsSignature;
|
|
742
778
|
try {
|
|
743
|
-
attestationsSignature = await this.validatorClient.signAttestationsAndSigners(attestations, signer, this.
|
|
779
|
+
attestationsSignature = await this.validatorClient.signAttestationsAndSigners(attestations, signer, this.targetSlot, this.checkpointNumber);
|
|
744
780
|
} catch (err) {
|
|
745
781
|
// We shouldn't really get here since we yield to another HA node
|
|
746
782
|
// as soon as we see these errors when creating block or checkpoint proposals.
|
|
@@ -750,10 +786,10 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
750
786
|
throw err;
|
|
751
787
|
}
|
|
752
788
|
// Enqueue publishing the checkpoint to L1
|
|
753
|
-
this.setStateFn(SequencerState.PUBLISHING_CHECKPOINT, this.
|
|
789
|
+
this.setStateFn(SequencerState.PUBLISHING_CHECKPOINT, this.targetSlot);
|
|
754
790
|
const aztecSlotDuration = this.l1Constants.slotDuration;
|
|
755
|
-
const
|
|
756
|
-
const txTimeoutAt = new Date((
|
|
791
|
+
const submissionSlotStart = Number(getTimestampForSlot(this.targetSlot, this.l1Constants));
|
|
792
|
+
const txTimeoutAt = new Date((submissionSlotStart + aztecSlotDuration) * 1000);
|
|
757
793
|
// If we have been configured to potentially skip publishing checkpoint then roll the dice here
|
|
758
794
|
if (this.config.skipPublishingCheckpointsPercent !== undefined && this.config.skipPublishingCheckpointsPercent > 0) {
|
|
759
795
|
const result = Math.max(0, randomInt(100));
|
|
@@ -799,7 +835,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
799
835
|
const timingInfo = this.timetable.canStartNextBlock(secondsIntoSlot);
|
|
800
836
|
if (!timingInfo.canStart) {
|
|
801
837
|
this.log.debug(`Not enough time left in slot to start another block`, {
|
|
802
|
-
slot: this.
|
|
838
|
+
slot: this.targetSlot,
|
|
803
839
|
blocksBuilt,
|
|
804
840
|
secondsIntoSlot
|
|
805
841
|
});
|
|
@@ -828,8 +864,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
828
864
|
} else if ('error' in buildResult) {
|
|
829
865
|
// If there was an error building the block, just exit the loop and give up the rest of the slot
|
|
830
866
|
if (!(buildResult.error instanceof SequencerInterruptedError)) {
|
|
831
|
-
this.log.warn(`Halting block building for slot ${this.
|
|
832
|
-
slot: this.
|
|
867
|
+
this.log.warn(`Halting block building for slot ${this.targetSlot}`, {
|
|
868
|
+
slot: this.targetSlot,
|
|
833
869
|
blocksBuilt,
|
|
834
870
|
error: buildResult.error
|
|
835
871
|
});
|
|
@@ -838,15 +874,13 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
838
874
|
}
|
|
839
875
|
const { block, usedTxs } = buildResult;
|
|
840
876
|
blocksInCheckpoint.push(block);
|
|
841
|
-
// Sync the proposed block to the archiver to make it available
|
|
842
|
-
// We wait for the sync to succeed, as this helps catch consistency errors, even if it means we lose some time for block-building
|
|
843
|
-
// If this throws, we abort the entire checkpoint
|
|
844
|
-
await this.syncProposedBlockToArchiver(block);
|
|
845
877
|
usedTxs.forEach((tx)=>txHashesAlreadyIncluded.add(tx.txHash.toString()));
|
|
846
|
-
// If this is the last block,
|
|
878
|
+
// If this is the last block, sync it to the archiver and exit the loop
|
|
879
|
+
// so we can build the checkpoint and start collecting attestations.
|
|
847
880
|
if (timingInfo.isLastBlock) {
|
|
848
|
-
this.
|
|
849
|
-
|
|
881
|
+
await this.syncProposedBlockToArchiver(block);
|
|
882
|
+
this.log.verbose(`Completed final block ${blockNumber} for slot ${this.targetSlot}`, {
|
|
883
|
+
slot: this.targetSlot,
|
|
850
884
|
blockNumber,
|
|
851
885
|
blocksBuilt
|
|
852
886
|
});
|
|
@@ -856,17 +890,22 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
856
890
|
};
|
|
857
891
|
break;
|
|
858
892
|
}
|
|
859
|
-
//
|
|
860
|
-
//
|
|
861
|
-
if
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
893
|
+
// Broadcast the block proposal (unless we're in fisherman mode) unless the block is the last one,
|
|
894
|
+
// in which case we'll broadcast it along with the checkpoint at the end of the loop.
|
|
895
|
+
// Note that we only send the block to the archiver if we manage to create the proposal, so if there's
|
|
896
|
+
// a HA error we don't pollute our archiver with a block that won't make it to the chain.
|
|
897
|
+
const proposal = await this.createBlockProposal(block, inHash, usedTxs, blockProposalOptions);
|
|
898
|
+
// Sync the proposed block to the archiver to make it available, only after we've managed to sign the proposal.
|
|
899
|
+
// We wait for the sync to succeed, as this helps catch consistency errors, even if it means we lose some time for block-building.
|
|
900
|
+
// If this throws, we abort the entire checkpoint.
|
|
901
|
+
await this.syncProposedBlockToArchiver(block);
|
|
902
|
+
// Once we have a signed proposal and the archiver agreed with our proposed block, then we broadcast it.
|
|
903
|
+
proposal && await this.p2pClient.broadcastProposal(proposal);
|
|
865
904
|
// Wait until the next block's start time
|
|
866
905
|
await this.waitUntilNextSubslot(timingInfo.deadline);
|
|
867
906
|
}
|
|
868
|
-
this.log.verbose(`Block building loop completed for slot ${this.
|
|
869
|
-
slot: this.
|
|
907
|
+
this.log.verbose(`Block building loop completed for slot ${this.targetSlot}`, {
|
|
908
|
+
slot: this.targetSlot,
|
|
870
909
|
blocksBuilt: blocksInCheckpoint.length
|
|
871
910
|
});
|
|
872
911
|
return {
|
|
@@ -874,16 +913,23 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
874
913
|
blockPendingBroadcast
|
|
875
914
|
};
|
|
876
915
|
}
|
|
916
|
+
/** Creates a block proposal for a given block via the validator client (unless in fisherman mode) */ createBlockProposal(block, inHash, usedTxs, blockProposalOptions) {
|
|
917
|
+
if (this.config.fishermanMode) {
|
|
918
|
+
this.log.info(`Skipping block proposal for block ${block.number} in fisherman mode`);
|
|
919
|
+
return Promise.resolve(undefined);
|
|
920
|
+
}
|
|
921
|
+
return this.validatorClient.createBlockProposal(block.header, block.indexWithinCheckpoint, inHash, block.archive.root, usedTxs, this.proposer, blockProposalOptions);
|
|
922
|
+
}
|
|
877
923
|
/** Sleeps until it is time to produce the next block in the slot */ async waitUntilNextSubslot(nextSubslotStart) {
|
|
878
|
-
this.setStateFn(SequencerState.WAITING_UNTIL_NEXT_BLOCK, this.
|
|
924
|
+
this.setStateFn(SequencerState.WAITING_UNTIL_NEXT_BLOCK, this.targetSlot);
|
|
879
925
|
this.log.verbose(`Waiting until time for the next block at ${nextSubslotStart}s into slot`, {
|
|
880
|
-
slot: this.
|
|
926
|
+
slot: this.targetSlot
|
|
881
927
|
});
|
|
882
928
|
await this.waitUntilTimeInSlot(nextSubslotStart);
|
|
883
929
|
}
|
|
884
930
|
/** Builds a single block. Called from the main block building loop. */ async buildSingleBlock(checkpointBuilder, opts) {
|
|
885
931
|
const { blockTimestamp, forceCreate, blockNumber, indexWithinCheckpoint, buildDeadline, txHashesAlreadyIncluded } = opts;
|
|
886
|
-
this.log.verbose(`Preparing block ${blockNumber} index ${indexWithinCheckpoint} at checkpoint ${this.checkpointNumber} for slot ${this.
|
|
932
|
+
this.log.verbose(`Preparing block ${blockNumber} index ${indexWithinCheckpoint} at checkpoint ${this.checkpointNumber} for slot ${this.targetSlot}`, {
|
|
887
933
|
...checkpointBuilder.getConstantData(),
|
|
888
934
|
...opts
|
|
889
935
|
});
|
|
@@ -891,15 +937,15 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
891
937
|
// Wait until we have enough txs to build the block
|
|
892
938
|
const { availableTxs, canStartBuilding, minTxs } = await this.waitForMinTxs(opts);
|
|
893
939
|
if (!canStartBuilding) {
|
|
894
|
-
this.log.warn(`Not enough txs to build block ${blockNumber} at index ${indexWithinCheckpoint} in slot ${this.
|
|
940
|
+
this.log.warn(`Not enough txs to build block ${blockNumber} at index ${indexWithinCheckpoint} in slot ${this.targetSlot} (got ${availableTxs} txs but needs ${minTxs})`, {
|
|
895
941
|
blockNumber,
|
|
896
|
-
slot: this.
|
|
942
|
+
slot: this.targetSlot,
|
|
897
943
|
indexWithinCheckpoint
|
|
898
944
|
});
|
|
899
945
|
this.eventEmitter.emit('block-tx-count-check-failed', {
|
|
900
946
|
minTxs,
|
|
901
947
|
availableTxs,
|
|
902
|
-
slot: this.
|
|
948
|
+
slot: this.targetSlot
|
|
903
949
|
});
|
|
904
950
|
this.metrics.recordBlockProposalFailed('insufficient_txs');
|
|
905
951
|
return undefined;
|
|
@@ -907,13 +953,13 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
907
953
|
// Create iterator to pending txs. We filter out txs already included in previous blocks in the checkpoint
|
|
908
954
|
// just in case p2p failed to sync the provisional block and didn't get to remove those txs from the mempool yet.
|
|
909
955
|
const pendingTxs = filter(this.p2pClient.iterateEligiblePendingTxs(), (tx)=>!txHashesAlreadyIncluded.has(tx.txHash.toString()));
|
|
910
|
-
this.log.debug(`Building block ${blockNumber} at index ${indexWithinCheckpoint} for slot ${this.
|
|
911
|
-
slot: this.
|
|
956
|
+
this.log.debug(`Building block ${blockNumber} at index ${indexWithinCheckpoint} for slot ${this.targetSlot} with ${availableTxs} available txs`, {
|
|
957
|
+
slot: this.targetSlot,
|
|
912
958
|
blockNumber,
|
|
913
959
|
indexWithinCheckpoint
|
|
914
960
|
});
|
|
915
|
-
this.setStateFn(SequencerState.CREATING_BLOCK, this.
|
|
916
|
-
// Per-block limits
|
|
961
|
+
this.setStateFn(SequencerState.CREATING_BLOCK, this.targetSlot);
|
|
962
|
+
// Per-block limits are operator overrides (from SEQ_MAX_L2_BLOCK_GAS etc.) further capped
|
|
917
963
|
// by remaining checkpoint-level budgets inside CheckpointBuilder before each block is built.
|
|
918
964
|
// minValidTxs is passed into the builder so it can reject the block *before* updating state.
|
|
919
965
|
const minValidTxs = forceCreate ? 0 : this.config.minValidTxsPerBlock ?? minTxs;
|
|
@@ -922,7 +968,9 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
922
968
|
maxBlockGas: this.config.maxL2BlockGas !== undefined || this.config.maxDABlockGas !== undefined ? new Gas(this.config.maxDABlockGas ?? Infinity, this.config.maxL2BlockGas ?? Infinity) : undefined,
|
|
923
969
|
deadline: buildDeadline,
|
|
924
970
|
isBuildingProposal: true,
|
|
925
|
-
minValidTxs
|
|
971
|
+
minValidTxs,
|
|
972
|
+
maxBlocksPerCheckpoint: this.timetable.maxNumberOfBlocks,
|
|
973
|
+
perBlockAllocationMultiplier: this.config.perBlockAllocationMultiplier
|
|
926
974
|
};
|
|
927
975
|
// Actually build the block by executing txs. The builder throws InsufficientValidTxsError
|
|
928
976
|
// if the number of successfully processed txs is below minValidTxs, ensuring state is not
|
|
@@ -931,8 +979,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
931
979
|
// If any txs failed during execution, drop them from the mempool so we don't pick them up again
|
|
932
980
|
await this.dropFailedTxsFromP2P(buildResult.failedTxs);
|
|
933
981
|
if (buildResult.status === 'insufficient-valid-txs') {
|
|
934
|
-
this.log.warn(`Block ${blockNumber} at index ${indexWithinCheckpoint} on slot ${this.
|
|
935
|
-
slot: this.
|
|
982
|
+
this.log.warn(`Block ${blockNumber} at index ${indexWithinCheckpoint} on slot ${this.targetSlot} has too few valid txs to be proposed`, {
|
|
983
|
+
slot: this.targetSlot,
|
|
936
984
|
blockNumber,
|
|
937
985
|
numTxs: buildResult.processedCount,
|
|
938
986
|
indexWithinCheckpoint,
|
|
@@ -940,7 +988,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
940
988
|
});
|
|
941
989
|
this.eventEmitter.emit('block-build-failed', {
|
|
942
990
|
reason: `Insufficient valid txs`,
|
|
943
|
-
slot: this.
|
|
991
|
+
slot: this.targetSlot
|
|
944
992
|
});
|
|
945
993
|
this.metrics.recordBlockProposalFailed('insufficient_valid_txs');
|
|
946
994
|
return undefined;
|
|
@@ -956,7 +1004,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
956
1004
|
const blockHash = await block.hash();
|
|
957
1005
|
const txHashes = block.body.txEffects.map((tx)=>tx.txHash);
|
|
958
1006
|
const manaPerSec = block.header.totalManaUsed.toNumberUnsafe() / (blockBuildDuration / 1000);
|
|
959
|
-
this.log.info(`Built block ${block.number} at checkpoint ${this.checkpointNumber} for slot ${this.
|
|
1007
|
+
this.log.info(`Built block ${block.number} at checkpoint ${this.checkpointNumber} for slot ${this.targetSlot} with ${numTxs} txs`, {
|
|
960
1008
|
blockHash,
|
|
961
1009
|
txHashes,
|
|
962
1010
|
manaPerSec,
|
|
@@ -964,7 +1012,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
964
1012
|
});
|
|
965
1013
|
this.eventEmitter.emit('block-proposed', {
|
|
966
1014
|
blockNumber: block.number,
|
|
967
|
-
slot: this.
|
|
1015
|
+
slot: this.targetSlot,
|
|
1016
|
+
buildSlot: this.slotNow
|
|
968
1017
|
});
|
|
969
1018
|
this.metrics.recordBuiltBlock(blockBuildDuration, block.header.totalManaUsed.toNumberUnsafe());
|
|
970
1019
|
return {
|
|
@@ -974,11 +1023,11 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
974
1023
|
} catch (err) {
|
|
975
1024
|
this.eventEmitter.emit('block-build-failed', {
|
|
976
1025
|
reason: err.message,
|
|
977
|
-
slot: this.
|
|
1026
|
+
slot: this.targetSlot
|
|
978
1027
|
});
|
|
979
1028
|
this.log.error(`Error building block`, err, {
|
|
980
1029
|
blockNumber,
|
|
981
|
-
slot: this.
|
|
1030
|
+
slot: this.targetSlot
|
|
982
1031
|
});
|
|
983
1032
|
this.metrics.recordBlockProposalFailed(err.name || 'unknown_error');
|
|
984
1033
|
this.metrics.recordFailedBlock();
|
|
@@ -1026,10 +1075,10 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1026
1075
|
};
|
|
1027
1076
|
}
|
|
1028
1077
|
// Wait a bit before checking again
|
|
1029
|
-
this.setStateFn(SequencerState.WAITING_FOR_TXS, this.
|
|
1030
|
-
this.log.verbose(`Waiting for enough txs to build block ${blockNumber} at index ${indexWithinCheckpoint} in slot ${this.
|
|
1078
|
+
this.setStateFn(SequencerState.WAITING_FOR_TXS, this.targetSlot);
|
|
1079
|
+
this.log.verbose(`Waiting for enough txs to build block ${blockNumber} at index ${indexWithinCheckpoint} in slot ${this.targetSlot} (have ${availableTxs} but need ${minTxs})`, {
|
|
1031
1080
|
blockNumber,
|
|
1032
|
-
slot: this.
|
|
1081
|
+
slot: this.targetSlot,
|
|
1033
1082
|
indexWithinCheckpoint
|
|
1034
1083
|
});
|
|
1035
1084
|
await this.waitForTxsPollingInterval();
|
|
@@ -1183,16 +1232,16 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1183
1232
|
/** Runs fee analysis and logs checkpoint outcome as fisherman */ async handleCheckpointEndAsFisherman(checkpoint) {
|
|
1184
1233
|
// Perform L1 fee analysis before clearing requests
|
|
1185
1234
|
// The callback is invoked asynchronously after the next block is mined
|
|
1186
|
-
const feeAnalysis = await this.publisher.analyzeL1Fees(this.
|
|
1235
|
+
const feeAnalysis = await this.publisher.analyzeL1Fees(this.targetSlot, (analysis)=>this.metrics.recordFishermanFeeAnalysis(analysis));
|
|
1187
1236
|
if (checkpoint) {
|
|
1188
|
-
this.log.info(`Validation checkpoint building SUCCEEDED for slot ${this.
|
|
1237
|
+
this.log.info(`Validation checkpoint building SUCCEEDED for slot ${this.targetSlot}`, {
|
|
1189
1238
|
...checkpoint.toCheckpointInfo(),
|
|
1190
1239
|
...checkpoint.getStats(),
|
|
1191
1240
|
feeAnalysisId: feeAnalysis?.id
|
|
1192
1241
|
});
|
|
1193
1242
|
} else {
|
|
1194
|
-
this.log.warn(`Validation block building FAILED for slot ${this.
|
|
1195
|
-
slot: this.
|
|
1243
|
+
this.log.warn(`Validation block building FAILED for slot ${this.targetSlot}`, {
|
|
1244
|
+
slot: this.targetSlot,
|
|
1196
1245
|
feeAnalysisId: feeAnalysis?.id
|
|
1197
1246
|
});
|
|
1198
1247
|
this.metrics.recordCheckpointProposalFailed('block_build_failed');
|
|
@@ -1203,15 +1252,15 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1203
1252
|
* Helper to handle HA double-signing errors. Returns true if the error was handled (caller should yield).
|
|
1204
1253
|
*/ handleHASigningError(err, errorContext) {
|
|
1205
1254
|
if (err instanceof DutyAlreadySignedError) {
|
|
1206
|
-
this.log.info(`${errorContext} for slot ${this.
|
|
1207
|
-
slot: this.
|
|
1255
|
+
this.log.info(`${errorContext} for slot ${this.targetSlot} already signed by another HA node, yielding`, {
|
|
1256
|
+
slot: this.targetSlot,
|
|
1208
1257
|
signedByNode: err.signedByNode
|
|
1209
1258
|
});
|
|
1210
1259
|
return true;
|
|
1211
1260
|
}
|
|
1212
1261
|
if (err instanceof SlashingProtectionError) {
|
|
1213
|
-
this.log.info(`${errorContext} for slot ${this.
|
|
1214
|
-
slot: this.
|
|
1262
|
+
this.log.info(`${errorContext} for slot ${this.targetSlot} blocked by slashing protection, yielding`, {
|
|
1263
|
+
slot: this.targetSlot,
|
|
1215
1264
|
existingMessageHash: err.existingMessageHash,
|
|
1216
1265
|
attemptedMessageHash: err.attemptedMessageHash
|
|
1217
1266
|
});
|
|
@@ -24,6 +24,7 @@ export type SequencerEvents = {
|
|
|
24
24
|
['block-proposed']: (args: {
|
|
25
25
|
blockNumber: BlockNumber;
|
|
26
26
|
slot: SlotNumber;
|
|
27
|
+
buildSlot: SlotNumber;
|
|
27
28
|
}) => void;
|
|
28
29
|
['checkpoint-empty']: (args: {
|
|
29
30
|
slot: SlotNumber;
|
|
@@ -43,4 +44,4 @@ export type SequencerEvents = {
|
|
|
43
44
|
error: Error;
|
|
44
45
|
}) => void;
|
|
45
46
|
};
|
|
46
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
47
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnRzLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VxdWVuY2VyL2V2ZW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxXQUFXLEVBQUUsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFakcsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDbEUsT0FBTyxLQUFLLEVBQUUsY0FBYyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRWpELE1BQU0sTUFBTSxlQUFlLEdBQUc7SUFDNUIsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRTtRQUN4QixRQUFRLEVBQUUsY0FBYyxDQUFDO1FBQ3pCLFFBQVEsRUFBRSxjQUFjLENBQUM7UUFDekIsZUFBZSxDQUFDLEVBQUUsTUFBTSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxFQUFFLFVBQVUsQ0FBQztLQUNuQixLQUFLLElBQUksQ0FBQztJQUNYLENBQUMsOEJBQThCLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRTtRQUFFLE1BQU0sRUFBRSxNQUFNLENBQUM7UUFBQyxJQUFJLEVBQUUsVUFBVSxDQUFBO0tBQUUsS0FBSyxJQUFJLENBQUM7SUFDdkYsQ0FBQyw2QkFBNkIsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFO1FBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQztRQUFDLFlBQVksRUFBRSxNQUFNLENBQUM7UUFBQyxJQUFJLEVBQUUsVUFBVSxDQUFBO0tBQUUsS0FBSyxJQUFJLENBQUM7SUFDNUcsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFO1FBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQztRQUFDLElBQUksRUFBRSxVQUFVLENBQUE7S0FBRSxLQUFLLElBQUksQ0FBQztJQUM3RSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUU7UUFBRSxXQUFXLEVBQUUsV0FBVyxDQUFDO1FBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQztRQUFDLFNBQVMsRUFBRSxVQUFVLENBQUE7S0FBRSxLQUFLLElBQUksQ0FBQztJQUMxRyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUU7UUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFBO0tBQUUsS0FBSyxJQUFJLENBQUM7SUFDM0QsQ0FBQywyQkFBMkIsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFO1FBQ3BDLElBQUksRUFBRSxVQUFVLENBQUM7UUFDakIsaUJBQWlCLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUM3QixhQUFhLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUN6QixXQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQztRQUN2QixjQUFjLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQztLQUMzQixLQUFLLElBQUksQ0FBQztJQUNYLENBQUMsc0JBQXNCLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRTtRQUFFLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQztRQUFDLElBQUksRUFBRSxVQUFVLENBQUE7S0FBRSxLQUFLLElBQUksQ0FBQztJQUM3RixDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUU7UUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFBO0tBQUUsS0FBSyxJQUFJLENBQUM7Q0FDeEQsQ0FBQyJ9
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/sequencer/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAEjG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,eAAe,GAAG;IAC5B,CAAC,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QACxB,QAAQ,EAAE,cAAc,CAAC;QACzB,QAAQ,EAAE,cAAc,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,UAAU,CAAC;KACnB,KAAK,IAAI,CAAC;IACX,CAAC,8BAA8B,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IACvF,CAAC,6BAA6B,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5G,CAAC,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7E,CAAC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/sequencer/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAEjG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,eAAe,GAAG;IAC5B,CAAC,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE;QACxB,QAAQ,EAAE,cAAc,CAAC;QACzB,QAAQ,EAAE,cAAc,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,UAAU,CAAC;KACnB,KAAK,IAAI,CAAC;IACX,CAAC,8BAA8B,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IACvF,CAAC,6BAA6B,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5G,CAAC,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7E,CAAC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,WAAW,CAAC;QAAC,IAAI,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IAC1G,CAAC,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IAC3D,CAAC,2BAA2B,CAAC,EAAE,CAAC,IAAI,EAAE;QACpC,IAAI,EAAE,UAAU,CAAC;QACjB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;KAC3B,KAAK,IAAI,CAAC;IACX,CAAC,sBAAsB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,gBAAgB,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7F,CAAC,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,KAAK,CAAA;KAAE,KAAK,IAAI,CAAC;CACxD,CAAC"}
|
|
@@ -31,6 +31,8 @@ export declare class SequencerMetrics {
|
|
|
31
31
|
private checkpointBlockCount;
|
|
32
32
|
private checkpointTxCount;
|
|
33
33
|
private checkpointTotalMana;
|
|
34
|
+
private pipelineDepth;
|
|
35
|
+
private pipelineDiscards;
|
|
34
36
|
private fishermanWouldBeIncluded;
|
|
35
37
|
private fishermanTimeBeforeBlock;
|
|
36
38
|
private fishermanPendingBlobTxCount;
|
|
@@ -53,6 +55,8 @@ export declare class SequencerMetrics {
|
|
|
53
55
|
recordBuiltBlock(buildDurationMs: number, totalMana: number): void;
|
|
54
56
|
recordFailedBlock(): void;
|
|
55
57
|
recordStateTransitionBufferMs(durationMs: number, state: SequencerState): void;
|
|
58
|
+
recordPipelineDepth(depth: number): void;
|
|
59
|
+
recordPipelineDiscard(count?: number): void;
|
|
56
60
|
incOpenSlot(slot: SlotNumber, proposer: string): void;
|
|
57
61
|
incFilledSlot(proposer: string, coinbase: Hex | EthAddress | undefined): Promise<void>;
|
|
58
62
|
recordCheckpointSuccess(): void;
|
|
@@ -69,4 +73,4 @@ export declare class SequencerMetrics {
|
|
|
69
73
|
*/
|
|
70
74
|
recordFishermanFeeAnalysis(analysis: L1FeeAnalysisResult): void;
|
|
71
75
|
}
|
|
72
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
76
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9tZXRyaWNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN2RCxPQUFPLEtBQUssRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzNFLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sRUFNTCxLQUFLLGVBQWUsRUFDcEIsS0FBSyxNQUFNLEVBR1osTUFBTSx5QkFBeUIsQ0FBQztBQUVqQyxPQUFPLEVBQUUsS0FBSyxHQUFHLEVBQWUsTUFBTSxNQUFNLENBQUM7QUFFN0MsT0FBTyxLQUFLLEVBQUUsY0FBYyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRWpELHFCQUFhLGdCQUFnQjtJQXNEekIsT0FBTyxDQUFDLE1BQU07SUFyRGhCLFNBQWdCLE1BQU0sRUFBRSxNQUFNLENBQUM7SUFDL0IsT0FBTyxDQUFDLEtBQUssQ0FBUTtJQUVyQixPQUFPLENBQUMsWUFBWSxDQUFnQjtJQUNwQyxPQUFPLENBQUMsa0JBQWtCLENBQVk7SUFDdEMsT0FBTyxDQUFDLHVCQUF1QixDQUFRO0lBQ3ZDLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBWTtJQUdqRCxPQUFPLENBQUMseUJBQXlCLENBQVE7SUFDekMsT0FBTyxDQUFDLDhCQUE4QixDQUFRO0lBQzlDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBUTtJQUNsQyxPQUFPLENBQUMsbUJBQW1CLENBQVE7SUFFbkMsT0FBTyxDQUFDLE9BQU8sQ0FBUTtJQUV2QixPQUFPLENBQUMsS0FBSyxDQUFnQjtJQUM3QixPQUFPLENBQUMsV0FBVyxDQUFnQjtJQUVuQyxPQUFPLENBQUMsbUJBQW1CLENBQWdCO0lBQzND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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/sequencer/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,MAAM,EAGZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,KAAK,GAAG,EAAe,MAAM,MAAM,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qBAAa,gBAAgB;
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/sequencer/metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,8 @@ export class SequencerMetrics {
|
|
|
27
27
|
checkpointBlockCount;
|
|
28
28
|
checkpointTxCount;
|
|
29
29
|
checkpointTotalMana;
|
|
30
|
+
pipelineDepth;
|
|
31
|
+
pipelineDiscards;
|
|
30
32
|
// Fisherman fee analysis metrics
|
|
31
33
|
fishermanWouldBeIncluded;
|
|
32
34
|
fishermanTimeBeforeBlock;
|
|
@@ -84,6 +86,9 @@ export class SequencerMetrics {
|
|
|
84
86
|
this.checkpointTxCount = this.meter.createGauge(Metrics.SEQUENCER_CHECKPOINT_TX_COUNT);
|
|
85
87
|
this.checkpointTotalMana = this.meter.createGauge(Metrics.SEQUENCER_CHECKPOINT_TOTAL_MANA);
|
|
86
88
|
this.slashingAttempts = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_SLASHING_ATTEMPTS_COUNT);
|
|
89
|
+
this.pipelineDepth = this.meter.createGauge(Metrics.SEQUENCER_PIPELINE_DEPTH);
|
|
90
|
+
this.pipelineDiscards = createUpDownCounterWithDefault(this.meter, Metrics.SEQUENCER_PIPELINE_DISCARDS_COUNT);
|
|
91
|
+
this.pipelineDepth.record(0);
|
|
87
92
|
// Fisherman fee analysis metrics
|
|
88
93
|
this.fishermanWouldBeIncluded = createUpDownCounterWithDefault(this.meter, Metrics.FISHERMAN_FEE_ANALYSIS_WOULD_BE_INCLUDED, {
|
|
89
94
|
[Attributes.OK]: [
|
|
@@ -145,6 +150,12 @@ export class SequencerMetrics {
|
|
|
145
150
|
[Attributes.SEQUENCER_STATE]: state
|
|
146
151
|
});
|
|
147
152
|
}
|
|
153
|
+
recordPipelineDepth(depth) {
|
|
154
|
+
this.pipelineDepth.record(depth);
|
|
155
|
+
}
|
|
156
|
+
recordPipelineDiscard(count = 1) {
|
|
157
|
+
this.pipelineDiscards.add(count);
|
|
158
|
+
}
|
|
148
159
|
incOpenSlot(slot, proposer) {
|
|
149
160
|
// sequencer went through the loop a second time. Noop
|
|
150
161
|
if (slot === this.lastSeenSlot) {
|