@aztec/sequencer-client 0.0.1-commit.1bea0213 → 0.0.1-commit.217f559981

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.
Files changed (55) hide show
  1. package/dest/client/sequencer-client.d.ts +12 -7
  2. package/dest/client/sequencer-client.d.ts.map +1 -1
  3. package/dest/client/sequencer-client.js +15 -4
  4. package/dest/config.d.ts +3 -4
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +17 -12
  7. package/dest/global_variable_builder/global_builder.d.ts +2 -4
  8. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  9. package/dest/publisher/config.d.ts +31 -17
  10. package/dest/publisher/config.d.ts.map +1 -1
  11. package/dest/publisher/config.js +101 -42
  12. package/dest/publisher/sequencer-publisher-factory.d.ts +11 -3
  13. package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
  14. package/dest/publisher/sequencer-publisher-factory.js +13 -2
  15. package/dest/publisher/sequencer-publisher-metrics.d.ts +1 -1
  16. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +1 -1
  17. package/dest/publisher/sequencer-publisher-metrics.js +12 -4
  18. package/dest/publisher/sequencer-publisher.d.ts +16 -8
  19. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  20. package/dest/publisher/sequencer-publisher.js +80 -39
  21. package/dest/sequencer/checkpoint_proposal_job.d.ts +32 -9
  22. package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
  23. package/dest/sequencer/checkpoint_proposal_job.js +105 -57
  24. package/dest/sequencer/metrics.d.ts +17 -5
  25. package/dest/sequencer/metrics.d.ts.map +1 -1
  26. package/dest/sequencer/metrics.js +111 -30
  27. package/dest/sequencer/sequencer.d.ts +17 -7
  28. package/dest/sequencer/sequencer.d.ts.map +1 -1
  29. package/dest/sequencer/sequencer.js +30 -27
  30. package/dest/sequencer/timetable.d.ts +1 -4
  31. package/dest/sequencer/timetable.d.ts.map +1 -1
  32. package/dest/sequencer/timetable.js +1 -4
  33. package/dest/test/index.d.ts +3 -5
  34. package/dest/test/index.d.ts.map +1 -1
  35. package/dest/test/mock_checkpoint_builder.d.ts +7 -5
  36. package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
  37. package/dest/test/mock_checkpoint_builder.js +6 -6
  38. package/dest/test/utils.d.ts +3 -3
  39. package/dest/test/utils.d.ts.map +1 -1
  40. package/dest/test/utils.js +5 -4
  41. package/package.json +28 -28
  42. package/src/client/sequencer-client.ts +25 -7
  43. package/src/config.ts +26 -19
  44. package/src/global_variable_builder/global_builder.ts +1 -1
  45. package/src/publisher/config.ts +112 -43
  46. package/src/publisher/sequencer-publisher-factory.ts +23 -6
  47. package/src/publisher/sequencer-publisher-metrics.ts +7 -3
  48. package/src/publisher/sequencer-publisher.ts +96 -45
  49. package/src/sequencer/checkpoint_proposal_job.ts +143 -74
  50. package/src/sequencer/metrics.ts +124 -32
  51. package/src/sequencer/sequencer.ts +40 -32
  52. package/src/sequencer/timetable.ts +6 -5
  53. package/src/test/index.ts +2 -4
  54. package/src/test/mock_checkpoint_builder.ts +14 -5
  55. package/src/test/utils.ts +5 -2
@@ -438,16 +438,18 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
438
438
  var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _initProto;
439
439
  import { NUM_CHECKPOINT_END_MARKER_FIELDS, getNumBlockEndBlobFields } from '@aztec/blob-lib/encoding';
440
440
  import { BLOBS_PER_CHECKPOINT, FIELDS_PER_BLOB } from '@aztec/constants';
