@aztec/sequencer-client 0.0.1-commit.54489865 → 0.0.1-commit.5914bae

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 (62) hide show
  1. package/dest/client/sequencer-client.d.ts +16 -7
  2. package/dest/client/sequencer-client.d.ts.map +1 -1
  3. package/dest/client/sequencer-client.js +56 -23
  4. package/dest/config.d.ts +25 -6
  5. package/dest/config.d.ts.map +1 -1
  6. package/dest/config.js +46 -28
  7. package/dest/global_variable_builder/global_builder.d.ts +14 -10
  8. package/dest/global_variable_builder/global_builder.d.ts.map +1 -1
  9. package/dest/global_variable_builder/global_builder.js +22 -21
  10. package/dest/global_variable_builder/index.d.ts +2 -2
  11. package/dest/global_variable_builder/index.d.ts.map +1 -1
  12. package/dest/publisher/config.d.ts +31 -17
  13. package/dest/publisher/config.d.ts.map +1 -1
  14. package/dest/publisher/config.js +101 -42
  15. package/dest/publisher/sequencer-publisher-factory.d.ts +11 -3
  16. package/dest/publisher/sequencer-publisher-factory.d.ts.map +1 -1
  17. package/dest/publisher/sequencer-publisher-factory.js +13 -2
  18. package/dest/publisher/sequencer-publisher.d.ts +29 -14
  19. package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
  20. package/dest/publisher/sequencer-publisher.js +144 -74
  21. package/dest/sequencer/checkpoint_proposal_job.d.ts +30 -7
  22. package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
  23. package/dest/sequencer/checkpoint_proposal_job.js +191 -113
  24. package/dest/sequencer/checkpoint_voter.d.ts +1 -2
  25. package/dest/sequencer/checkpoint_voter.d.ts.map +1 -1
  26. package/dest/sequencer/checkpoint_voter.js +2 -5
  27. package/dest/sequencer/metrics.d.ts +17 -5
  28. package/dest/sequencer/metrics.d.ts.map +1 -1
  29. package/dest/sequencer/metrics.js +86 -15
  30. package/dest/sequencer/sequencer.d.ts +29 -13
  31. package/dest/sequencer/sequencer.d.ts.map +1 -1
  32. package/dest/sequencer/sequencer.js +47 -43
  33. package/dest/sequencer/timetable.d.ts +4 -6
  34. package/dest/sequencer/timetable.d.ts.map +1 -1
  35. package/dest/sequencer/timetable.js +7 -11
  36. package/dest/sequencer/types.d.ts +2 -2
  37. package/dest/sequencer/types.d.ts.map +1 -1
  38. package/dest/test/index.d.ts +3 -5
  39. package/dest/test/index.d.ts.map +1 -1
  40. package/dest/test/mock_checkpoint_builder.d.ts +12 -12
  41. package/dest/test/mock_checkpoint_builder.d.ts.map +1 -1
  42. package/dest/test/mock_checkpoint_builder.js +47 -36
  43. package/dest/test/utils.d.ts +3 -3
  44. package/dest/test/utils.d.ts.map +1 -1
  45. package/dest/test/utils.js +5 -4
  46. package/package.json +28 -28
  47. package/src/client/sequencer-client.ts +78 -21
  48. package/src/config.ts +61 -38
  49. package/src/global_variable_builder/global_builder.ts +23 -24
  50. package/src/global_variable_builder/index.ts +1 -1
  51. package/src/publisher/config.ts +112 -43
  52. package/src/publisher/sequencer-publisher-factory.ts +23 -6
  53. package/src/publisher/sequencer-publisher.ts +155 -87
  54. package/src/sequencer/checkpoint_proposal_job.ts +285 -159
  55. package/src/sequencer/checkpoint_voter.ts +1 -12
  56. package/src/sequencer/metrics.ts +92 -18
  57. package/src/sequencer/sequencer.ts +60 -49
  58. package/src/sequencer/timetable.ts +13 -12
  59. package/src/sequencer/types.ts +1 -1
  60. package/src/test/index.ts +2 -4
  61. package/src/test/mock_checkpoint_builder.ts +67 -53
  62. package/src/test/utils.ts +5 -2
