@aztec/sequencer-client 0.0.1-commit.21ecf947b → 0.0.1-commit.2448fdb
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 +16 -7
- package/dest/client/sequencer-client.d.ts.map +1 -1
- package/dest/client/sequencer-client.js +56 -23
- package/dest/config.d.ts +25 -5
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +42 -20
- package/dest/global_variable_builder/global_builder.d.ts +14 -10
- package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
- package/dest/global_variable_builder/global_builder.js +22 -21
- 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 +31 -17
- package/dest/publisher/config.d.ts.map +1 -1
- package/dest/publisher/config.js +101 -42
- package/dest/publisher/sequencer-publisher-factory.d.ts +11 -3
- package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher-factory.js +13 -2
- package/dest/publisher/sequencer-publisher.d.ts +22 -13
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +92 -52
- package/dest/sequencer/checkpoint_proposal_job.d.ts +4 -4
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +129 -75
- 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/metrics.d.ts +13 -5
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +32 -10
- package/dest/sequencer/sequencer.d.ts +27 -13
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +41 -42
- package/dest/sequencer/timetable.d.ts +4 -3
- package/dest/sequencer/timetable.d.ts.map +1 -1
- package/dest/sequencer/timetable.js +6 -7
- 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 +7 -9
- package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
- package/dest/test/mock_checkpoint_builder.js +41 -30
- package/package.json +28 -28
- package/src/client/sequencer-client.ts +78 -21
- package/src/config.ts +52 -27
- package/src/global_variable_builder/global_builder.ts +23 -24
- package/src/global_variable_builder/index.ts +1 -1
- package/src/publisher/config.ts +112 -43
- package/src/publisher/sequencer-publisher-factory.ts +23 -6
- package/src/publisher/sequencer-publisher.ts +96 -66
- package/src/sequencer/checkpoint_proposal_job.ts +200 -106
- package/src/sequencer/checkpoint_voter.ts +1 -12
- package/src/sequencer/metrics.ts +39 -13
- package/src/sequencer/sequencer.ts +52 -48
- package/src/sequencer/timetable.ts +7 -7
- package/src/sequencer/types.ts +1 -1
- package/src/test/index.ts +2 -4
- package/src/test/mock_checkpoint_builder.ts +53 -48
|
@@ -436,22 +436,21 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
|
436
436
|
return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
|
|
437
437
|
}
|
|
438
438
|
var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _initProto;
|
|
439
|
-
import { NUM_CHECKPOINT_END_MARKER_FIELDS, getNumBlockEndBlobFields } from '@aztec/blob-lib/encoding';
|
|
440
|
-
import { BLOBS_PER_CHECKPOINT, FIELDS_PER_BLOB } from '@aztec/constants';
|
|
441
439
|
import { BlockNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
|
|
442
440
|
import { randomInt } from '@aztec/foundation/crypto/random';
|
|
443
|
-
import {
|
|
441
|
+
import { flipSignature, generateRecoverableSignature, generateUnrecoverableSignature } from '@aztec/foundation/crypto/secp256k1-signer';
|
|
444
442
|
import { filter } from '@aztec/foundation/iterator';
|
|
445
443
|
import { createLogger } from '@aztec/foundation/log';
|
|
446
444
|
import { sleep, sleepUntil } from '@aztec/foundation/sleep';
|
|
447
445
|
import { Timer } from '@aztec/foundation/timer';
|
|
448
446
|
import { isErrorClass, unfreeze } from '@aztec/foundation/types';
|
|
449
447
|
import { CommitteeAttestationsAndSigners, MaliciousCommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
|
|
448
|
+
import { validateCheckpoint } from '@aztec/stdlib/checkpoint';
|
|
450
449
|
import { getSlotStartBuildTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
451
450
|
import { Gas } from '@aztec/stdlib/gas';
|
|
452
|
-
import {
|
|
451
|
+
import { InsufficientValidTxsError } from '@aztec/stdlib/interfaces/server';
|
|
453
452
|
import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
|
|
454
|
-
import { orderAttestations } from '@aztec/stdlib/p2p';
|
|
453
|
+
import { orderAttestations, trimAttestations } from '@aztec/stdlib/p2p';
|
|
455
454
|
import { AttestationTimeoutError } from '@aztec/stdlib/validators';
|
|
456
455
|
import { Attributes, trackSpan } from '@aztec/telemetry-client';
|
|
457
456
|
import { DutyAlreadySignedError, SlashingProtectionError } from '@aztec/validator-ha-signer/errors';
|
|
@@ -590,7 +589,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
590
589
|
// Wait until the voting promises have resolved, so all requests are enqueued (not sent)
|
|
591
590
|
await Promise.all(votesPromises);
|
|
592
591
|
if (checkpoint) {
|
|
593
|
-
this.metrics.
|
|
592
|
+
this.metrics.recordCheckpointProposalSuccess();
|
|
594
593
|
}
|
|
595
594
|
// Do not post anything to L1 if we are fishermen, but do perform L1 fee analysis
|
|
596
595
|
if (this.config.fishermanMode) {
|
|
@@ -640,13 +639,12 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
640
639
|
const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(this.checkpointNumber);
|
|
641
640
|
const inHash = computeInHashFromL1ToL2Messages(l1ToL2Messages);
|
|
642
641
|
// Collect the out hashes of all the checkpoints before this one in the same epoch
|
|
643
|
-
const
|
|
644
|
-
const previousCheckpointOutHashes = previousCheckpoints.map((c)=>c.getCheckpointOutHash());
|
|
642
|
+
const previousCheckpointOutHashes = (await this.l2BlockSource.getCheckpointsDataForEpoch(this.epoch)).filter((c)=>c.checkpointNumber < this.checkpointNumber).map((c)=>c.checkpointOutHash);
|
|
645
643
|
// Get the fee asset price modifier from the oracle
|
|
646
644
|
const feeAssetPriceModifier = await this.publisher.getFeeAssetPriceModifier();
|
|
647
645
|
const fork = _ts_add_disposable_resource(env, await this.worldState.fork(this.syncedToBlockNumber, {
|
|
648
646
|
closeDelayMs: 12_000
|
|
649
|
-
}),
|
|
647
|
+
}), true);
|
|
650
648
|
// Create checkpoint builder for the entire slot
|
|
651
649
|
const checkpointBuilder = await this.checkpointsBuilder.startCheckpoint(this.checkpointNumber, checkpointGlobalVariables, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, this.log.getBindings());
|
|
652
650
|
// Options for the validator client when creating block and checkpoint proposals
|
|
@@ -660,6 +658,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
660
658
|
};
|
|
661
659
|
let blocksInCheckpoint = [];
|
|
662
660
|
let blockPendingBroadcast = undefined;
|
|
661
|
+
const checkpointBuildTimer = new Timer();
|
|
663
662
|
try {
|
|
664
663
|
// Main loop: build blocks for the checkpoint
|
|
665
664
|
const result = await this.buildBlocksForCheckpoint(checkpointBuilder, checkpointGlobalVariables.timestamp, inHash, blockProposalOptions);
|
|
@@ -683,10 +682,37 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
683
682
|
});
|
|
684
683
|
return undefined;
|
|
685
684
|
}
|
|
685
|
+
const minBlocksForCheckpoint = this.config.minBlocksForCheckpoint;
|
|
686
|
+
if (minBlocksForCheckpoint !== undefined && blocksInCheckpoint.length < minBlocksForCheckpoint) {
|
|
687
|
+
this.log.warn(`Checkpoint has fewer blocks than minimum (${blocksInCheckpoint.length} < ${minBlocksForCheckpoint}), skipping proposal`, {
|
|
688
|
+
slot: this.slot,
|
|
689
|
+
blocksBuilt: blocksInCheckpoint.length,
|
|
690
|
+
minBlocksForCheckpoint
|
|
691
|
+
});
|
|
692
|
+
return undefined;
|
|
693
|
+
}
|
|
686
694
|
// Assemble and broadcast the checkpoint proposal, including the last block that was not
|
|
687
695
|
// broadcasted yet, and wait to collect the committee attestations.
|
|
688
696
|
this.setStateFn(SequencerState.ASSEMBLING_CHECKPOINT, this.slot);
|
|
689
697
|
const checkpoint = await checkpointBuilder.completeCheckpoint();
|
|
698
|
+
// Final validation: per-block limits are only checked if the operator set them explicitly.
|
|
699
|
+
// Otherwise, checkpoint-level budgets were already enforced by the redistribution logic.
|
|
700
|
+
try {
|
|
701
|
+
validateCheckpoint(checkpoint, {
|
|
702
|
+
rollupManaLimit: this.l1Constants.rollupManaLimit,
|
|
703
|
+
maxL2BlockGas: this.config.maxL2BlockGas,
|
|
704
|
+
maxDABlockGas: this.config.maxDABlockGas,
|
|
705
|
+
maxTxsPerBlock: this.config.maxTxsPerBlock,
|
|
706
|
+
maxTxsPerCheckpoint: this.config.maxTxsPerCheckpoint
|
|
707
|
+
});
|
|
708
|
+
} catch (err) {
|
|
709
|
+
this.log.error(`Built an invalid checkpoint at slot ${this.slot} (skipping proposal)`, err, {
|
|
710
|
+
checkpoint: checkpoint.header.toInspect()
|
|
711
|
+
});
|
|
712
|
+
return undefined;
|
|
713
|
+
}
|
|
714
|
+
// Record checkpoint-level build metrics
|
|
715
|
+
this.metrics.recordCheckpointBuild(checkpointBuildTimer.ms(), blocksInCheckpoint.length, checkpoint.getStats().txCount, Number(checkpoint.header.totalManaUsed.toBigInt()));
|
|
690
716
|
// Do not collect attestations nor publish to L1 in fisherman mode
|
|
691
717
|
if (this.config.fishermanMode) {
|
|
692
718
|
this.log.info(`Built checkpoint for slot ${this.slot} with ${blocksInCheckpoint.length} blocks. ` + `Skipping proposal in fisherman mode.`, {
|
|
@@ -729,6 +755,14 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
729
755
|
const aztecSlotDuration = this.l1Constants.slotDuration;
|
|
730
756
|
const slotStartBuildTimestamp = this.getSlotStartBuildTimestamp();
|
|
731
757
|
const txTimeoutAt = new Date((slotStartBuildTimestamp + aztecSlotDuration) * 1000);
|
|
758
|
+
// If we have been configured to potentially skip publishing checkpoint then roll the dice here
|
|
759
|
+
if (this.config.skipPublishingCheckpointsPercent !== undefined && this.config.skipPublishingCheckpointsPercent > 0) {
|
|
760
|
+
const result = Math.max(0, randomInt(100));
|
|
761
|
+
if (result < this.config.skipPublishingCheckpointsPercent) {
|
|
762
|
+
this.log.warn(`Skipping publishing proposal for checkpoint ${checkpoint.number}. Configured percentage: ${this.config.skipPublishingCheckpointsPercent}, generated value: ${result}`);
|
|
763
|
+
return checkpoint;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
732
766
|
await this.publisher.enqueueProposeCheckpoint(checkpoint, attestations, attestationsSignature, {
|
|
733
767
|
txTimeoutAt,
|
|
734
768
|
forcePendingCheckpointNumber: this.invalidateCheckpoint?.forcePendingCheckpointNumber
|
|
@@ -738,7 +772,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
738
772
|
env.error = e;
|
|
739
773
|
env.hasError = true;
|
|
740
774
|
} finally{
|
|
741
|
-
_ts_dispose_resources(env);
|
|
775
|
+
const result = _ts_dispose_resources(env);
|
|
776
|
+
if (result) await result;
|
|
742
777
|
}
|
|
743
778
|
} catch (err) {
|
|
744
779
|
if (err && (err instanceof DutyAlreadySignedError || err instanceof SlashingProtectionError)) {
|
|
@@ -755,8 +790,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
755
790
|
const blocksInCheckpoint = [];
|
|
756
791
|
const txHashesAlreadyIncluded = new Set();
|
|
757
792
|
const initialBlockNumber = BlockNumber(this.syncedToBlockNumber + 1);
|
|
758
|
-
|
|
759
|
-
let remainingBlobFields = BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB - NUM_CHECKPOINT_END_MARKER_FIELDS;
|
|
793
|
+
const slot = this.slot;
|
|
760
794
|
// Last block in the checkpoint will usually be flagged as pending broadcast, so we send it along with the checkpoint proposal
|
|
761
795
|
let blockPendingBroadcast = undefined;
|
|
762
796
|
while(true){
|
|
@@ -767,7 +801,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
767
801
|
const timingInfo = this.timetable.canStartNextBlock(secondsIntoSlot);
|
|
768
802
|
if (!timingInfo.canStart) {
|
|
769
803
|
this.log.debug(`Not enough time left in slot to start another block`, {
|
|
770
|
-
slot
|
|
804
|
+
slot,
|
|
771
805
|
blocksBuilt,
|
|
772
806
|
secondsIntoSlot
|
|
773
807
|
});
|
|
@@ -782,8 +816,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
782
816
|
buildDeadline: timingInfo.deadline ? new Date((this.getSlotStartBuildTimestamp() + timingInfo.deadline) * 1000) : undefined,
|
|
783
817
|
blockNumber,
|
|
784
818
|
indexWithinCheckpoint,
|
|
785
|
-
txHashesAlreadyIncluded
|
|
786
|
-
remainingBlobFields
|
|
819
|
+
txHashesAlreadyIncluded
|
|
787
820
|
});
|
|
788
821
|
// TODO(palla/mbps): Review these conditions. We may want to keep trying in some scenarios.
|
|
789
822
|
if (!buildResult && timingInfo.isLastBlock) {
|
|
@@ -797,33 +830,23 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
797
830
|
} else if ('error' in buildResult) {
|
|
798
831
|
// If there was an error building the block, just exit the loop and give up the rest of the slot
|
|
799
832
|
if (!(buildResult.error instanceof SequencerInterruptedError)) {
|
|
800
|
-
this.log.warn(`Halting block building for slot ${
|
|
801
|
-
slot
|
|
833
|
+
this.log.warn(`Halting block building for slot ${slot}`, {
|
|
834
|
+
slot,
|
|
802
835
|
blocksBuilt,
|
|
803
836
|
error: buildResult.error
|
|
804
837
|
});
|
|
805
838
|
}
|
|
806
839
|
break;
|
|
807
840
|
}
|
|
808
|
-
const { block, usedTxs
|
|
841
|
+
const { block, usedTxs } = buildResult;
|
|
809
842
|
blocksInCheckpoint.push(block);
|
|
810
|
-
// Update remaining blob fields for the next block
|
|
811
|
-
remainingBlobFields = newRemainingBlobFields;
|
|
812
|
-
// Sync the proposed block to the archiver to make it available
|
|
813
|
-
// Note that the checkpoint builder uses its own fork so it should not need to wait for this syncing
|
|
814
|
-
// Eventually we should refactor the checkpoint builder to not need a separate long-lived fork
|
|
815
|
-
// Fire and forget - don't block the critical path, but log errors
|
|
816
|
-
this.syncProposedBlockToArchiver(block).catch((err)=>{
|
|
817
|
-
this.log.error(`Failed to sync proposed block ${block.number} to archiver`, {
|
|
818
|
-
blockNumber: block.number,
|
|
819
|
-
err
|
|
820
|
-
});
|
|
821
|
-
});
|
|
822
843
|
usedTxs.forEach((tx)=>txHashesAlreadyIncluded.add(tx.txHash.toString()));
|
|
823
|
-
// If this is the last block,
|
|
844
|
+
// If this is the last block, send the proposed block to the archiver,
|
|
845
|
+
// and exit the loop now so we can build the checkpoint and start collecting attestations.
|
|
824
846
|
if (timingInfo.isLastBlock) {
|
|
825
|
-
this.
|
|
826
|
-
|
|
847
|
+
await this.syncProposedBlockToArchiver(block);
|
|
848
|
+
this.log.verbose(`Completed final block ${blockNumber} for slot ${slot}`, {
|
|
849
|
+
slot,
|
|
827
850
|
blockNumber,
|
|
828
851
|
blocksBuilt
|
|
829
852
|
});
|
|
@@ -833,12 +856,17 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
833
856
|
};
|
|
834
857
|
break;
|
|
835
858
|
}
|
|
836
|
-
//
|
|
837
|
-
//
|
|
838
|
-
if
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
859
|
+
// Broadcast the block proposal (unless we're in fisherman mode) unless the block is the last one,
|
|
860
|
+
// in which case we'll broadcast it along with the checkpoint at the end of the loop.
|
|
861
|
+
// Note that we only send the block to the archiver if we manage to create the proposal, so if there's
|
|
862
|
+
// a HA error we don't pollute our archiver with a block that won't make it to the chain.
|
|
863
|
+
const proposal = await this.createBlockProposal(block, inHash, usedTxs, blockProposalOptions);
|
|
864
|
+
// Sync the proposed block to the archiver to make it available, only after we've managed to sign the proposal.
|
|
865
|
+
// We wait for the sync to succeed, as this helps catch consistency errors, even if it means we lose some time for block-building.
|
|
866
|
+
// If this throws, we abort the entire checkpoint.
|
|
867
|
+
await this.syncProposedBlockToArchiver(block);
|
|
868
|
+
// Once we have a signed proposal and the archiver agreed with our proposed block, then we broadcast it.
|
|
869
|
+
proposal && await this.p2pClient.broadcastProposal(proposal);
|
|
842
870
|
// Wait until the next block's start time
|
|
843
871
|
await this.waitUntilNextSubslot(timingInfo.deadline);
|
|
844
872
|
}
|
|
@@ -851,6 +879,13 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
851
879
|
blockPendingBroadcast
|
|
852
880
|
};
|
|
853
881
|
}
|
|
882
|
+
/** Creates a block proposal for a given block via the validator client (unless in fisherman mode) */ createBlockProposal(block, inHash, usedTxs, blockProposalOptions) {
|
|
883
|
+
if (this.config.fishermanMode) {
|
|
884
|
+
this.log.info(`Skipping block proposal for block ${block.number} in fisherman mode`);
|
|
885
|
+
return Promise.resolve(undefined);
|
|
886
|
+
}
|
|
887
|
+
return this.validatorClient.createBlockProposal(block.header, block.indexWithinCheckpoint, inHash, block.archive.root, usedTxs, this.proposer, blockProposalOptions);
|
|
888
|
+
}
|
|
854
889
|
/** Sleeps until it is time to produce the next block in the slot */ async waitUntilNextSubslot(nextSubslotStart) {
|
|
855
890
|
this.setStateFn(SequencerState.WAITING_UNTIL_NEXT_BLOCK, this.slot);
|
|
856
891
|
this.log.verbose(`Waiting until time for the next block at ${nextSubslotStart}s into slot`, {
|
|
@@ -859,15 +894,14 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
859
894
|
await this.waitUntilTimeInSlot(nextSubslotStart);
|
|
860
895
|
}
|
|
861
896
|
/** Builds a single block. Called from the main block building loop. */ async buildSingleBlock(checkpointBuilder, opts) {
|
|
862
|
-
const { blockTimestamp, forceCreate, blockNumber, indexWithinCheckpoint, buildDeadline, txHashesAlreadyIncluded
|
|
897
|
+
const { blockTimestamp, forceCreate, blockNumber, indexWithinCheckpoint, buildDeadline, txHashesAlreadyIncluded } = opts;
|
|
863
898
|
this.log.verbose(`Preparing block ${blockNumber} index ${indexWithinCheckpoint} at checkpoint ${this.checkpointNumber} for slot ${this.slot}`, {
|
|
864
899
|
...checkpointBuilder.getConstantData(),
|
|
865
900
|
...opts
|
|
866
901
|
});
|
|
867
902
|
try {
|
|
868
903
|
// Wait until we have enough txs to build the block
|
|
869
|
-
const minTxs = this.
|
|
870
|
-
const { availableTxs, canStartBuilding } = await this.waitForMinTxs(opts);
|
|
904
|
+
const { availableTxs, canStartBuilding, minTxs } = await this.waitForMinTxs(opts);
|
|
871
905
|
if (!canStartBuilding) {
|
|
872
906
|
this.log.warn(`Not enough txs to build block ${blockNumber} at index ${indexWithinCheckpoint} in slot ${this.slot} (got ${availableTxs} txs but needs ${minTxs})`, {
|
|
873
907
|
blockNumber,
|
|
@@ -891,32 +925,32 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
891
925
|
indexWithinCheckpoint
|
|
892
926
|
});
|
|
893
927
|
this.setStateFn(SequencerState.CREATING_BLOCK, this.slot);
|
|
894
|
-
//
|
|
895
|
-
|
|
896
|
-
|
|
928
|
+
// Per-block limits are operator overrides (from SEQ_MAX_L2_BLOCK_GAS etc.) further capped
|
|
929
|
+
// by remaining checkpoint-level budgets inside CheckpointBuilder before each block is built.
|
|
930
|
+
// minValidTxs is passed into the builder so it can reject the block *before* updating state.
|
|
931
|
+
const minValidTxs = forceCreate ? 0 : this.config.minValidTxsPerBlock ?? minTxs;
|
|
897
932
|
const blockBuilderOptions = {
|
|
898
933
|
maxTransactions: this.config.maxTxsPerBlock,
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
934
|
+
maxBlockGas: this.config.maxL2BlockGas !== undefined || this.config.maxDABlockGas !== undefined ? new Gas(this.config.maxDABlockGas ?? Infinity, this.config.maxL2BlockGas ?? Infinity) : undefined,
|
|
935
|
+
deadline: buildDeadline,
|
|
936
|
+
isBuildingProposal: true,
|
|
937
|
+
minValidTxs,
|
|
938
|
+
maxBlocksPerCheckpoint: this.timetable.maxNumberOfBlocks,
|
|
939
|
+
perBlockAllocationMultiplier: this.config.perBlockAllocationMultiplier
|
|
903
940
|
};
|
|
904
|
-
// Actually build the block by executing txs
|
|
941
|
+
// Actually build the block by executing txs. The builder throws InsufficientValidTxsError
|
|
942
|
+
// if the number of successfully processed txs is below minValidTxs, ensuring state is not
|
|
943
|
+
// updated for blocks that will be discarded.
|
|
905
944
|
const buildResult = await this.buildSingleBlockWithCheckpointBuilder(checkpointBuilder, pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions);
|
|
906
945
|
// If any txs failed during execution, drop them from the mempool so we don't pick them up again
|
|
907
946
|
await this.dropFailedTxsFromP2P(buildResult.failedTxs);
|
|
908
|
-
|
|
909
|
-
// too long, then we may not get to minTxsPerBlock after executing public functions.
|
|
910
|
-
const minValidTxs = this.config.minValidTxsPerBlock ?? minTxs;
|
|
911
|
-
const numTxs = buildResult.status === 'no-valid-txs' ? 0 : buildResult.numTxs;
|
|
912
|
-
if (buildResult.status === 'no-valid-txs' || !forceCreate && numTxs < minValidTxs) {
|
|
947
|
+
if (buildResult.status === 'insufficient-valid-txs') {
|
|
913
948
|
this.log.warn(`Block ${blockNumber} at index ${indexWithinCheckpoint} on slot ${this.slot} has too few valid txs to be proposed`, {
|
|
914
949
|
slot: this.slot,
|
|
915
950
|
blockNumber,
|
|
916
|
-
numTxs,
|
|
951
|
+
numTxs: buildResult.processedCount,
|
|
917
952
|
indexWithinCheckpoint,
|
|
918
|
-
minValidTxs
|
|
919
|
-
buildResult: buildResult.status
|
|
953
|
+
minValidTxs
|
|
920
954
|
});
|
|
921
955
|
this.eventEmitter.emit('block-build-failed', {
|
|
922
956
|
reason: `Insufficient valid txs`,
|
|
@@ -926,7 +960,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
926
960
|
return undefined;
|
|
927
961
|
}
|
|
928
962
|
// Block creation succeeded, emit stats and metrics
|
|
929
|
-
const {
|
|
963
|
+
const { block, publicProcessorDuration, usedTxs, blockBuildDuration, numTxs } = buildResult;
|
|
930
964
|
const blockStats = {
|
|
931
965
|
eventName: 'l2-block-built',
|
|
932
966
|
duration: blockBuildDuration,
|
|
@@ -935,7 +969,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
935
969
|
};
|
|
936
970
|
const blockHash = await block.hash();
|
|
937
971
|
const txHashes = block.body.txEffects.map((tx)=>tx.txHash);
|
|
938
|
-
const manaPerSec =
|
|
972
|
+
const manaPerSec = block.header.totalManaUsed.toNumberUnsafe() / (blockBuildDuration / 1000);
|
|
939
973
|
this.log.info(`Built block ${block.number} at checkpoint ${this.checkpointNumber} for slot ${this.slot} with ${numTxs} txs`, {
|
|
940
974
|
blockHash,
|
|
941
975
|
txHashes,
|
|
@@ -946,11 +980,10 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
946
980
|
blockNumber: block.number,
|
|
947
981
|
slot: this.slot
|
|
948
982
|
});
|
|
949
|
-
this.metrics.recordBuiltBlock(blockBuildDuration,
|
|
983
|
+
this.metrics.recordBuiltBlock(blockBuildDuration, block.header.totalManaUsed.toNumberUnsafe());
|
|
950
984
|
return {
|
|
951
985
|
block,
|
|
952
|
-
usedTxs
|
|
953
|
-
remainingBlobFields: maxBlobFieldsForTxs - usedTxBlobFields
|
|
986
|
+
usedTxs
|
|
954
987
|
};
|
|
955
988
|
} catch (err) {
|
|
956
989
|
this.eventEmitter.emit('block-build-failed', {
|
|
@@ -968,7 +1001,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
968
1001
|
};
|
|
969
1002
|
}
|
|
970
1003
|
}
|
|
971
|
-
/** Uses the checkpoint builder to build a block, catching
|
|
1004
|
+
/** Uses the checkpoint builder to build a block, catching InsufficientValidTxsError. */ async buildSingleBlockWithCheckpointBuilder(checkpointBuilder, pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions) {
|
|
972
1005
|
try {
|
|
973
1006
|
const workTimer = new Timer();
|
|
974
1007
|
const result = await checkpointBuilder.buildBlock(pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions);
|
|
@@ -979,10 +1012,11 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
979
1012
|
status: 'success'
|
|
980
1013
|
};
|
|
981
1014
|
} catch (err) {
|
|
982
|
-
if (isErrorClass(err,
|
|
1015
|
+
if (isErrorClass(err, InsufficientValidTxsError)) {
|
|
983
1016
|
return {
|
|
984
1017
|
failedTxs: err.failedTxs,
|
|
985
|
-
|
|
1018
|
+
processedCount: err.processedCount,
|
|
1019
|
+
status: 'insufficient-valid-txs'
|
|
986
1020
|
};
|
|
987
1021
|
}
|
|
988
1022
|
throw err;
|
|
@@ -1001,7 +1035,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1001
1035
|
if (startBuildingDeadline === undefined || now >= startBuildingDeadline) {
|
|
1002
1036
|
return {
|
|
1003
1037
|
canStartBuilding: false,
|
|
1004
|
-
availableTxs
|
|
1038
|
+
availableTxs,
|
|
1039
|
+
minTxs
|
|
1005
1040
|
};
|
|
1006
1041
|
}
|
|
1007
1042
|
// Wait a bit before checking again
|
|
@@ -1016,7 +1051,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1016
1051
|
}
|
|
1017
1052
|
return {
|
|
1018
1053
|
canStartBuilding: true,
|
|
1019
|
-
availableTxs
|
|
1054
|
+
availableTxs,
|
|
1055
|
+
minTxs
|
|
1020
1056
|
};
|
|
1021
1057
|
}
|
|
1022
1058
|
/**
|
|
@@ -1053,10 +1089,16 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1053
1089
|
try {
|
|
1054
1090
|
const attestations = await this.validatorClient.collectAttestations(proposal, numberOfRequiredAttestations, attestationDeadline);
|
|
1055
1091
|
collectedAttestationsCount = attestations.length;
|
|
1092
|
+
// Trim attestations to minimum required to save L1 calldata gas
|
|
1093
|
+
const localAddresses = this.validatorClient.getValidatorAddresses();
|
|
1094
|
+
const trimmed = trimAttestations(attestations, numberOfRequiredAttestations, this.attestorAddress, localAddresses);
|
|
1095
|
+
if (trimmed.length < attestations.length) {
|
|
1096
|
+
this.log.debug(`Trimmed attestations from ${attestations.length} to ${trimmed.length} for L1 submission`);
|
|
1097
|
+
}
|
|
1056
1098
|
// Rollup contract requires that the signatures are provided in the order of the committee
|
|
1057
|
-
const sorted = orderAttestations(
|
|
1099
|
+
const sorted = orderAttestations(trimmed, committee);
|
|
1058
1100
|
// Manipulate the attestations if we've been configured to do so
|
|
1059
|
-
if (this.config.injectFakeAttestation || this.config.shuffleAttestationOrdering) {
|
|
1101
|
+
if (this.config.injectFakeAttestation || this.config.injectHighSValueAttestation || this.config.injectUnrecoverableSignatureAttestation || this.config.shuffleAttestationOrdering) {
|
|
1060
1102
|
return this.manipulateAttestations(proposal.slotNumber, epoch, seed, committee, sorted);
|
|
1061
1103
|
}
|
|
1062
1104
|
return new CommitteeAttestationsAndSigners(sorted);
|
|
@@ -1073,7 +1115,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1073
1115
|
// Compute the proposer index in the committee, since we dont want to tweak it.
|
|
1074
1116
|
// Otherwise, the L1 rollup contract will reject the block outright.
|
|
1075
1117
|
const proposerIndex = Number(this.epochCache.computeProposerIndex(slotNumber, epoch, seed, BigInt(committee.length)));
|
|
1076
|
-
if (this.config.injectFakeAttestation) {
|
|
1118
|
+
if (this.config.injectFakeAttestation || this.config.injectHighSValueAttestation || this.config.injectUnrecoverableSignatureAttestation) {
|
|
1077
1119
|
// Find non-empty attestations that are not from the proposer
|
|
1078
1120
|
const nonProposerIndices = [];
|
|
1079
1121
|
for(let i = 0; i < attestations.length; i++){
|
|
@@ -1083,8 +1125,16 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1083
1125
|
}
|
|
1084
1126
|
if (nonProposerIndices.length > 0) {
|
|
1085
1127
|
const targetIndex = nonProposerIndices[randomInt(nonProposerIndices.length)];
|
|
1086
|
-
this.
|
|
1087
|
-
|
|
1128
|
+
if (this.config.injectHighSValueAttestation) {
|
|
1129
|
+
this.log.warn(`Injecting high-s value attestation in checkpoint for slot ${slotNumber} at index ${targetIndex}`);
|
|
1130
|
+
unfreeze(attestations[targetIndex]).signature = flipSignature(attestations[targetIndex].signature);
|
|
1131
|
+
} else if (this.config.injectUnrecoverableSignatureAttestation) {
|
|
1132
|
+
this.log.warn(`Injecting unrecoverable signature attestation in checkpoint for slot ${slotNumber} at index ${targetIndex}`);
|
|
1133
|
+
unfreeze(attestations[targetIndex]).signature = generateUnrecoverableSignature();
|
|
1134
|
+
} else {
|
|
1135
|
+
this.log.warn(`Injecting fake attestation in checkpoint for slot ${slotNumber} at index ${targetIndex}`);
|
|
1136
|
+
unfreeze(attestations[targetIndex]).signature = generateRecoverableSignature();
|
|
1137
|
+
}
|
|
1088
1138
|
}
|
|
1089
1139
|
return new CommitteeAttestationsAndSigners(attestations);
|
|
1090
1140
|
}
|
|
@@ -1119,8 +1169,12 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1119
1169
|
* Adds the proposed block to the archiver so it's available via P2P.
|
|
1120
1170
|
* Gossip doesn't echo messages back to the sender, so the proposer's archiver/world-state
|
|
1121
1171
|
* would never receive its own block without this explicit sync.
|
|
1172
|
+
*
|
|
1173
|
+
* In fisherman mode we skip this push: the fisherman builds blocks locally for validation
|
|
1174
|
+
* and fee analysis only, and pushing them to the archiver causes spurious reorg cascades
|
|
1175
|
+
* whenever the real proposer's block arrives from L1.
|
|
1122
1176
|
*/ async syncProposedBlockToArchiver(block) {
|
|
1123
|
-
if (this.config.skipPushProposedBlocksToArchiver !== false) {
|
|
1177
|
+
if (this.config.skipPushProposedBlocksToArchiver !== false || this.config.fishermanMode) {
|
|
1124
1178
|
this.log.warn(`Skipping push of proposed block ${block.number} to archiver`, {
|
|
1125
1179
|
blockNumber: block.number,
|
|
1126
1180
|
slot: block.header.globalVariables.slotNumber
|
|
@@ -1148,7 +1202,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
|
|
|
1148
1202
|
slot: this.slot,
|
|
1149
1203
|
feeAnalysisId: feeAnalysis?.id
|
|
1150
1204
|
});
|
|
1151
|
-
this.metrics.
|
|
1205
|
+
this.metrics.recordCheckpointProposalFailed('block_build_failed');
|
|
1152
1206
|
}
|
|
1153
1207
|
this.publisher.clearPendingRequests();
|
|
1154
1208
|
}
|
|
@@ -20,7 +20,6 @@ export declare class CheckpointVoter {
|
|
|
20
20
|
private readonly config;
|
|
21
21
|
private readonly metrics;
|
|
22
22
|
private readonly log;
|
|
23
|
-
private slotTimestamp;
|
|
24
23
|
private governanceSigner;
|
|
25
24
|
private slashingSigner;
|
|
26
25
|
constructor(slot: SlotNumber, publisher: SequencerPublisher, attestorAddress: EthAddress, validatorClient: ValidatorClient, slasherClient: SlasherClientInterface | undefined, l1Constants: SequencerRollupConstants, config: ResolvedSequencerConfig, metrics: SequencerMetrics, log: Logger);
|
|
@@ -32,4 +31,4 @@ export declare class CheckpointVoter {
|
|
|
32
31
|
private enqueueGovernanceVote;
|
|
33
32
|
private enqueueSlashingVote;
|
|
34
33
|
}
|
|
35
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludF92b3Rlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9jaGVja3BvaW50X3ZvdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BELE9BQU8sS0FBSyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0QsT0FBTyxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMvRSxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQU0vRCxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzlFLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3JELE9BQU8sS0FBSyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRTNEOztHQUVHO0FBQ0gscUJBQWEsZUFBZTtJQUt4QixPQUFPLENBQUMsUUFBUSxDQUFDLElBQUk7SUFDckIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTO0lBQzFCLE9BQU8sQ0FBQyxRQUFRLENBQUMsZUFBZTtJQUNoQyxPQUFPLENBQUMsUUFBUSxDQUFDLGVBQWU7SUFDaEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxhQUFhO0lBQzlCLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVztJQUM1QixPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU07SUFDdkIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPO0lBQ3hCLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRztJQVp0QixPQUFPLENBQUMsZ0JBQWdCLENBQXVEO0lBQy9FLE9BQU8sQ0FBQyxjQUFjLENBQXVEO0lBRTdFLFlBQ21CLElBQUksRUFBRSxVQUFVLEVBQ2hCLFNBQVMsRUFBRSxrQkFBa0IsRUFDN0IsZUFBZSxFQUFFLFVBQVUsRUFDM0IsZUFBZSxFQUFFLGVBQWUsRUFDaEMsYUFBYSxFQUFFLHNCQUFzQixHQUFHLFNBQVMsRUFDakQsV0FBVyxFQUFFLHdCQUF3QixFQUNyQyxNQUFNLEVBQUUsdUJBQXVCLEVBQy9CLE9BQU8sRUFBRSxnQkFBZ0IsRUFDekIsR0FBRyxFQUFFLE1BQU0sRUFXN0I7SUFFRDs7O09BR0c7SUFDSCxZQUFZLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FVM0U7WUFFYSxxQkFBcUI7WUErQnJCLG1CQUFtQjtDQTJCbEMifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkpoint_voter.d.ts","sourceRoot":"","sources":["../../src/sequencer/checkpoint_voter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"checkpoint_voter.d.ts","sourceRoot":"","sources":["../../src/sequencer/checkpoint_voter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAM/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE3D;;GAEG;AACH,qBAAa,eAAe;IAKxB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAZtB,OAAO,CAAC,gBAAgB,CAAuD;IAC/E,OAAO,CAAC,cAAc,CAAuD;IAE7E,YACmB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,kBAAkB,EAC7B,eAAe,EAAE,UAAU,EAC3B,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,sBAAsB,GAAG,SAAS,EACjD,WAAW,EAAE,wBAAwB,EACrC,MAAM,EAAE,uBAAuB,EAC/B,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,MAAM,EAW7B;IAED;;;OAGG;IACH,YAAY,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,CAU3E;YAEa,qBAAqB;YA+BrB,mBAAmB;CA2BlC"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
|
|
2
1
|
import { DutyAlreadySignedError } from '@aztec/validator-ha-signer/errors';
|
|
3
2
|
import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
4
3
|
/**
|
|
@@ -13,7 +12,6 @@ import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
|
13
12
|
config;
|
|
14
13
|
metrics;
|
|
15
14
|
log;
|
|
16
|
-
slotTimestamp;
|
|
17
15
|
governanceSigner;
|
|
18
16
|
slashingSigner;
|
|
19
17
|
constructor(slot, publisher, attestorAddress, validatorClient, slasherClient, l1Constants, config, metrics, log){
|
|
@@ -26,7 +24,6 @@ import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
|
26
24
|
this.config = config;
|
|
27
25
|
this.metrics = metrics;
|
|
28
26
|
this.log = log;
|
|
29
|
-
this.slotTimestamp = getTimestampForSlot(this.slot, this.l1Constants);
|
|
30
27
|
// Create separate signers with appropriate duty contexts for governance and slashing votes
|
|
31
28
|
// These use HA protection to ensure only one node signs per slot/duty
|
|
32
29
|
const governanceContext = {
|
|
@@ -69,7 +66,7 @@ import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
|
69
66
|
governanceProposerPayload: governanceProposerPayload.toString()
|
|
70
67
|
});
|
|
71
68
|
try {
|
|
72
|
-
return await this.publisher.enqueueGovernanceCastSignal(governanceProposerPayload, this.slot, this.
|
|
69
|
+
return await this.publisher.enqueueGovernanceCastSignal(governanceProposerPayload, this.slot, this.attestorAddress, this.governanceSigner);
|
|
73
70
|
} catch (err) {
|
|
74
71
|
if (err instanceof DutyAlreadySignedError) {
|
|
75
72
|
this.log.info(`Governance vote already signed by another node`, {
|
|
@@ -93,7 +90,7 @@ import { DutyType } from '@aztec/validator-ha-signer/types';
|
|
|
93
90
|
actionCount: actions.length
|
|
94
91
|
});
|
|
95
92
|
this.metrics.recordSlashingAttempt(actions.length);
|
|
96
|
-
return await this.publisher.enqueueSlashingActions(actions, this.slot, this.
|
|
93
|
+
return await this.publisher.enqueueSlashingActions(actions, this.slot, this.attestorAddress, this.slashingSigner);
|
|
97
94
|
} catch (err) {
|
|
98
95
|
if (err instanceof DutyAlreadySignedError) {
|
|
99
96
|
this.log.info(`Slashing vote already signed by another node`, {
|
|
@@ -21,11 +21,16 @@ export declare class SequencerMetrics {
|
|
|
21
21
|
private slots;
|
|
22
22
|
private filledSlots;
|
|
23
23
|
private blockProposalFailed;
|
|
24
|
-
private
|
|
25
|
-
private
|
|
24
|
+
private checkpointProposalSuccess;
|
|
25
|
+
private checkpointPrecheckFailed;
|
|
26
|
+
private checkpointProposalFailed;
|
|
26
27
|
private checkpointSuccess;
|
|
27
28
|
private slashingAttempts;
|
|
28
29
|
private checkpointAttestationDelay;
|
|
30
|
+
private checkpointBuildDuration;
|
|
31
|
+
private checkpointBlockCount;
|
|
32
|
+
private checkpointTxCount;
|
|
33
|
+
private checkpointTotalMana;
|
|
29
34
|
private fishermanWouldBeIncluded;
|
|
30
35
|
private fishermanTimeBeforeBlock;
|
|
31
36
|
private fishermanPendingBlobTxCount;
|
|
@@ -52,8 +57,11 @@ export declare class SequencerMetrics {
|
|
|
52
57
|
incFilledSlot(proposer: string, coinbase: Hex | EthAddress | undefined): Promise<void>;
|
|
53
58
|
recordCheckpointSuccess(): void;
|
|
54
59
|
recordBlockProposalFailed(reason?: string): void;
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
recordCheckpointProposalSuccess(): void;
|
|
61
|
+
recordCheckpointPrecheckFailed(checkType: 'slot_already_taken' | 'rollup_contract_check_failed' | 'slot_mismatch' | 'block_number_mismatch'): void;
|
|
62
|
+
recordCheckpointProposalFailed(reason?: string): void;
|
|
63
|
+
/** Records aggregate metrics for a completed checkpoint build. */
|
|
64
|
+
recordCheckpointBuild(durationMs: number, blockCount: number, txCount: number, totalMana: number): void;
|
|
57
65
|
recordSlashingAttempt(actionCount: number): void;
|
|
58
66
|
/**
|
|
59
67
|
* Records metrics for a completed fisherman fee analysis
|
|
@@ -61,4 +69,4 @@ export declare class SequencerMetrics {
|
|
|
61
69
|
*/
|
|
62
70
|
recordFishermanFeeAnalysis(analysis: L1FeeAnalysisResult): void;
|
|
63
71
|
}
|
|
64
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
72
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9tZXRyaWNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN2RCxPQUFPLEtBQUssRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzNFLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sRUFNTCxLQUFLLGVBQWUsRUFDcEIsS0FBSyxNQUFNLEVBR1osTUFBTSx5QkFBeUIsQ0FBQztBQUVqQyxPQUFPLEVBQUUsS0FBSyxHQUFHLEVBQWUsTUFBTSxNQUFNLENBQUM7QUFFN0MsT0FBTyxLQUFLLEVBQUUsY0FBYyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRWpELHFCQUFhLGdCQUFnQjtJQW9EekIsT0FBTyxDQUFDLE1BQU07SUFuRGhCLFNBQWdCLE1BQU0sRUFBRSxNQUFNLENBQUM7SUFDL0IsT0FBTyxDQUFDLEtBQUssQ0FBUTtJQUVyQixPQUFPLENBQUMsWUFBWSxDQUFnQjtJQUNwQyxPQUFPLENBQUMsa0JBQWtCLENBQVk7SUFDdEMsT0FBTyxDQUFDLHVCQUF1QixDQUFRO0lBQ3ZDLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBWTtJQUdqRCxPQUFPLENBQUMseUJBQXlCLENBQVE7SUFDekMsT0FBTyxDQUFDLDhCQUE4QixDQUFRO0lBQzlDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBUTtJQUNsQyxPQUFPLENBQUMsbUJBQW1CLENBQVE7SUFFbkMsT0FBTyxDQUFDLE9BQU8sQ0FBUTtJQUV2QixPQUFPLENBQUMsS0FBSyxDQUFnQjtJQUM3QixPQUFPLENBQUMsV0FBVyxDQUFnQjtJQUVuQyxPQUFPLENBQUMsbUJBQW1CLENBQWdCO0lBQzND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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;
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/sequencer/metrics.ts"],"names":[],"mappings":"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"}
|