441
- import { BlockNumber } from '@aztec/foundation/branded-types';
441
+ import { BlockNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
442
442
  import { randomInt } from '@aztec/foundation/crypto/random';
443
443
  import { Signature } from '@aztec/foundation/eth-signature';
444
444
  import { filter } from '@aztec/foundation/iterator';
445
+ import { createLogger } from '@aztec/foundation/log';
445
446
  import { sleep, sleepUntil } from '@aztec/foundation/sleep';
446
447
  import { Timer } from '@aztec/foundation/timer';
447
- import { unfreeze } from '@aztec/foundation/types';
448
+ import { isErrorClass, unfreeze } from '@aztec/foundation/types';
448
449
  import { CommitteeAttestationsAndSigners, MaliciousCommitteeAttestationsAndSigners } from '@aztec/stdlib/block';
449
450
  import { getSlotStartBuildTimestamp } from '@aztec/stdlib/epoch-helpers';
450
451
  import { Gas } from '@aztec/stdlib/gas';
452
+ import { NoValidTxsError } from '@aztec/stdlib/interfaces/server';
451
453
  import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
452
454
  import { orderAttestations } from '@aztec/stdlib/p2p';
453
455
  import { AttestationTimeoutError } from '@aztec/stdlib/validators';
@@ -495,7 +497,6 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
495
497
  metrics;
496
498
  eventEmitter;
497
499
  setStateFn;
498
- log;
499
500
  tracer;
500
501
  static{
501
502
  ({ e: [_initProto] } = _apply_decs_2203_r(this, [
@@ -541,8 +542,9 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
541
542
  ]
542
543
  ], []));
543
544
  }
545
+ log;
544
546
  constructor(epoch, slot, checkpointNumber, syncedToBlockNumber, // TODO(palla/mbps): Can we remove the proposer in favor of attestorAddress? Need to check fisherman-node flows.
545
- proposer, publisher, attestorAddress, invalidateCheckpoint, validatorClient, globalsBuilder, p2pClient, worldState, l1ToL2MessageSource, l2BlockSource, checkpointsBuilder, blockSink, l1Constants, config, timetable, slasherClient, epochCache, dateProvider, metrics, eventEmitter, setStateFn, log, tracer){
547
+ proposer, publisher, attestorAddress, invalidateCheckpoint, validatorClient, globalsBuilder, p2pClient, worldState, l1ToL2MessageSource, l2BlockSource, checkpointsBuilder, blockSink, l1Constants, config, timetable, slasherClient, epochCache, dateProvider, metrics, eventEmitter, setStateFn, tracer, bindings){
546
548
  this.epoch = epoch;
547
549
  this.slot = slot;
548
550
  this.checkpointNumber = checkpointNumber;
@@ -568,9 +570,12 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
568
570
  this.metrics = metrics;
569
571
  this.eventEmitter = eventEmitter;
570
572
  this.setStateFn = setStateFn;
571
- this.log = log;
572
573
  this.tracer = tracer;
573
574
  _initProto(this);
575
+ this.log = createLogger('sequencer:checkpoint-proposal', {
576
+ ...bindings,
577
+ instanceId: `slot-${slot}`
578
+ });
574
579
  }