@@ -1 +1 @@
1
- {"version":3,"file":"checkpoint_proposal_job.d.ts","sourceRoot":"","sources":["../../src/sequencer/checkpoint_proposal_job.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checkpoint_proposal_job.d.ts","sourceRoot":"","sources":["../../src/sequencer/checkpoint_proposal_job.ts"],"names":[],"mappings":"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"}
@@ -436,21 +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
- import { BlockNumber } from '@aztec/foundation/branded-types';
439
+ import { BlockNumber, IndexWithinCheckpoint } from '@aztec/foundation/branded-types';
442
440
  import { randomInt } from '@aztec/foundation/crypto/random';
443
- import { Signature } from '@aztec/foundation/eth-signature';
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
- import { unfreeze } from '@aztec/foundation/types';
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';
451
+ import { InsufficientValidTxsError } from '@aztec/stdlib/interfaces/server';
452
452
  import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
453
- import { orderAttestations } from '@aztec/stdlib/p2p';
453
+ import { orderAttestations, trimAttestations } from '@aztec/stdlib/p2p';
454
454
  import { AttestationTimeoutError } from '@aztec/stdlib/validators';
455
455
  import { Attributes, trackSpan } from '@aztec/telemetry-client';
456
456
  import { DutyAlreadySignedError, SlashingProtectionError } from '@aztec/validator-ha-signer/errors';
@@ -589,7 +589,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
589
589
  // Wait until the voting promises have resolved, so all requests are enqueued (not sent)
590
590
  await Promise.all(votesPromises);
591
591
  if (checkpoint) {
592
- this.metrics.recordBlockProposalSuccess();
592
+ this.metrics.recordCheckpointProposalSuccess();
593
593
  }
594
594
  // Do not post anything to L1 if we are fishermen, but do perform L1 fee analysis
595
595
  if (this.config.fishermanMode) {
@@ -639,13 +639,14 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
639
639
  const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(this.checkpointNumber);
640
640
  const inHash = computeInHashFromL1ToL2Messages(l1ToL2Messages);
641
641
  // Collect the out hashes of all the checkpoints before this one in the same epoch
642
- const previousCheckpoints = (await this.l2BlockSource.getCheckpointsForEpoch(this.epoch)).filter((c)=>c.number < this.checkpointNumber);
643
- 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);
643
+ // Get the fee asset price modifier from the oracle
644
+ const feeAssetPriceModifier = await this.publisher.getFeeAssetPriceModifier();
644
645
  const fork = _ts_add_disposable_resource(env, await this.worldState.fork(this.syncedToBlockNumber, {
645
646
  closeDelayMs: 12_000
646
- }), false);
647
+ }), true);
647
648
  // Create checkpoint builder for the entire slot
648
- const checkpointBuilder = await this.checkpointsBuilder.startCheckpoint(this.checkpointNumber, checkpointGlobalVariables, l1ToL2Messages, previousCheckpointOutHashes, fork, this.log.getBindings());
649
+ const checkpointBuilder = await this.checkpointsBuilder.startCheckpoint(this.checkpointNumber, checkpointGlobalVariables, feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, this.log.getBindings());
649
650
  // Options for the validator client when creating block and checkpoint proposals
650
651
  const blockProposalOptions = {
651
652
  publishFullTxs: !!this.config.publishTxsWithProposals,
@@ -657,6 +658,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
657
658
  };
658
659
  let blocksInCheckpoint = [];
659
660
  let blockPendingBroadcast = undefined;
661
+ const checkpointBuildTimer = new Timer();
660
662
  try {
661
663
  // Main loop: build blocks for the checkpoint
662
664
  const result = await this.buildBlocksForCheckpoint(checkpointBuilder, checkpointGlobalVariables.timestamp, inHash, blockProposalOptions);
@@ -666,19 +668,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
666
668
  // These errors are expected in HA mode, so we yield and let another HA node handle the slot
667
669
  // The only distinction between the 2 errors is SlashingProtectionError throws when the payload is different,
668
670
  // which is normal for block building (may have picked different txs)
669
- if (err instanceof DutyAlreadySignedError) {
670
- this.log.info(`Checkpoint proposal for slot ${this.slot} already signed by another HA node, yielding`, {
671
- slot: this.slot,
672
- signedByNode: err.signedByNode
673
- });
674
- return undefined;
675
- }
676
- if (err instanceof SlashingProtectionError) {
677
- this.log.info(`Checkpoint proposal for slot ${this.slot} blocked by slashing protection, yielding`, {
678
- slot: this.slot,
679
- existingMessageHash: err.existingMessageHash,
680
- attemptedMessageHash: err.attemptedMessageHash
681
- });
671
+ if (this.handleHASigningError(err, 'Block proposal')) {
682
672
  return undefined;
683
673
  }
684
674
  throw err;
@@ -692,10 +682,37 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
692
682
  });