575
580
  /**
576
581
  * Executes the checkpoint proposal job.
@@ -585,7 +590,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
585
590
  // Wait until the voting promises have resolved, so all requests are enqueued (not sent)
586
591
  await Promise.all(votesPromises);
587
592
  if (checkpoint) {
588
- this.metrics.recordBlockProposalSuccess();
593
+ this.metrics.recordCheckpointProposalSuccess();
589
594
  }
590
595
  // Do not post anything to L1 if we are fishermen, but do perform L1 fee analysis
591
596
  if (this.config.fishermanMode) {
@@ -635,13 +640,14 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
635
640
  const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(this.checkpointNumber);
636
641
  const inHash = computeInHashFromL1ToL2Messages(l1ToL2Messages);
637
642
  // Collect the out hashes of all the checkpoints before this one in the same epoch
638
- const previousCheckpoints = (await this.l2BlockSource.getCheckpointsForEpoch(this.epoch)).filter((c)=>c.number < this.checkpointNumber);
639
- const previousCheckpointOutHashes = previousCheckpoints.map((c)=>c.getCheckpointOutHash());
643
+ const previousCheckpointOutHashes = (await this.l2BlockSource.getCheckpointsDataForEpoch(this.epoch)).filter((c)=>c.checkpointNumber < this.checkpointNumber).map((c)=>c.checkpointOutHash);
644
+ // Get the fee asset price modifier from the oracle
645
+ const feeAssetPriceModifier = await this.publisher.getFeeAssetPriceModifier();
640
646
  const fork = _ts_add_disposable_resource(env, await this.worldState.fork(this.syncedToBlockNumber, {
641
647
  closeDelayMs: 12_000
642
- }), false);
648
+ }), true);
643
649
  // Create checkpoint builder for the entire slot
644
- const checkpointBuilder = await this.checkpointsBuilder.startCheckpoint(this.checkpointNumber, checkpointGlobalVariables, l1ToL2Messages, previousCheckpointOutHashes, fork);
650
+ const checkpointBuilder = await this.checkpointsBuilder.startCheckpoint(this.checkpointNumber, checkpointGlobalVariables, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, this.log.getBindings());
645
651
  // Options for the validator client when creating block and checkpoint proposals
646
652
  const blockProposalOptions = {
647
653
  publishFullTxs: !!this.config.publishTxsWithProposals,
@@ -653,6 +659,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
653
659
  };
654
660
  let blocksInCheckpoint = [];
655
661
  let blockPendingBroadcast = undefined;
662
+ const checkpointBuildTimer = new Timer();
656
663
  try {
657
664
  // Main loop: build blocks for the checkpoint
658
665
  const result = await this.buildBlocksForCheckpoint(checkpointBuilder, checkpointGlobalVariables.timestamp, inHash, blockProposalOptions);
@@ -662,19 +669,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
662
669
  // These errors are expected in HA mode, so we yield and let another HA node handle the slot
663
670
  // The only distinction between the 2 errors is SlashingProtectionError throws when the payload is different,
664
671
  // which is normal for block building (may have picked different txs)
665
- if (err instanceof DutyAlreadySignedError) {
666
- this.log.info(`Checkpoint proposal for slot ${this.slot} already signed by another HA node, yielding`, {
667
- slot: this.slot,
668
- signedByNode: err.signedByNode
669
- });
670
- return undefined;
671
- }
672
- if (err instanceof SlashingProtectionError) {
673
- this.log.info(`Checkpoint proposal for slot ${this.slot} blocked by slashing protection, yielding`, {
674
- slot: this.slot,
675
- existingMessageHash: err.existingMessageHash,
676
- attemptedMessageHash: err.attemptedMessageHash
677
- });
672
+ if (this.handleHASigningError(err, 'Block proposal')) {
678
673
  return undefined;
679
674
  }
680
675
  throw err;
@@ -688,10 +683,21 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
688
683
  });
689
684
  return undefined;
690
685
  }
686
+ const minBlocksForCheckpoint = this.config.minBlocksForCheckpoint;
687
+ if (minBlocksForCheckpoint !== undefined && blocksInCheckpoint.length < minBlocksForCheckpoint) {
688
+ this.log.warn(`Checkpoint has fewer blocks than minimum (${blocksInCheckpoint.length} < ${minBlocksForCheckpoint}), skipping proposal`, {
689
+ slot: this.slot,
690
+ blocksBuilt: blocksInCheckpoint.length,
691
+ minBlocksForCheckpoint
692
+ });
693
+ return undefined;
694
+ }
691
695
  // Assemble and broadcast the checkpoint proposal, including the last block that was not
692
696
  // broadcasted yet, and wait to collect the committee attestations.
693
697
  this.setStateFn(SequencerState.ASSEMBLING_CHECKPOINT, this.slot);
694
698
  const checkpoint = await checkpointBuilder.completeCheckpoint();
699
+ // Record checkpoint-level build metrics
700
+ this.metrics.recordCheckpointBuild(checkpointBuildTimer.ms(), blocksInCheckpoint.length, checkpoint.getStats().txCount, Number(checkpoint.header.totalManaUsed.toBigInt()));
695
701
  // Do not collect attestations nor publish to L1 in fisherman mode
696
702
  if (this.config.fishermanMode) {
697
703
  this.log.info(`Built checkpoint for slot ${this.slot} with ${blocksInCheckpoint.length} blocks. ` + `Skipping proposal in fisherman mode.`, {
@@ -709,7 +715,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
709
715
  txs: blockPendingBroadcast.txs
710
716
  };
711
717
  // Create the checkpoint proposal and broadcast it
712
- const proposal = await this.validatorClient.createCheckpointProposal(checkpoint.header, checkpoint.archive.root, lastBlock, this.proposer, checkpointProposalOptions);
718
+ const proposal = await this.validatorClient.createCheckpointProposal(checkpoint.header, checkpoint.archive.root, feeAssetPriceModifier, lastBlock, this.proposer, checkpointProposalOptions);
713
719
  const blockProposedAt = this.dateProvider.now();
714
720
  await this.p2pClient.broadcastCheckpointProposal(proposal);
715
721
  this.setStateFn(SequencerState.COLLECTING_ATTESTATIONS, this.slot);
@@ -723,20 +729,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
723
729
  attestationsSignature = await this.validatorClient.signAttestationsAndSigners(attestations, signer, this.slot, this.checkpointNumber);
724
730
  } catch (err) {
725
731
  // We shouldn't really get here since we yield to another HA node
726
- // as soon as we see these errors when creating block proposals.
727
- if (err instanceof DutyAlreadySignedError) {
728
- this.log.info(`Attestations signature for slot ${this.slot} already signed by another HA node, yielding`, {
729
- slot: this.slot,
730
- signedByNode: err.signedByNode
731
- });
732
- return undefined;
733
- }
734
- if (err instanceof SlashingProtectionError) {
735
- this.log.info(`Attestations signature for slot ${this.slot} blocked by slashing protection, yielding`, {
736
- slot: this.slot,
737
- existingMessageHash: err.existingMessageHash,
738
- attemptedMessageHash: err.attemptedMessageHash
739
- });
732
+ // as soon as we see these errors when creating block or checkpoint proposals.
733
+ if (this.handleHASigningError(err, 'Attestations signature')) {
740
734
  return undefined;
741
735
  }
742
736
  throw err;
@@ -746,6 +740,14 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
746
740
  const aztecSlotDuration = this.l1Constants.slotDuration;
747
741
  const slotStartBuildTimestamp = this.getSlotStartBuildTimestamp();
748
742
  const txTimeoutAt = new Date((slotStartBuildTimestamp + aztecSlotDuration) * 1000);
743
+ // If we have been configured to potentially skip publishing checkpoint then roll the dice here
744
+ if (this.config.skipPublishingCheckpointsPercent !== undefined && this.config.skipPublishingCheckpointsPercent > 0) {
745
+ const result = Math.max(0, randomInt(100));
746
+ if (result < this.config.skipPublishingCheckpointsPercent) {
747
+ this.log.warn(`Skipping publishing proposal for checkpoint ${checkpoint.number}. Configured percentage: ${this.config.skipPublishingCheckpointsPercent}, generated value: ${result}`);
748
+ return checkpoint;
749
+ }
750
+ }
749
751
  await this.publisher.enqueueProposeCheckpoint(checkpoint, attestations, attestationsSignature, {
750
752
  txTimeoutAt,
751
753
  forcePendingCheckpointNumber: this.invalidateCheckpoint?.forcePendingCheckpointNumber
@@ -755,7 +757,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
755
757
  env.error = e;
756
758
  env.hasError = true;
757
759
  } finally{
758
- _ts_dispose_resources(env);
760
+ const result = _ts_dispose_resources(env);
761
+ if (result) await result;
759
762
  }
760
763
  } catch (err) {
761
764
  if (err && (err instanceof DutyAlreadySignedError || err instanceof SlashingProtectionError)) {
@@ -778,7 +781,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
778
781
  let blockPendingBroadcast = undefined;
779
782
  while(true){
780
783
  const blocksBuilt = blocksInCheckpoint.length;
781
- const indexWithinCheckpoint = blocksBuilt;
784
+ const indexWithinCheckpoint = IndexWithinCheckpoint(blocksBuilt);
782
785
  const blockNumber = BlockNumber(initialBlockNumber + blocksBuilt);
783
786
  const secondsIntoSlot = this.getSecondsIntoSlot();
784
787
  const timingInfo = this.timetable.canStartNextBlock(secondsIntoSlot);
@@ -802,6 +805,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
802
805
  txHashesAlreadyIncluded,
803
806
  remainingBlobFields
804
807
  });
808
+ // TODO(palla/mbps): Review these conditions. We may want to keep trying in some scenarios.
805
809
  if (!buildResult && timingInfo.isLastBlock) {
806
810
  break;
807
811
  } else if (!buildResult && timingInfo.deadline !== undefined) {
@@ -900,7 +904,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
900
904
  }
901
905
  // Create iterator to pending txs. We filter out txs already included in previous blocks in the checkpoint
902
906
  // just in case p2p failed to sync the provisional block and didn't get to remove those txs from the mempool yet.
903
- const pendingTxs = filter(this.p2pClient.iteratePendingTxs(), (tx)=>!txHashesAlreadyIncluded.has(tx.txHash.toString()));
907
+ const pendingTxs = filter(this.p2pClient.iterateEligiblePendingTxs(), (tx)=>!txHashesAlreadyIncluded.has(tx.txHash.toString()));
904
908
  this.log.debug(`Building block ${blockNumber} at index ${indexWithinCheckpoint} for slot ${this.slot} with ${availableTxs} available txs`, {
905
909
  slot: this.slot,
906
910
  blockNumber,
@@ -918,35 +922,35 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
918
922
  deadline: buildDeadline
919
923
  };
920
924
  // Actually build the block by executing txs
921
- const workTimer = new Timer();
922
- const { publicGas, block, publicProcessorDuration, numTxs, blockBuildingTimer, usedTxs, failedTxs, usedTxBlobFields } = await checkpointBuilder.buildBlock(pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions);
923
- const blockBuildDuration = workTimer.ms();
925
+ const buildResult = await this.buildSingleBlockWithCheckpointBuilder(checkpointBuilder, pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions);
924
926
  // If any txs failed during execution, drop them from the mempool so we don't pick them up again
925
- await this.dropFailedTxsFromP2P(failedTxs);
927
+ await this.dropFailedTxsFromP2P(buildResult.failedTxs);
926
928
  // Check if we have created a block with enough txs. If there were invalid txs in the pool, or if execution took
927
929
  // too long, then we may not get to minTxsPerBlock after executing public functions.
928
930
  const minValidTxs = this.config.minValidTxsPerBlock ?? minTxs;
929
- if (!forceCreate && numTxs < minValidTxs) {
930
- this.log.warn(`Block ${blockNumber} at index ${indexWithinCheckpoint} on slot ${this.slot} has too few valid txs to be proposed (got ${numTxs} but required ${minValidTxs})`, {
931
+ const numTxs = buildResult.status === 'no-valid-txs' ? 0 : buildResult.numTxs;
932
+ if (buildResult.status === 'no-valid-txs' || !forceCreate && numTxs < minValidTxs) {
933
+ this.log.warn(`Block ${blockNumber} at index ${indexWithinCheckpoint} on slot ${this.slot} has too few valid txs to be proposed`, {
931
934
  slot: this.slot,
932
935
  blockNumber,
933
936
  numTxs,
934
- indexWithinCheckpoint
937
+ indexWithinCheckpoint,
938
+ minValidTxs,
939
+ buildResult: buildResult.status
935
940
  });
936
- this.eventEmitter.emit('block-tx-count-check-failed', {
937
- minTxs: minValidTxs,
938
- availableTxs: numTxs,
941
+ this.eventEmitter.emit('block-build-failed', {
942
+ reason: `Insufficient valid txs`,
939
943
  slot: this.slot
940
944
  });
941
945
  this.metrics.recordBlockProposalFailed('insufficient_valid_txs');
942
946
  return undefined;
943
947
  }
944
948
  // Block creation succeeded, emit stats and metrics
949
+ const { publicGas, block, publicProcessorDuration, usedTxs, usedTxBlobFields, blockBuildDuration } = buildResult;
945
950
  const blockStats = {
946
951
  eventName: 'l2-block-built',
947
952
  duration: blockBuildDuration,
948
953
  publicProcessDuration: publicProcessorDuration,
949
- rollupCircuitsDuration: blockBuildingTimer.ms(),
950
954
  ...block.getStats()
951
955
  };
952
956
  const blockHash = await block.hash();
@@ -984,9 +988,30 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
984
988
  };
985
989
  }
986
990
  }
991
+ /** Uses the checkpoint builder to build a block, catching specific txs */ async buildSingleBlockWithCheckpointBuilder(checkpointBuilder, pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions) {
992
+ try {
993
+ const workTimer = new Timer();
994
+ const result = await checkpointBuilder.buildBlock(pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions);
995
+ const blockBuildDuration = workTimer.ms();
996
+ return {
997
+ ...result,
998
+ blockBuildDuration,
999
+ status: 'success'
1000
+ };
1001
+ } catch (err) {
1002
+ if (isErrorClass(err, NoValidTxsError)) {
1003
+ return {
1004
+ failedTxs: err.failedTxs,
1005
+ status: 'no-valid-txs'
1006
+ };
1007
+ }
1008
+ throw err;
1009
+ }
1010
+ }
987
1011
  /** Waits until minTxs are available on the pool for building a block. */ async waitForMinTxs(opts) {
988
- const minTxs = this.config.minTxsPerBlock;
989
1012
  const { indexWithinCheckpoint, blockNumber, buildDeadline, forceCreate } = opts;
1013
+ // We only allow a block with 0 txs in the first block of the checkpoint
1014
+ const minTxs = indexWithinCheckpoint > 0 && this.config.minTxsPerBlock === 0 ? 1 : this.config.minTxsPerBlock;
990
1015
  // Deadline is undefined if we are not enforcing the timetable, meaning we'll exit immediately when out of time
991
1016
  const startBuildingDeadline = buildDeadline ? new Date(buildDeadline.getTime() - this.timetable.minExecutionTime * 1000) : undefined;
992
1017
  let availableTxs = await this.p2pClient.getPendingTxCount();
@@ -1006,7 +1031,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1006
1031
  slot: this.slot,
1007
1032
  indexWithinCheckpoint
1008
1033
  });
1009
- await sleep(TXS_POLLING_MS);
1034
+ await this.waitForTxsPollingInterval();
1010
1035
  availableTxs = await this.p2pClient.getPendingTxCount();
1011
1036
  }
1012
1037
  return {
@@ -1041,7 +1066,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1041
1066
  return new CommitteeAttestationsAndSigners(orderAttestations(attestations ?? [], committee));
1042
1067
  }
1043
1068
  const attestationTimeAllowed = this.config.enforceTimeTable ? this.timetable.getMaxAllowedTime(SequencerState.PUBLISHING_CHECKPOINT) : this.l1Constants.slotDuration;
1044
- const attestationDeadline = new Date(this.dateProvider.now() + attestationTimeAllowed * 1000);
1069
+ const attestationDeadline = new Date((this.getSlotStartBuildTimestamp() + attestationTimeAllowed) * 1000);
1045
1070
  this.metrics.recordRequiredAttestations(numberOfRequiredAttestations, attestationTimeAllowed);
1046
1071
  const collectAttestationsTimer = new Timer();
1047
1072
  let collectedAttestationsCount = 0;
@@ -1108,7 +1133,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1108
1133
  const failedTxData = failedTxs.map((fail)=>fail.tx);
1109
1134
  const failedTxHashes = failedTxData.map((tx)=>tx.getTxHash());