693
683
  return undefined;
694
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
+ }
695
694
  // Assemble and broadcast the checkpoint proposal, including the last block that was not
696
695
  // broadcasted yet, and wait to collect the committee attestations.
697
696
  this.setStateFn(SequencerState.ASSEMBLING_CHECKPOINT, this.slot);
698
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()));
699
716
  // Do not collect attestations nor publish to L1 in fisherman mode
700
717
  if (this.config.fishermanMode) {
701
718
  this.log.info(`Built checkpoint for slot ${this.slot} with ${blocksInCheckpoint.length} blocks. ` + `Skipping proposal in fisherman mode.`, {
@@ -713,7 +730,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
713
730
  txs: blockPendingBroadcast.txs
714
731
  };
715
732
  // Create the checkpoint proposal and broadcast it
716
- const proposal = await this.validatorClient.createCheckpointProposal(checkpoint.header, checkpoint.archive.root, lastBlock, this.proposer, checkpointProposalOptions);
733
+ const proposal = await this.validatorClient.createCheckpointProposal(checkpoint.header, checkpoint.archive.root, feeAssetPriceModifier, lastBlock, this.proposer, checkpointProposalOptions);
717
734
  const blockProposedAt = this.dateProvider.now();
718
735
  await this.p2pClient.broadcastCheckpointProposal(proposal);
719
736
  this.setStateFn(SequencerState.COLLECTING_ATTESTATIONS, this.slot);
@@ -727,20 +744,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
727
744
  attestationsSignature = await this.validatorClient.signAttestationsAndSigners(attestations, signer, this.slot, this.checkpointNumber);
728
745
  } catch (err) {
729
746
  // We shouldn't really get here since we yield to another HA node
730
- // as soon as we see these errors when creating block proposals.
731
- if (err instanceof DutyAlreadySignedError) {
732
- this.log.info(`Attestations signature for slot ${this.slot} already signed by another HA node, yielding`, {
733
- slot: this.slot,
734
- signedByNode: err.signedByNode
735
- });
736
- return undefined;
737
- }
738
- if (err instanceof SlashingProtectionError) {
739
- this.log.info(`Attestations signature for slot ${this.slot} blocked by slashing protection, yielding`, {
740
- slot: this.slot,
741
- existingMessageHash: err.existingMessageHash,
742
- attemptedMessageHash: err.attemptedMessageHash
743
- });
747
+ // as soon as we see these errors when creating block or checkpoint proposals.
748
+ if (this.handleHASigningError(err, 'Attestations signature')) {
744
749
  return undefined;
745
750
  }
746
751
  throw err;
@@ -750,6 +755,14 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
750
755
  const aztecSlotDuration = this.l1Constants.slotDuration;
751
756
  const slotStartBuildTimestamp = this.getSlotStartBuildTimestamp();
752
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
+ }
753
766
  await this.publisher.enqueueProposeCheckpoint(checkpoint, attestations, attestationsSignature, {
754
767
  txTimeoutAt,
755
768
  forcePendingCheckpointNumber: this.invalidateCheckpoint?.forcePendingCheckpointNumber
@@ -759,7 +772,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
759
772
  env.error = e;
760
773
  env.hasError = true;
761
774
  } finally{
762
- _ts_dispose_resources(env);
775
+ const result = _ts_dispose_resources(env);
776
+ if (result) await result;
763
777
  }
764
778
  } catch (err) {
765
779
  if (err && (err instanceof DutyAlreadySignedError || err instanceof SlashingProtectionError)) {
@@ -776,19 +790,18 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
776
790
  const blocksInCheckpoint = [];
777
791
  const txHashesAlreadyIncluded = new Set();
778
792
  const initialBlockNumber = BlockNumber(this.syncedToBlockNumber + 1);
779
- // Remaining blob fields available for blocks (checkpoint end marker already subtracted)
780
- let remainingBlobFields = BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB - NUM_CHECKPOINT_END_MARKER_FIELDS;
793
+ const slot = this.slot;
781
794
  // Last block in the checkpoint will usually be flagged as pending broadcast, so we send it along with the checkpoint proposal
782
795
  let blockPendingBroadcast = undefined;
783
796
  while(true){
784
797
  const blocksBuilt = blocksInCheckpoint.length;
785
- const indexWithinCheckpoint = blocksBuilt;
798
+ const indexWithinCheckpoint = IndexWithinCheckpoint(blocksBuilt);
786
799
  const blockNumber = BlockNumber(initialBlockNumber + blocksBuilt);
787
800
  const secondsIntoSlot = this.getSecondsIntoSlot();
788
801
  const timingInfo = this.timetable.canStartNextBlock(secondsIntoSlot);
789
802
  if (!timingInfo.canStart) {
790
803
  this.log.debug(`Not enough time left in slot to start another block`, {
791
- slot: this.slot,
804
+ slot,
792
805
  blocksBuilt,
793
806
  secondsIntoSlot
794
807
  });
@@ -803,9 +816,9 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
803
816
  buildDeadline: timingInfo.deadline ? new Date((this.getSlotStartBuildTimestamp() + timingInfo.deadline) * 1000) : undefined,
804
817
  blockNumber,
805
818
  indexWithinCheckpoint,
806
- txHashesAlreadyIncluded,
807
- remainingBlobFields
819
+ txHashesAlreadyIncluded
808
820
  });
821
+ // TODO(palla/mbps): Review these conditions. We may want to keep trying in some scenarios.
809
822
  if (!buildResult && timingInfo.isLastBlock) {
810
823
  break;
811
824
  } else if (!buildResult && timingInfo.deadline !== undefined) {
@@ -817,33 +830,23 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
817
830
  } else if ('error' in buildResult) {
818
831
  // If there was an error building the block, just exit the loop and give up the rest of the slot
819
832
  if (!(buildResult.error instanceof SequencerInterruptedError)) {
820
- this.log.warn(`Halting block building for slot ${this.slot}`, {
821
- slot: this.slot,
833
+ this.log.warn(`Halting block building for slot ${slot}`, {
834
+ slot,
822
835
  blocksBuilt,
823
836
  error: buildResult.error
824
837
  });
825
838
  }
826
839
  break;
827
840
  }
828
- const { block, usedTxs, remainingBlobFields: newRemainingBlobFields } = buildResult;
841
+ const { block, usedTxs } = buildResult;
829
842
  blocksInCheckpoint.push(block);
830
- // Update remaining blob fields for the next block
831
- remainingBlobFields = newRemainingBlobFields;
832
- // Sync the proposed block to the archiver to make it available
833
- // Note that the checkpoint builder uses its own fork so it should not need to wait for this syncing
834
- // Eventually we should refactor the checkpoint builder to not need a separate long-lived fork
835
- // Fire and forget - don't block the critical path, but log errors
836
- this.syncProposedBlockToArchiver(block).catch((err)=>{
837
- this.log.error(`Failed to sync proposed block ${block.number} to archiver`, {
838
- blockNumber: block.number,
839
- err
840
- });
841
- });
842
843
  usedTxs.forEach((tx)=>txHashesAlreadyIncluded.add(tx.txHash.toString()));
843
- // If this is the last block, exit the loop now so we start collecting attestations
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.
844
846
  if (timingInfo.isLastBlock) {
845
- this.log.verbose(`Completed final block ${blockNumber} for slot ${this.slot}`, {
846
- slot: this.slot,
847
+ await this.syncProposedBlockToArchiver(block);
848
+ this.log.verbose(`Completed final block ${blockNumber} for slot ${slot}`, {
849
+ slot,
847
850
  blockNumber,
848
851
  blocksBuilt
849
852
  });
@@ -853,12 +856,17 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
853
856
  };
854
857
  break;
855
858
  }
856
- // For non-last blocks, broadcast the block proposal (unless we're in fisherman mode)
857
- // If the block is the last one, we'll broadcast it along with the checkpoint at the end of the loop
858
- if (!this.config.fishermanMode) {
859
- const proposal = await this.validatorClient.createBlockProposal(block.header, block.indexWithinCheckpoint, inHash, block.archive.root, usedTxs, this.proposer, blockProposalOptions);
860
- await this.p2pClient.broadcastProposal(proposal);
861
- }
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);
862
870
  // Wait until the next block's start time
863
871
  await this.waitUntilNextSubslot(timingInfo.deadline);
864
872
  }
@@ -871,6 +879,13 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
871
879
  blockPendingBroadcast
872
880
  };
873
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
+ }
874
889
  /** Sleeps until it is time to produce the next block in the slot */ async waitUntilNextSubslot(nextSubslotStart) {
875
890
  this.setStateFn(SequencerState.WAITING_UNTIL_NEXT_BLOCK, this.slot);
876
891
  this.log.verbose(`Waiting until time for the next block at ${nextSubslotStart}s into slot`, {
@@ -879,15 +894,14 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
879
894
  await this.waitUntilTimeInSlot(nextSubslotStart);
880
895
  }
881
896
  /** Builds a single block. Called from the main block building loop. */ async buildSingleBlock(checkpointBuilder, opts) {
882
- const { blockTimestamp, forceCreate, blockNumber, indexWithinCheckpoint, buildDeadline, txHashesAlreadyIncluded, remainingBlobFields } = opts;
897
+ const { blockTimestamp, forceCreate, blockNumber, indexWithinCheckpoint, buildDeadline, txHashesAlreadyIncluded } = opts;
883
898
  this.log.verbose(`Preparing block ${blockNumber} index ${indexWithinCheckpoint} at checkpoint ${this.checkpointNumber} for slot ${this.slot}`, {
884
899
  ...checkpointBuilder.getConstantData(),
885
900
  ...opts
886
901
  });
887
902
  try {
888
903
  // Wait until we have enough txs to build the block
889
- const minTxs = this.config.minTxsPerBlock;
890
- const { availableTxs, canStartBuilding } = await this.waitForMinTxs(opts);
904
+ const { availableTxs, canStartBuilding, minTxs } = await this.waitForMinTxs(opts);
891
905
  if (!canStartBuilding) {
892
906
  this.log.warn(`Not enough txs to build block ${blockNumber} at index ${indexWithinCheckpoint} in slot ${this.slot} (got ${availableTxs} txs but needs ${minTxs})`, {
893
907
  blockNumber,
@@ -904,58 +918,58 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
904
918
  }
905
919
  // Create iterator to pending txs. We filter out txs already included in previous blocks in the checkpoint
906
920
  // just in case p2p failed to sync the provisional block and didn't get to remove those txs from the mempool yet.
907
- const pendingTxs = filter(this.p2pClient.iteratePendingTxs(), (tx)=>!txHashesAlreadyIncluded.has(tx.txHash.toString()));
921
+ const pendingTxs = filter(this.p2pClient.iterateEligiblePendingTxs(), (tx)=>!txHashesAlreadyIncluded.has(tx.txHash.toString()));
908
922
  this.log.debug(`Building block ${blockNumber} at index ${indexWithinCheckpoint} for slot ${this.slot} with ${availableTxs} available txs`, {
909
923
  slot: this.slot,
910
924
  blockNumber,
911
925
  indexWithinCheckpoint
912
926
  });
913
927
  this.setStateFn(SequencerState.CREATING_BLOCK, this.slot);
914
- // Calculate blob fields limit for txs (remaining capacity - this block's end overhead)
915
- const blockEndOverhead = getNumBlockEndBlobFields(indexWithinCheckpoint === 0);
916
- const maxBlobFieldsForTxs = remainingBlobFields - blockEndOverhead;
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;
917
932
  const blockBuilderOptions = {
918
933
  maxTransactions: this.config.maxTxsPerBlock,
919
- maxBlockSize: this.config.maxBlockSizeInBytes,
920
- maxBlockGas: new Gas(this.config.maxDABlockGas, this.config.maxL2BlockGas),
921
- maxBlobFields: maxBlobFieldsForTxs,
922
- deadline: buildDeadline
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
923
940
  };
924
- // Actually build the block by executing txs
925
- const workTimer = new Timer();
926
- const { publicGas, block, publicProcessorDuration, numTxs, blockBuildingTimer, usedTxs, failedTxs, usedTxBlobFields } = await checkpointBuilder.buildBlock(pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions);
927
- const blockBuildDuration = workTimer.ms();
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.
944
+ const buildResult = await this.buildSingleBlockWithCheckpointBuilder(checkpointBuilder, pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions);
928
945
  // If any txs failed during execution, drop them from the mempool so we don't pick them up again
929
- await this.dropFailedTxsFromP2P(failedTxs);
930
- // Check if we have created a block with enough txs. If there were invalid txs in the pool, or if execution took
931
- // too long, then we may not get to minTxsPerBlock after executing public functions.
932
- const minValidTxs = this.config.minValidTxsPerBlock ?? minTxs;
933
- if (!forceCreate && numTxs < minValidTxs) {
934
- 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})`, {
946
+ await this.dropFailedTxsFromP2P(buildResult.failedTxs);
947
+ if (buildResult.status === 'insufficient-valid-txs') {
948
+ this.log.warn(`Block ${blockNumber} at index ${indexWithinCheckpoint} on slot ${this.slot} has too few valid txs to be proposed`, {
935
949
  slot: this.slot,
936
950
  blockNumber,
937
- numTxs,
938
- indexWithinCheckpoint
951
+ numTxs: buildResult.processedCount,
952
+ indexWithinCheckpoint,
953
+ minValidTxs
939
954
  });
940
- this.eventEmitter.emit('block-tx-count-check-failed', {
941
- minTxs: minValidTxs,
942
- availableTxs: numTxs,
955
+ this.eventEmitter.emit('block-build-failed', {
956
+ reason: `Insufficient valid txs`,
943
957
  slot: this.slot
944
958
  });
945
959
  this.metrics.recordBlockProposalFailed('insufficient_valid_txs');
946
960
  return undefined;
947
961
  }
948
962
  // Block creation succeeded, emit stats and metrics
963
+ const { block, publicProcessorDuration, usedTxs, blockBuildDuration, numTxs } = buildResult;
949
964
  const blockStats = {
950
965
  eventName: 'l2-block-built',
951
966
  duration: blockBuildDuration,
952
967
  publicProcessDuration: publicProcessorDuration,
953
- rollupCircuitsDuration: blockBuildingTimer.ms(),
954
968
  ...block.getStats()
955
969
  };
956
970
  const blockHash = await block.hash();
957
971
  const txHashes = block.body.txEffects.map((tx)=>tx.txHash);
958
- const manaPerSec = publicGas.l2Gas / (blockBuildDuration / 1000);
972
+ const manaPerSec = block.header.totalManaUsed.toNumberUnsafe() / (blockBuildDuration / 1000);
959
973
  this.log.info(`Built block ${block.number} at checkpoint ${this.checkpointNumber} for slot ${this.slot} with ${numTxs} txs`, {
960
974
  blockHash,
961
975
  txHashes,
@@ -966,11 +980,10 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
966
980
  blockNumber: block.number,
967
981
  slot: this.slot
968
982
  });
969
- this.metrics.recordBuiltBlock(blockBuildDuration, publicGas.l2Gas);
983
+ this.metrics.recordBuiltBlock(blockBuildDuration, block.header.totalManaUsed.toNumberUnsafe());
970
984
  return {
971
985
  block,
972
- usedTxs,
973
- remainingBlobFields: maxBlobFieldsForTxs - usedTxBlobFields
986
+ usedTxs
974
987
  };
975
988
  } catch (err) {
976
989
  this.eventEmitter.emit('block-build-failed', {
@@ -988,9 +1001,31 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
988
1001
  };
989
1002
  }
990
1003
  }
1004
+ /** Uses the checkpoint builder to build a block, catching InsufficientValidTxsError. */ async buildSingleBlockWithCheckpointBuilder(checkpointBuilder, pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions) {
1005
+ try {
1006
+ const workTimer = new Timer();
1007
+ const result = await checkpointBuilder.buildBlock(pendingTxs, blockNumber, blockTimestamp, blockBuilderOptions);
1008
+ const blockBuildDuration = workTimer.ms();
1009
+ return {
1010
+ ...result,
1011
+ blockBuildDuration,
1012
+ status: 'success'
1013
+ };
1014
+ } catch (err) {
1015
+ if (isErrorClass(err, InsufficientValidTxsError)) {
1016
+ return {
1017
+ failedTxs: err.failedTxs,
1018
+ processedCount: err.processedCount,
1019
+ status: 'insufficient-valid-txs'
1020
+ };
1021
+ }
1022
+ throw err;
1023
+ }
1024
+ }
991
1025
  /** Waits until minTxs are available on the pool for building a block. */ async waitForMinTxs(opts) {
992
- const minTxs = this.config.minTxsPerBlock;
993
1026
  const { indexWithinCheckpoint, blockNumber, buildDeadline, forceCreate } = opts;
1027
+ // We only allow a block with 0 txs in the first block of the checkpoint
1028
+ const minTxs = indexWithinCheckpoint > 0 && this.config.minTxsPerBlock === 0 ? 1 : this.config.minTxsPerBlock;
994
1029
  // Deadline is undefined if we are not enforcing the timetable, meaning we'll exit immediately when out of time
995
1030
  const startBuildingDeadline = buildDeadline ? new Date(buildDeadline.getTime() - this.timetable.minExecutionTime * 1000) : undefined;
996
1031
  let availableTxs = await this.p2pClient.getPendingTxCount();
@@ -1000,7 +1035,8 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1000
1035
  if (startBuildingDeadline === undefined || now >= startBuildingDeadline) {
1001
1036
  return {
1002
1037
  canStartBuilding: false,
1003
- availableTxs: availableTxs
1038
+ availableTxs,
1039
+ minTxs
1004
1040
  };
1005
1041
  }
1006
1042
  // Wait a bit before checking again
@@ -1010,12 +1046,13 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1010
1046
  slot: this.slot,
1011
1047
  indexWithinCheckpoint
1012
1048
  });
1013
- await sleep(TXS_POLLING_MS);
1049
+ await this.waitForTxsPollingInterval();
1014
1050
  availableTxs = await this.p2pClient.getPendingTxCount();
1015
1051
  }
1016
1052
  return {
1017
1053
  canStartBuilding: true,
1018
- availableTxs
1054
+ availableTxs,
1055
+ minTxs
1019
1056
  };
1020
1057
  }
1021
1058
  /**
@@ -1052,10 +1089,16 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1052
1089
  try {
1053
1090
  const attestations = await this.validatorClient.collectAttestations(proposal, numberOfRequiredAttestations, attestationDeadline);
1054
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
+ }
1055
1098
  // Rollup contract requires that the signatures are provided in the order of the committee
1056
- const sorted = orderAttestations(attestations, committee);
1099
+ const sorted = orderAttestations(trimmed, committee);
1057
1100
  // Manipulate the attestations if we've been configured to do so
1058
- if (this.config.injectFakeAttestation || this.config.shuffleAttestationOrdering) {
1101
+ if (this.config.injectFakeAttestation || this.config.injectHighSValueAttestation || this.config.injectUnrecoverableSignatureAttestation || this.config.shuffleAttestationOrdering) {
1059
1102
  return this.manipulateAttestations(proposal.slotNumber, epoch, seed, committee, sorted);
1060
1103
  }
1061
1104
  return new CommitteeAttestationsAndSigners(sorted);
@@ -1072,7 +1115,7 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1072
1115
  // Compute the proposer index in the committee, since we dont want to tweak it.
1073
1116
  // Otherwise, the L1 rollup contract will reject the block outright.
1074
1117
  const proposerIndex = Number(this.epochCache.computeProposerIndex(slotNumber, epoch, seed, BigInt(committee.length)));
1075
- if (this.config.injectFakeAttestation) {
1118
+ if (this.config.injectFakeAttestation || this.config.injectHighSValueAttestation || this.config.injectUnrecoverableSignatureAttestation) {
1076
1119
  // Find non-empty attestations that are not from the proposer
1077
1120
  const nonProposerIndices = [];
1078
1121
  for(let i = 0; i < attestations.length; i++){
@@ -1082,8 +1125,16 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1082
1125
  }
1083
1126
  if (nonProposerIndices.length > 0) {
1084
1127
  const targetIndex = nonProposerIndices[randomInt(nonProposerIndices.length)];
1085
- this.log.warn(`Injecting fake attestation in checkpoint for slot ${slotNumber} at index ${targetIndex}`);
1086
- unfreeze(attestations[targetIndex]).signature = Signature.random();
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
+ }
1087
1138
  }
1088
1139
  return new CommitteeAttestationsAndSigners(attestations);
1089
1140
  }
@@ -1112,14 +1163,18 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1112
1163
  const failedTxData = failedTxs.map((fail)=>fail.tx);
1113
1164
  const failedTxHashes = failedTxData.map((tx)=>tx.getTxHash());
1114
1165
  this.log.verbose(`Dropping failed txs ${failedTxHashes.join(', ')}`);
1115
- await this.p2pClient.deleteTxs(failedTxHashes);
1166
+ await this.p2pClient.handleFailedExecution(failedTxHashes);
1116
1167
  }
1117
1168
  /**
1118
1169
  * Adds the proposed block to the archiver so it's available via P2P.
1119
1170
  * Gossip doesn't echo messages back to the sender, so the proposer's archiver/world-state
1120
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.
1121
1176
  */ async syncProposedBlockToArchiver(block) {
1122
- if (this.config.skipPushProposedBlocksToArchiver !== false) {
1177
+ if (this.config.skipPushProposedBlocksToArchiver !== false || this.config.fishermanMode) {
1123
1178
  this.log.warn(`Skipping push of proposed block ${block.number} to archiver`, {
1124
1179
  blockNumber: block.number,
1125
1180
  slot: block.header.globalVariables.slotNumber
@@ -1147,15 +1202,38 @@ _dec = trackSpan('CheckpointProposalJob.execute'), _dec1 = trackSpan('Checkpoint
1147
1202
  slot: this.slot,
1148
1203
  feeAnalysisId: feeAnalysis?.id
1149
1204
  });
1150
- this.metrics.recordBlockProposalFailed('block_build_failed');
1205
+ this.metrics.recordCheckpointProposalFailed('block_build_failed');
1151
1206
  }
1152
1207
  this.publisher.clearPendingRequests();
1153
1208
  }
1209
+ /**
1210
+ * Helper to handle HA double-signing errors. Returns true if the error was handled (caller should yield).
1211
+ */ handleHASigningError(err, errorContext) {
1212
+ if (err instanceof DutyAlreadySignedError) {
1213
+ this.log.info(`${errorContext} for slot ${this.slot} already signed by another HA node, yielding`, {
1214
+ slot: this.slot,
1215
+ signedByNode: err.signedByNode
1216
+ });
1217
+ return true;
1218
+ }
1219
+ if (err instanceof SlashingProtectionError) {
1220
+ this.log.info(`${errorContext} for slot ${this.slot} blocked by slashing protection, yielding`, {
1221
+ slot: this.slot,
1222
+ existingMessageHash: err.existingMessageHash,
1223
+ attemptedMessageHash: err.attemptedMessageHash
1224
+ });
1225
+ return true;
1226
+ }
1227
+ return false;
1228
+ }
1154
1229
  /** Waits until a specific time within the current slot */ async waitUntilTimeInSlot(targetSecondsIntoSlot) {
1155
1230
  const slotStartTimestamp = this.getSlotStartBuildTimestamp();
1156
1231
  const targetTimestamp = slotStartTimestamp + targetSecondsIntoSlot;
1157
1232
  await sleepUntil(new Date(targetTimestamp * 1000), this.dateProvider.nowAsDate());
1158
1233
  }
1234
+ /** Waits the polling interval for transactions. Extracted for test overriding. */ async waitForTxsPollingInterval() {
1235
+ await sleep(TXS_POLLING_MS);
1236
+ }
1159
1237
  getSlotStartBuildTimestamp() {
1160
1238
  return getSlotStartBuildTimestamp(this.slot, this.l1Constants);
1161
1239
  }
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludF92b3Rlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcXVlbmNlci9jaGVja3BvaW50X3ZvdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xFLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BELE9BQU8sS0FBSyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFN0QsT0FBTyxLQUFLLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMvRSxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQU0vRCxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzlFLE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3JELE9BQU8sS0FBSyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBRTNEOztHQUVHO0FBQ0gscUJBQWEsZUFBZTtJQU14QixPQUFPLENBQUMsUUFBUSxDQUFDLElBQUk7SUFDckIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTO0lBQzFCLE9BQU8sQ0FBQyxRQUFRLENBQUMsZUFBZTtJQUNoQyxPQUFPLENBQUMsUUFBUSxDQUFDLGVBQWU7SUFDaEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxhQUFhO0lBQzlCLE9BQU8sQ0FBQyxRQUFRLENBQUMsV0FBVztJQUM1QixPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU07SUFDdkIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPO0lBQ3hCLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRztJQWJ0QixPQUFPLENBQUMsYUFBYSxDQUFTO0lBQzlCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBdUQ7SUFDL0UsT0FBTyxDQUFDLGNBQWMsQ0FBdUQ7SUFFN0UsWUFDbUIsSUFBSSxFQUFFLFVBQVUsRUFDaEIsU0FBUyxFQUFFLGtCQUFrQixFQUM3QixlQUFlLEVBQUUsVUFBVSxFQUMzQixlQUFlLEVBQUUsZUFBZSxFQUNoQyxhQUFhLEVBQUUsc0JBQXNCLEdBQUcsU0FBUyxFQUNqRCxXQUFXLEVBQUUsd0JBQXdCLEVBQ3JDLE1BQU0sRUFBRSx1QkFBdUIsRUFDL0IsT0FBTyxFQUFFLGdCQUFnQixFQUN6QixHQUFHLEVBQUUsTUFBTSxFQWE3QjtJQUVEOzs7T0FHRztJQUNILFlBQVksSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFDLEVBQUUsT0FBTyxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsQ0FBQyxDQVUzRTtZQUVhLHFCQUFxQjtZQWdDckIsbUJBQW1CO0NBaUNsQyJ9
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;AAE7D,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;IAMxB,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;IAbtB,OAAO,CAAC,aAAa,CAAS;IAC9B,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,EAa7B;IAED;;;OAGG;IACH,YAAY,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC,CAU3E;YAEa,qBAAqB;YAgCrB,mBAAmB;CAiClC"}
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"}