1110
1135
  this.log.verbose(`Dropping failed txs ${failedTxHashes.join(', ')}`);
1111
- await this.p2pClient.deleteTxs(failedTxHashes);
1136
+ await this.p2pClient.handleFailedExecution(failedTxHashes);
1112
1137
  }
1113
1138
  /**
1114
1139
  * Adds the proposed block to the archiver so it's available via P2P.
@@ -1143,15 +1168,38 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1143
1168
  slot: this.slot,
1144
1169
  feeAnalysisId: feeAnalysis?.id
1145
1170
  });
1146
- this.metrics.recordBlockProposalFailed('block_build_failed');
1171
+ this.metrics.recordCheckpointProposalFailed('block_build_failed');
1147
1172
  }
1148
1173
  this.publisher.clearPendingRequests();
1149
1174
  }
1175
+ /**
1176
+ * Helper to handle HA double-signing errors. Returns true if the error was handled (caller should yield).
1177
+ */ handleHASigningError(err, errorContext) {
1178
+ if (err instanceof DutyAlreadySignedError) {
1179
+ this.log.info(`${errorContext} for slot ${this.slot} already signed by another HA node, yielding`, {
1180
+ slot: this.slot,
1181
+ signedByNode: err.signedByNode
1182
+ });
1183
+ return true;
1184
+ }
1185
+ if (err instanceof SlashingProtectionError) {
1186
+ this.log.info(`${errorContext} for slot ${this.slot} blocked by slashing protection, yielding`, {
1187
+ slot: this.slot,
1188
+ existingMessageHash: err.existingMessageHash,
1189
+ attemptedMessageHash: err.attemptedMessageHash
1190
+ });
1191
+ return true;
1192
+ }
1193
+ return false;
1194
+ }
1150
1195
  /** Waits until a specific time within the current slot */ async waitUntilTimeInSlot(targetSecondsIntoSlot) {
1151
1196
  const slotStartTimestamp = this.getSlotStartBuildTimestamp();
1152
1197
  const targetTimestamp = slotStartTimestamp + targetSecondsIntoSlot;
1153
1198
  await sleepUntil(new Date(targetTimestamp * 1000), this.dateProvider.nowAsDate());
1154
1199
  }
1200
+ /** Waits the polling interval for transactions. Extracted for test overriding. */ async waitForTxsPollingInterval() {
1201
+ await sleep(TXS_POLLING_MS);
1202
+ }
1155
1203
  getSlotStartBuildTimestamp() {
1156
1204
  return getSlotStartBuildTimestamp(this.slot, this.l1Constants);
1157
1205
  }
@@ -21,15 +21,24 @@ export declare class SequencerMetrics {
21
21
  private slots;
22
22
  private filledSlots;
23
23
  private blockProposalFailed;
24
- private blockProposalSuccess;
25
- private blockProposalPrecheckFailed;
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;
32
37
  private fishermanIncludedBlobTxCount;
38
+ private fishermanPendingBlobCount;
39
+ private fishermanIncludedBlobCount;
40
+ private fishermanBlockBlobsFull;
41
+ private fishermanMaxBlobCapacity;
33
42
  private fishermanCalculatedPriorityFee;
34
43
  private fishermanPriorityFeeDelta;
35
44
  private fishermanEstimatedCost;
@@ -48,8 +57,11 @@ export declare class SequencerMetrics {
48
57
  incFilledSlot(proposer: string, coinbase: Hex | EthAddress | undefined): Promise<void>;
49
58
  recordCheckpointSuccess(): void;
50
59
  recordBlockProposalFailed(reason?: string): void;
51
- recordBlockProposalSuccess(): void;
52
- recordBlockProposalPrecheckFailed(checkType: string): void;
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;
53
65
  recordSlashingAttempt(actionCount: number): void;
54
66
  /**
55
67
  * Records metrics for a completed fisherman fee analysis
@@ -57,4 +69,4 @@ export declare class SequencerMetrics {
57
69
  */
58
70
  recordFishermanFeeAnalysis(analysis: L1FeeAnalysisResult): void;
59
71
  }
60
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9tZXRyaWNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN2RCxPQUFPLEtBQUssRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNoRSxPQUFPLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzNFLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sRUFNTCxLQUFLLGVBQWUsRUFDcEIsS0FBSyxNQUFNLEVBRVosTUFBTSx5QkFBeUIsQ0FBQztBQUVqQyxPQUFPLEVBQUUsS0FBSyxHQUFHLEVBQWUsTUFBTSxNQUFNLENBQUM7QUFFN0MsT0FBTyxLQUFLLEVBQUUsY0FBYyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBR2pELHFCQUFhLGdCQUFnQjtJQTJDekIsT0FBTyxDQUFDLE1BQU07SUExQ2hCLFNBQWdCLE1BQU0sRUFBRSxNQUFNLENBQUM7SUFDL0IsT0FBTyxDQUFDLEtBQUssQ0FBUTtJQUVyQixPQUFPLENBQUMsWUFBWSxDQUFnQjtJQUNwQyxPQUFPLENBQUMsa0JBQWtCLENBQVk7SUFDdEMsT0FBTyxDQUFDLHVCQUF1QixDQUFRO0lBQ3ZDLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBWTtJQUdqRCxPQUFPLENBQUMseUJBQXlCLENBQVE7SUFDekMsT0FBTyxDQUFDLDhCQUE4QixDQUFRO0lBQzlDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBUTtJQUNsQyxPQUFPLENBQUMsbUJBQW1CLENBQVE7SUFFbkMsT0FBTyxDQUFDLE9BQU8sQ0FBUTtJQUV2QixPQUFPLENBQUMsS0FBSyxDQUFnQjtJQUM3QixPQUFPLENBQUMsV0FBVyxDQUFnQjtJQUVuQyxPQUFPLENBQUMsbUJBQW1CLENBQWdCO0lBQzNDLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBZ0I7SUFDNUMsT0FBTyxDQUFDLDJCQUEyQixDQUFnQjtJQUNuRCxPQUFPLENBQUMsaUJBQWlCLENBQWdCO0lBQ3pDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBZ0I7SUFDeEMsT0FBTyxDQUFDLDBCQUEwQixDQUFZO0lBRzlDLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBZ0I7SUFDaEQsT0FBTyxDQUFDLHdCQUF3QixDQUFZO0lBQzVDLE9BQU8sQ0FBQywyQkFBMkIsQ0FBWTtJQUMvQyxPQUFPLENBQUMsNEJBQTRCLENBQVk7SUFDaEQsT0FBTyxDQUFDLDhCQUE4QixDQUFZO0lBQ2xELE9BQU8sQ0FBQyx5QkFBeUIsQ0FBWTtJQUM3QyxPQUFPLENBQUMsc0JBQXNCLENBQVk7SUFDMUMsT0FBTyxDQUFDLDZCQUE2QixDQUFZO0lBQ2pELE9BQU8sQ0FBQywrQkFBK0IsQ0FBWTtJQUNuRCxPQUFPLENBQUMsNkJBQTZCLENBQVk7SUFFakQsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFhO0lBRWxDLFlBQ0UsTUFBTSxFQUFFLGVBQWUsRUFDZixNQUFNLEVBQUUsY0FBYyxFQUM5QixJQUFJLFNBQWMsRUFtRm5CO0lBRU0sMEJBQTBCLENBQUMseUJBQXlCLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLFFBT3ZGO0lBRU0sZ0NBQWdDLENBQUMsUUFBUSxFQUFFLE1BQU0sUUFFdkQ7SUFFTSwyQkFBMkIsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLFFBR25FO0lBRUQsZ0JBQWdCLENBQUMsZUFBZSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxRQU0xRDtJQUVELGlCQUFpQixTQUloQjtJQUVELDZCQUE2QixDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLGNBQWMsUUFJdEU7SUFFRCxXQUFXLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxRQVc3QztJQUVLLGFBQWEsQ0FBQyxRQUFRLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLEdBQUcsVUFBVSxHQUFHLFNBQVMsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBaUIzRjtJQUVELHVCQUF1QixTQUV0QjtJQUVELHlCQUF5QixDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sUUFJeEM7SUFFRCwwQkFBMEIsU0FFekI7SUFFRCxpQ0FBaUMsQ0FBQyxTQUFTLEVBQUUsTUFBTSxRQUlsRDtJQUVELHFCQUFxQixDQUFDLFdBQVcsRUFBRSxNQUFNLFFBRXhDO0lBRUQ7OztPQUdHO0lBQ0gsMEJBQTBCLENBQUMsUUFBUSxFQUFFLG1CQUFtQixRQXFGdkQ7Q0FDRiJ9
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,EAEZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,KAAK,GAAG,EAAe,MAAM,MAAM,CAAC;AAE7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD,qBAAa,gBAAgB;IA2CzB,OAAO,CAAC,MAAM;IA1ChB,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAQ;IAErB,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,kBAAkB,CAAY;IACtC,OAAO,CAAC,uBAAuB,CAAQ;IACvC,OAAO,CAAC,6BAA6B,CAAY;IAGjD,OAAO,CAAC,yBAAyB,CAAQ;IACzC,OAAO,CAAC,8BAA8B,CAAQ;IAC9C,OAAO,CAAC,kBAAkB,CAAQ;IAClC,OAAO,CAAC,mBAAmB,CAAQ;IAEnC,OAAO,CAAC,OAAO,CAAQ;IAEvB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,WAAW,CAAgB;IAEnC,OAAO,CAAC,mBAAmB,CAAgB;IAC3C,OAAO,CAAC,oBAAoB,CAAgB;IAC5C,OAAO,CAAC,2BAA2B,CAAgB;IACnD,OAAO,CAAC,iBAAiB,CAAgB;IACzC,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,0BAA0B,CAAY;IAG9C,OAAO,CAAC,wBAAwB,CAAgB;IAChD,OAAO,CAAC,wBAAwB,CAAY;IAC5C,OAAO,CAAC,2BAA2B,CAAY;IAC/C,OAAO,CAAC,4BAA4B,CAAY;IAChD,OAAO,CAAC,8BAA8B,CAAY;IAClD,OAAO,CAAC,yBAAyB,CAAY;IAC7C,OAAO,CAAC,sBAAsB,CAAY;IAC1C,OAAO,CAAC,6BAA6B,CAAY;IACjD,OAAO,CAAC,+BAA+B,CAAY;IACnD,OAAO,CAAC,6BAA6B,CAAY;IAEjD,OAAO,CAAC,YAAY,CAAC,CAAa;IAElC,YACE,MAAM,EAAE,eAAe,EACf,MAAM,EAAE,cAAc,EAC9B,IAAI,SAAc,EAmFnB;IAEM,0BAA0B,CAAC,yBAAyB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,QAOvF;IAEM,gCAAgC,CAAC,QAAQ,EAAE,MAAM,QAEvD;IAEM,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAGnE;IAED,gBAAgB,CAAC,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,QAM1D;IAED,iBAAiB,SAIhB;IAED,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,QAItE;IAED,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,QAW7C;IAEK,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB3F;IAED,uBAAuB,SAEtB;IAED,yBAAyB,CAAC,MAAM,CAAC,EAAE,MAAM,QAIxC;IAED,0BAA0B,SAEzB;IAED,iCAAiC,CAAC,SAAS,EAAE,MAAM,QAIlD;IAED,qBAAqB,CAAC,WAAW,EAAE,MAAM,QAExC;IAED;;;OAGG;IACH,0BAA0B,CAAC,QAAQ,EAAE,mBAAmB,QAqFvD;CACF"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/sequencer/metrics.ts"],"names":[],"mappings":"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"}