@aztec/sequencer-client 0.0.1-commit.0dc957cde → 0.0.1-commit.0ec55a70b

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.
@@ -449,8 +449,11 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
449
449
  }
450
450
  runningPromise;
451
451
  state;
452
+ stateSlotNumber;
453
+ stateEnteredAtMs;
452
454
  metrics;
453
455
  checkpointProposalJobMetrics;
456
+ stateLog;
454
457
  /** The last slot for which we attempted to perform our voting duties with degraded block production */ lastSlotForFallbackVote;
455
458
  /** The last slot for which we logged "no committee" warning, to avoid spam */ lastSlotForNoCommitteeWarning;
456
459
  /** The last slot for which we triggered a checkpoint proposal job, to prevent duplicate attempts. */ lastSlotForCheckpointProposalJob;
@@ -459,12 +462,18 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
459
462
  /** The last checkpoint proposal job, tracked so we can await its pending L1 submission during shutdown. */ lastCheckpointProposalJob;
460
463
  /** The maximum number of seconds that the sequencer can be into a slot to transition to a particular state. */ timetable;
461
464
  /** Config for the sequencer */ config;
465
+ signatureContext;
462
466
  constructor(publisherFactory, validatorClient, globalsBuilder, p2pClient, worldState, slasherClient, l2BlockSource, l1ToL2MessageSource, checkpointsBuilder, l1Constants, dateProvider, epochCache, rollupContract, config, telemetry = getTelemetryClient(), log = createLogger('sequencer')){
463
- super(), this.publisherFactory = publisherFactory, this.validatorClient = validatorClient, this.globalsBuilder = globalsBuilder, this.p2pClient = p2pClient, this.worldState = worldState, this.slasherClient = slasherClient, this.l2BlockSource = l2BlockSource, this.l1ToL2MessageSource = l1ToL2MessageSource, this.checkpointsBuilder = checkpointsBuilder, this.l1Constants = l1Constants, this.dateProvider = dateProvider, this.epochCache = epochCache, this.rollupContract = rollupContract, this.telemetry = telemetry, this.log = log, this.state = (_initProto(this), SequencerState.STOPPED), this.config = DefaultSequencerConfig;
467
+ super(), this.publisherFactory = publisherFactory, this.validatorClient = validatorClient, this.globalsBuilder = globalsBuilder, this.p2pClient = p2pClient, this.worldState = worldState, this.slasherClient = slasherClient, this.l2BlockSource = l2BlockSource, this.l1ToL2MessageSource = l1ToL2MessageSource, this.checkpointsBuilder = checkpointsBuilder, this.l1Constants = l1Constants, this.dateProvider = dateProvider, this.epochCache = epochCache, this.rollupContract = rollupContract, this.telemetry = telemetry, this.log = log, this.state = (_initProto(this), SequencerState.STOPPED), this.stateEnteredAtMs = performance.now(), this.config = DefaultSequencerConfig;
468
+ this.stateLog = log.createChild('state');
464
469
  // Add [FISHERMAN] prefix to logger if in fisherman mode
465
470
  if (config.fishermanMode) {
466
471
  this.log = log.createChild('[FISHERMAN]');
467
472
  }
473
+ this.signatureContext = {
474
+ chainId: config.l1ChainId,
475
+ rollupAddress: config.l1Contracts.rollupAddress
476
+ };
468
477
  this.metrics = new SequencerMetrics(telemetry, this.rollupContract, 'Sequencer');
469
478
  this.checkpointProposalJobMetrics = new CheckpointProposalJobMetrics(telemetry);
470
479
  this.updateConfig(config);
@@ -681,7 +690,7 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
681
690
  // and the archive at that checkpoint so L1 simulation sees the correct chain tip.
682
691
  const parentCheckpointNumber = CheckpointNumber(checkpointNumber - 1);
683
692
  l1SimulationOverridesBuilder.forPendingCheckpoint(parentCheckpointNumber).withPendingArchive(syncedTo.archive);
684
- this.metrics.recordPipelineDepth(1);
693
+ this.metrics.recordPipelineDepth(syncedTo.checkpointNumber - syncedTo.checkpointedCheckpointNumber);
685
694
  this.log.verbose(`Building on top of proposed checkpoint (pending=${syncedTo.proposedCheckpointData?.checkpointNumber})`);
686
695
  // Clear the invalidation - the proposed checkpoint should handle it.
687
696
  invalidateCheckpoint = undefined;
@@ -742,7 +751,7 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
742
751
  return this.createCheckpointProposalJob(slot, targetSlot, targetEpoch, checkpointNumber, syncedTo.blockNumber, proposer, publisher, attestorAddress, invalidateCheckpoint, syncedTo.proposedCheckpointData);
743
752
  }
744
753
  createCheckpointProposalJob(slot, targetSlot, targetEpoch, checkpointNumber, syncedToBlockNumber, proposer, publisher, attestorAddress, invalidateCheckpoint, proposedCheckpointData) {
745
- return new CheckpointProposalJob(slot, targetSlot, targetEpoch, checkpointNumber, syncedToBlockNumber, proposer, publisher, attestorAddress, invalidateCheckpoint, this.validatorClient, this.globalsBuilder, this.p2pClient, this.worldState, this.l1ToL2MessageSource, this.l2BlockSource, this.checkpointsBuilder, this.l2BlockSource, this.l1Constants, this.config, this.timetable, this.slasherClient, this.epochCache, this.dateProvider, this.metrics, this.checkpointProposalJobMetrics.createRecorder(), this, this.setState.bind(this), this.tracer, this.log.getBindings(), proposedCheckpointData);
754
+ return new CheckpointProposalJob(slot, targetSlot, targetEpoch, checkpointNumber, syncedToBlockNumber, proposer, publisher, attestorAddress, invalidateCheckpoint, this.validatorClient, this.globalsBuilder, this.p2pClient, this.worldState, this.l1ToL2MessageSource, this.l2BlockSource, this.checkpointsBuilder, this.l2BlockSource, this.l1Constants, this.signatureContext, this.config, this.timetable, this.slasherClient, this.epochCache, this.dateProvider, this.metrics, this.checkpointProposalJobMetrics.createRecorder(), this, this.setState.bind(this), this.tracer, this.log.getBindings(), proposedCheckpointData);
746
755
  }
747
756
  /**
748
757
  * Returns the current sequencer state.
@@ -768,21 +777,37 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
768
777
  secondsIntoSlot = this.getSecondsIntoSlot(slotNumber);
769
778
  this.timetable.assertTimeLeft(proposedState, secondsIntoSlot);
770
779
  }
780
+ const oldState = this.state;
781
+ const oldStateSlotNumber = this.stateSlotNumber;
782
+ const stateChanged = proposedState !== oldState;
783
+ const transitionAtMs = performance.now();
784
+ const stateDurationMs = transitionAtMs - this.stateEnteredAtMs;
771
785
  const boringStates = [
772
786
  SequencerState.IDLE,
773
787
  SequencerState.SYNCHRONIZING
774
788
  ];
775
- const logLevel = boringStates.includes(proposedState) && boringStates.includes(this.state) ? 'trace' : 'debug';
776
- this.log[logLevel](`Transitioning from ${this.state} to ${proposedState}`, {
789
+ const logLevel = boringStates.includes(proposedState) && boringStates.includes(oldState) ? 'trace' : 'debug';
790
+ this.stateLog[logLevel](`Transitioning from ${oldState} to ${proposedState}`, {
791
+ oldState,
792
+ newState: proposedState,
777
793
  slotNumber,
778
- secondsIntoSlot
794
+ stateSlotNumber: oldStateSlotNumber,
795
+ secondsIntoSlot,
796
+ ...stateChanged && {
797
+ stateDurationMs: Math.ceil(stateDurationMs)
798
+ }
779
799
  });
780
800
  this.emit('state-changed', {
781
- oldState: this.state,
801
+ oldState,
782
802
  newState: proposedState,
783
803
  secondsIntoSlot,
784
804
  slot: slotNumber
785
805
  });
806
+ if (stateChanged) {
807
+ this.metrics.recordStateDuration(stateDurationMs, oldState);
808
+ this.stateEnteredAtMs = transitionAtMs;
809
+ this.stateSlotNumber = slotNumber;
810
+ }
786
811
  this.state = proposedState;
787
812
  }
788
813
  /**
@@ -817,7 +842,7 @@ _dec = trackSpan('Sequencer.work'), _dec1 = trackSpan('Sequencer.prepareCheckpoi
817
842
  checkpointed: t.checkpointed
818
843
  })),
819
844
  this.l2BlockSource.getPendingChainValidationStatus(),
820
- this.l2BlockSource.getProposedCheckpointOnly()
845
+ this.l2BlockSource.getLastProposedCheckpoint()
821
846
  ]);
822
847
  const [worldState, l2Tips, p2p, l1ToL2MessageSourceTips, pendingChainValidationStatus, proposedCheckpointData] = syncedBlocks;
823
848
  // Handle zero as a special case, since the block hash won't match across services if we're changing the prefilled data for the genesis block,
@@ -50,4 +50,4 @@ export declare function setupTxsAndBlock(p2p: MockProxy<P2P>, globalVariables: G
50
50
  txs: Tx[];
51
51
  block: L2Block;
52
52
  }>;
53
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUM1RSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzVELE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV0QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxxQkFBcUIsRUFBRSxrQkFBa0IsRUFBb0IsTUFBTSxtQkFBbUIsQ0FBQztBQUcvRyxPQUFPLEVBQWUsZUFBZSxFQUFFLEtBQUssRUFBRSxFQUFvQyxNQUFNLGtCQUFrQixDQUFDO0FBRTNHLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBR3BELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBRTdGOztHQUVHO0FBQ0gsd0JBQXNCLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FNckU7QUFFRDs7R0FFRztBQUNILHdCQUFzQixTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLGVBQWUsRUFBRSxlQUFlLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQWdCN0Y7QUFFRDs7R0FFRztBQUNILHdCQUFnQixjQUFjLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUluRTtBQUVEOztHQUVHO0FBQ0gsd0JBQXVCLGNBQWMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcscUJBQXFCLENBQUMsRUFBRSxDQUFDLENBSW5GO0FBRUQ7O0dBRUc7QUFDSCx3QkFBZ0Isb0JBQW9CLENBQUMsTUFBTSxFQUFFLGVBQWUsR0FBRyxvQkFBb0IsRUFBRSxDQUdwRjtBQXVCRDs7R0FFRztBQUNILHdCQUFnQixtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEdBQUcsYUFBYSxDQVV2RjtBQUVEOztHQUVHO0FBQ0gsd0JBQWdCLHdCQUF3QixDQUN0QyxLQUFLLEVBQUUsT0FBTyxFQUNkLG1CQUFtQixFQUFFLFNBQVMsRUFDOUIsY0FBYyxDQUFDLEVBQUUsU0FBUyxFQUMxQixxQkFBcUIsR0FBRSxNQUFXLEdBQ2pDLGtCQUFrQixDQVNwQjtBQUVEOzs7O0dBSUc7QUFDSCx3QkFBZ0IsMkJBQTJCLENBQ3pDLEtBQUssRUFBRSxPQUFPLEVBQ2QsU0FBUyxFQUFFLFNBQVMsRUFDcEIsTUFBTSxFQUFFLFVBQVUsRUFDbEIscUJBQXFCLEdBQUUsTUFBVyxHQUNqQyxxQkFBcUIsQ0FPdkI7QUFFRDs7O0dBR0c7QUFDSCx3QkFBc0IsZ0JBQWdCLENBQ3BDLEdBQUcsRUFBRSxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQ25CLGVBQWUsRUFBRSxlQUFlLEVBQ2hDLE9BQU8sRUFBRSxNQUFNLEVBQ2YsT0FBTyxFQUFFLEVBQUUsR0FDVixPQUFPLENBQUM7SUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFBQyxLQUFLLEVBQUUsT0FBTyxDQUFBO0NBQUUsQ0FBQyxDQUt4QyJ9
53
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUM1RSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzVELE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV0QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxxQkFBcUIsRUFBRSxrQkFBa0IsRUFBb0IsTUFBTSxtQkFBbUIsQ0FBQztBQU8vRyxPQUFPLEVBQWUsZUFBZSxFQUFFLEtBQUssRUFBRSxFQUFvQyxNQUFNLGtCQUFrQixDQUFDO0FBRTNHLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBR3BELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBRTdGOztHQUVHO0FBQ0gsd0JBQXNCLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FNckU7QUFFRDs7R0FFRztBQUNILHdCQUFzQixTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLGVBQWUsRUFBRSxlQUFlLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQWdCN0Y7QUFFRDs7R0FFRztBQUNILHdCQUFnQixjQUFjLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUluRTtBQUVEOztHQUVHO0FBQ0gsd0JBQXVCLGNBQWMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcscUJBQXFCLENBQUMsRUFBRSxDQUFDLENBSW5GO0FBRUQ7O0dBRUc7QUFDSCx3QkFBZ0Isb0JBQW9CLENBQUMsTUFBTSxFQUFFLGVBQWUsR0FBRyxvQkFBb0IsRUFBRSxDQUdwRjtBQXVCRDs7R0FFRztBQUNILHdCQUFnQixtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEdBQUcsYUFBYSxDQVd2RjtBQUVEOztHQUVHO0FBQ0gsd0JBQWdCLHdCQUF3QixDQUN0QyxLQUFLLEVBQUUsT0FBTyxFQUNkLG1CQUFtQixFQUFFLFNBQVMsRUFDOUIsY0FBYyxDQUFDLEVBQUUsU0FBUyxFQUMxQixxQkFBcUIsR0FBRSxNQUFXLEdBQ2pDLGtCQUFrQixDQWdCcEI7QUFFRDs7OztHQUlHO0FBQ0gsd0JBQWdCLDJCQUEyQixDQUN6QyxLQUFLLEVBQUUsT0FBTyxFQUNkLFNBQVMsRUFBRSxTQUFTLEVBQ3BCLE1BQU0sRUFBRSxVQUFVLEVBQ2xCLHFCQUFxQixHQUFFLE1BQVcsR0FDakMscUJBQXFCLENBYXZCO0FBRUQ7OztHQUdHO0FBQ0gsd0JBQXNCLGdCQUFnQixDQUNwQyxHQUFHLEVBQUUsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUNuQixlQUFlLEVBQUUsZUFBZSxFQUNoQyxPQUFPLEVBQUUsTUFBTSxFQUNmLE9BQU8sRUFBRSxFQUFFLEdBQ1YsT0FBTyxDQUFDO0lBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQTtDQUFFLENBQUMsQ0FLeEMifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAoB,MAAM,mBAAmB,CAAC;AAG/G,OAAO,EAAe,eAAe,EAAE,KAAK,EAAE,EAAoC,MAAM,kBAAkB,CAAC;AAE3G,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAE7F;;GAEG;AACH,wBAAsB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAMrE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB7F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,IAAI,CAInE;AAED;;GAEG;AACH,wBAAuB,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,qBAAqB,CAAC,EAAE,CAAC,CAInF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,oBAAoB,EAAE,CAGpF;AAuBD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,aAAa,CAUvF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,mBAAmB,EAAE,SAAS,EAC9B,cAAc,CAAC,EAAE,SAAS,EAC1B,qBAAqB,GAAE,MAAW,GACjC,kBAAkB,CASpB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,UAAU,EAClB,qBAAqB,GAAE,MAAW,GACjC,qBAAqB,CAOvB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,EACnB,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,EAAE,GACV,OAAO,CAAC;IAAE,GAAG,EAAE,EAAE,EAAE,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAKxC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/test/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAoB,MAAM,mBAAmB,CAAC;AAO/G,OAAO,EAAe,eAAe,EAAE,KAAK,EAAE,EAAoC,MAAM,kBAAkB,CAAC;AAE3G,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAE7F;;GAEG;AACH,wBAAsB,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAMrE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB7F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,IAAI,CAInE;AAED;;GAEG;AACH,wBAAuB,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,qBAAqB,CAAC,EAAE,CAAC,CAInF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,oBAAoB,EAAE,CAGpF;AAuBD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,aAAa,CAWvF;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,mBAAmB,EAAE,SAAS,EAC9B,cAAc,CAAC,EAAE,SAAS,EAC1B,qBAAqB,GAAE,MAAW,GACjC,kBAAkB,CAgBpB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,UAAU,EAClB,qBAAqB,GAAE,MAAW,GACjC,qBAAqB,CAavB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,EACnB,eAAe,EAAE,eAAe,EAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,EAAE,GACV,OAAO,CAAC;IAAE,GAAG,EAAE,EAAE,EAAE,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAKxC"}
@@ -7,7 +7,7 @@ import { PublicDataWrite } from '@aztec/stdlib/avm';
7
7
  import { CommitteeAttestation, L2Block } from '@aztec/stdlib/block';
8
8
  import { BlockProposal, CheckpointAttestation, CheckpointProposal, ConsensusPayload } from '@aztec/stdlib/p2p';
9
9
  import { CheckpointHeader } from '@aztec/stdlib/rollup';
10
- import { makeAppendOnlyTreeSnapshot, mockTxForRollup } from '@aztec/stdlib/testing';
10
+ import { TEST_COORDINATION_SIGNATURE_CONTEXT, makeAppendOnlyTreeSnapshot, mockTxForRollup } from '@aztec/stdlib/testing';
11
11
  import { BlockHeader, makeProcessedTxFromPrivateOnlyTx } from '@aztec/stdlib/tx';
12
12
  // Re-export mock classes from their dedicated file
13
13
  export { MockCheckpointBuilder, MockCheckpointsBuilder } from './mock_checkpoint_builder.js';
@@ -64,14 +64,14 @@ export { MockCheckpointBuilder, MockCheckpointsBuilder } from './mock_checkpoint
64
64
  * Creates a block proposal from a block and signature
65
65
  */ export function createBlockProposal(block, signature) {
66
66
  const txHashes = block.body.txEffects.map((tx)=>tx.txHash);
67
- return new BlockProposal(block.header, block.indexWithinCheckpoint, Fr.ZERO, block.archive.root, txHashes, signature);
67
+ return new BlockProposal(block.header, block.indexWithinCheckpoint, Fr.ZERO, block.archive.root, txHashes, signature, TEST_COORDINATION_SIGNATURE_CONTEXT);
68
68
  }
69
69
  /**
70
70
  * Creates a checkpoint proposal from a block and signature
71
71
  */ export function createCheckpointProposal(block, checkpointSignature, blockSignature, feeAssetPriceModifier = 0n) {
72
72
  const txHashes = block.body.txEffects.map((tx)=>tx.txHash);
73
73
  const checkpointHeader = createCheckpointHeaderFromBlock(block);
74
- return new CheckpointProposal(checkpointHeader, block.archive.root, feeAssetPriceModifier, checkpointSignature, {
74
+ return new CheckpointProposal(checkpointHeader, block.archive.root, feeAssetPriceModifier, checkpointSignature, TEST_COORDINATION_SIGNATURE_CONTEXT, {
75
75
  blockHeader: block.header,
76
76
  indexWithinCheckpoint: block.indexWithinCheckpoint,
77
77
  txHashes,
@@ -84,10 +84,11 @@ export { MockCheckpointBuilder, MockCheckpointsBuilder } from './mock_checkpoint
84
84
  * In production, the sender is recovered from the signature.
85
85
  */ export function createCheckpointAttestation(block, signature, sender, feeAssetPriceModifier = 0n) {
86
86
  const checkpointHeader = createCheckpointHeaderFromBlock(block);
87
- const payload = new ConsensusPayload(checkpointHeader, block.archive.root, feeAssetPriceModifier);
87
+ const payload = new ConsensusPayload(checkpointHeader, block.archive.root, feeAssetPriceModifier, TEST_COORDINATION_SIGNATURE_CONTEXT);
88
88
  const attestation = new CheckpointAttestation(payload, signature, signature);
89
- // Set sender directly for testing (bypasses signature recovery)
90
- attestation.sender = sender;
89
+ // Bypass signature recovery for testing since we use random signatures
90
+ attestation.getSender = ()=>sender;
91
+ attestation.getProposer = ()=>sender;
91
92
  return attestation;
92
93
  }
93
94
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/sequencer-client",
3
- "version": "0.0.1-commit.0dc957cde",
3
+ "version": "0.0.1-commit.0ec55a70b",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -26,37 +26,37 @@
26
26
  "test:integration:run": "NODE_NO_WARNINGS=1 node --experimental-vm-modules $(yarn bin jest) --no-cache --config jest.integration.config.json"
27
27
  },
28
28
  "dependencies": {
29
- "@aztec/aztec.js": "0.0.1-commit.0dc957cde",
30
- "@aztec/bb-prover": "0.0.1-commit.0dc957cde",
31
- "@aztec/blob-client": "0.0.1-commit.0dc957cde",
32
- "@aztec/blob-lib": "0.0.1-commit.0dc957cde",
33
- "@aztec/constants": "0.0.1-commit.0dc957cde",
34
- "@aztec/epoch-cache": "0.0.1-commit.0dc957cde",
35
- "@aztec/ethereum": "0.0.1-commit.0dc957cde",
36
- "@aztec/foundation": "0.0.1-commit.0dc957cde",
37
- "@aztec/l1-artifacts": "0.0.1-commit.0dc957cde",
38
- "@aztec/node-keystore": "0.0.1-commit.0dc957cde",
39
- "@aztec/noir-acvm_js": "0.0.1-commit.0dc957cde",
40
- "@aztec/noir-contracts.js": "0.0.1-commit.0dc957cde",
41
- "@aztec/noir-protocol-circuits-types": "0.0.1-commit.0dc957cde",
42
- "@aztec/noir-types": "0.0.1-commit.0dc957cde",
43
- "@aztec/p2p": "0.0.1-commit.0dc957cde",
44
- "@aztec/protocol-contracts": "0.0.1-commit.0dc957cde",
45
- "@aztec/prover-client": "0.0.1-commit.0dc957cde",
46
- "@aztec/simulator": "0.0.1-commit.0dc957cde",
47
- "@aztec/slasher": "0.0.1-commit.0dc957cde",
48
- "@aztec/stdlib": "0.0.1-commit.0dc957cde",
49
- "@aztec/telemetry-client": "0.0.1-commit.0dc957cde",
50
- "@aztec/validator-client": "0.0.1-commit.0dc957cde",
51
- "@aztec/validator-ha-signer": "0.0.1-commit.0dc957cde",
52
- "@aztec/world-state": "0.0.1-commit.0dc957cde",
29
+ "@aztec/aztec.js": "0.0.1-commit.0ec55a70b",
30
+ "@aztec/bb-prover": "0.0.1-commit.0ec55a70b",
31
+ "@aztec/blob-client": "0.0.1-commit.0ec55a70b",
32
+ "@aztec/blob-lib": "0.0.1-commit.0ec55a70b",
33
+ "@aztec/constants": "0.0.1-commit.0ec55a70b",
34
+ "@aztec/epoch-cache": "0.0.1-commit.0ec55a70b",
35
+ "@aztec/ethereum": "0.0.1-commit.0ec55a70b",
36
+ "@aztec/foundation": "0.0.1-commit.0ec55a70b",
37
+ "@aztec/l1-artifacts": "0.0.1-commit.0ec55a70b",
38
+ "@aztec/node-keystore": "0.0.1-commit.0ec55a70b",
39
+ "@aztec/noir-acvm_js": "0.0.1-commit.0ec55a70b",
40
+ "@aztec/noir-contracts.js": "0.0.1-commit.0ec55a70b",
41
+ "@aztec/noir-protocol-circuits-types": "0.0.1-commit.0ec55a70b",
42
+ "@aztec/noir-types": "0.0.1-commit.0ec55a70b",
43
+ "@aztec/p2p": "0.0.1-commit.0ec55a70b",
44
+ "@aztec/protocol-contracts": "0.0.1-commit.0ec55a70b",
45
+ "@aztec/prover-client": "0.0.1-commit.0ec55a70b",
46
+ "@aztec/simulator": "0.0.1-commit.0ec55a70b",
47
+ "@aztec/slasher": "0.0.1-commit.0ec55a70b",
48
+ "@aztec/stdlib": "0.0.1-commit.0ec55a70b",
49
+ "@aztec/telemetry-client": "0.0.1-commit.0ec55a70b",
50
+ "@aztec/validator-client": "0.0.1-commit.0ec55a70b",
51
+ "@aztec/validator-ha-signer": "0.0.1-commit.0ec55a70b",
52
+ "@aztec/world-state": "0.0.1-commit.0ec55a70b",
53
53
  "lodash.chunk": "^4.2.0",
54
54
  "tslib": "^2.4.0",
55
55
  "viem": "npm:@aztec/viem@2.38.2"
56
56
  },
57
57
  "devDependencies": {
58
- "@aztec/archiver": "0.0.1-commit.0dc957cde",
59
- "@aztec/kv-store": "0.0.1-commit.0dc957cde",
58
+ "@aztec/archiver": "0.0.1-commit.0ec55a70b",
59
+ "@aztec/kv-store": "0.0.1-commit.0ec55a70b",
60
60
  "@electric-sql/pglite": "^0.3.14",
61
61
  "@jest/globals": "^30.0.0",
62
62
  "@types/jest": "^30.0.0",
package/src/config.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  booleanConfigHelper,
6
6
  getConfigFromMappings,
7
7
  numberConfigHelper,
8
+ optionalNumberConfigHelper,
8
9
  pickConfigMappings,
9
10
  } from '@aztec/foundation/config';
10
11
  import { EthAddress } from '@aztec/foundation/eth-address';
@@ -13,6 +14,7 @@ import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p/config';
13
14
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
14
15
  import {
15
16
  type ChainConfig,
17
+ DEFAULT_MAX_BLOCKS_PER_CHECKPOINT,
16
18
  type PipelineConfig,
17
19
  type SequencerConfig,
18
20
  chainConfigMappings,
@@ -58,6 +60,7 @@ export const DefaultSequencerConfig = {
58
60
  shuffleAttestationOrdering: false,
59
61
  skipPushProposedBlocksToArchiver: false,
60
62
  skipPublishingCheckpointsPercent: 0,
63
+ maxBlocksPerCheckpoint: DEFAULT_MAX_BLOCKS_PER_CHECKPOINT,
61
64
  } satisfies ResolvedSequencerConfig;
62
65
 
63
66
  /**
@@ -83,7 +86,7 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
83
86
  maxTxsPerCheckpoint: {
84
87
  env: 'SEQ_MAX_TX_PER_CHECKPOINT',
85
88
  description: 'The maximum number of txs across all blocks in a checkpoint.',
86
- parseEnv: (val: string) => parseInt(val, 10),
89
+ ...optionalNumberConfigHelper(),
87
90
  },
88
91
  minTxsPerBlock: {
89
92
  env: 'SEQ_MIN_TX_PER_BLOCK',
@@ -102,12 +105,12 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
102
105
  maxL2BlockGas: {
103
106
  env: 'SEQ_MAX_L2_BLOCK_GAS',
104
107
  description: 'The maximum L2 block gas.',
105
- parseEnv: (val: string) => parseInt(val, 10),
108
+ ...optionalNumberConfigHelper(),
106
109
  },
107
110
  maxDABlockGas: {
108
111
  env: 'SEQ_MAX_DA_BLOCK_GAS',
109
112
  description: 'The maximum DA block gas.',
110
- parseEnv: (val: string) => parseInt(val, 10),
113
+ ...optionalNumberConfigHelper(),
111
114
  },
112
115
  perBlockAllocationMultiplier: {
113
116
  env: 'SEQ_PER_BLOCK_ALLOCATION_MULTIPLIER',
@@ -153,7 +156,7 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
153
156
  l1PublishingTime: {
154
157
  env: 'SEQ_L1_PUBLISHING_TIME_ALLOWANCE_IN_SLOT',
155
158
  description: 'How much time (in seconds) we allow in the slot for publishing the L1 tx (defaults to 1 L1 slot).',
156
- parseEnv: (val: string) => parseInt(val, 10),
159
+ ...optionalNumberConfigHelper(),
157
160
  },
158
161
  fakeProcessingDelayPerTxMs: {
159
162
  description: 'Used for testing to introduce a fake delay after processing each tx',
@@ -228,6 +231,10 @@ export const sequencerConfigMappings: ConfigMappingsType<SequencerConfig> = {
228
231
  description: 'Percent probability (0 - 100) of sequencer skipping checkpoint publishing (testing only)',
229
232
  ...numberConfigHelper(DefaultSequencerConfig.skipPublishingCheckpointsPercent),
230
233
  },
234
+ skipBroadcastProposals: {
235
+ description: 'Skip broadcasting checkpoint and block proposals via gossipsub when proposer (for testing only)',
236
+ ...booleanConfigHelper(false),
237
+ },
231
238
  ...pickConfigMappings(p2pConfigMappings, ['txPublicSetupAllowListExtend']),
232
239
  };
233
240
 
@@ -709,7 +709,7 @@ export class SequencerPublisher {
709
709
 
710
710
  const args = [
711
711
  header.toViem(),
712
- CommitteeAttestationsAndSigners.empty().getPackedAttestations(),
712
+ CommitteeAttestationsAndSigners.packAttestations([]),
713
713
  [], // no signers
714
714
  Signature.empty().toViemSignature(),
715
715
  `0x${'0'.repeat(64)}`, // 32 empty bytes
@@ -850,9 +850,7 @@ export class SequencerPublisher {
850
850
  const logData = { ...checkpoint, reason };
851
851
  this.log.debug(`Building invalidate checkpoint ${checkpoint.checkpointNumber} request`, logData);
852
852
 
853
- const attestationsAndSigners = new CommitteeAttestationsAndSigners(
854
- validationResult.attestations,
855
- ).getPackedAttestations();
853
+ const attestationsAndSigners = CommitteeAttestationsAndSigners.packAttestations(validationResult.attestations);
856
854
 
857
855
  if (reason === 'invalid-attestation') {
858
856
  return this.rollupContract.buildInvalidateBadAttestationRequest(
@@ -48,7 +48,7 @@ In a typical configuration without pipelining, a 72-second slot contains:
48
48
  - 1 last validator re-execution sub-slot (8 seconds)
49
49
  - 1 attestation and publishing period (17 seconds)
50
50
 
51
- With proposer pipelining enabled, the last validator re-execution sub-slot is still reserved, but the checkpoint finalization and L1 publishing budget is no longer subtracted when deciding how many block-building sub-slots fit in the slot.
51
+ With proposer pipelining enabled, the last validator re-execution sub-slot is still reserved, but L1 publishing is deferred to the target slot and removed from the current slot budget. Attestation collection is completed inside the build slot itself, so the proposer can send the L1 transaction immediately at the target-slot boundary.
52
52
 
53
53
  ### The Fixed Sub-Slot Model
54
54
 
@@ -89,7 +89,8 @@ timeReservedAtEnd (normal mode) = blockDuration (last sub-slot for
89
89
  + checkpointFinalizationTime
90
90
 
91
91
  timeReservedAtEnd (pipelining) = assembleTime
92
- + propagationTime (proposal must reach validators before the slot flips)
92
+ + 2 * propagationTime (proposal out + attestations back)
93
+ + blockDuration (last-block re-execution)
93
94
 
94
95
  timeAvailableForBlocks = slotDuration - initializationOffset - timeReservedAtEnd
95
96
 
@@ -110,47 +111,45 @@ This means:
110
111
 
111
112
  **The same slot with proposer pipelining enabled:**
112
113
  ```
113
- timeReservedAtEnd = 1s + 2s = 3s
114
- timeAvailableForBlocks = 72s - 2s - 3s = 67s
115
- numberOfBlocks = floor(67s / 8s) = 8 blocks
114
+ timeReservedAtEnd = 1s + 2*2s + 8s = 13s
115
+ timeAvailableForBlocks = 72s - 2s - 13s = 57s
116
+ numberOfBlocks = floor(57s / 8s) = 7 blocks
116
117
  ```
117
118
 
118
- The extra two block opportunities come from not charging the current slot for checkpoint finalization and L1 publishing.
119
+ The extra two block opportunities come from not charging the current slot for L1 publishing. The proposal broadcast, attestation round-trip, and last-block re-execution are now all reserved inside the build slot so that attestations are in hand at the slot boundary.
119
120
 
120
121
  ### Pipelining Mode
121
122
 
122
- When proposer pipelining is enabled, the sequencer uses the current wall-clock slot to build the checkpoint for the **next target slot**.
123
+ When proposer pipelining is enabled, the sequencer uses the current wall-clock slot to build the checkpoint for the **next target slot**, and finishes collecting attestations before the slot boundary so that L1 publishing can happen immediately at the target-slot boundary.
123
124
 
124
125
  It helps to think in terms of two different slots:
125
126
 
126
- - **Wall-clock slot N-1**: The sequencer initializes checkpoint `N`, builds its blocks, and validators re-execute the last block
127
- - **Target slot N**: Checkpoint `N` is proposed, attestations are gathered, and the L1 transaction is submitted
127
+ - **Wall-clock slot N-1**: The sequencer initializes checkpoint `N`, builds its blocks, validators re-execute the last block, and attestations are gathered
128
+ - **Target slot N**: The checkpoint is submitted to L1
128
129
 
129
130
  So the work is split like this:
130
131
 
131
- - **During slot N-1**: Initialization, block building, and last-block re-execution
132
- - **Near the end of slot N-1**: The checkpoint proposal is broadcast so validators can start the last re-execution as slot `N` begins.
133
- - **During slot N**: Validators finish re-executing, send attestations, the proposer collects them, and the checkpoint is submitted to L1 before slot `N` reaches its publish cutoff
132
+ - **During slot N-1**: Initialization, block building, last-block re-execution, proposal broadcast, and attestation collection
133
+ - **At the start of slot N**: The L1 transaction is submitted attestations are already in hand
134
134
 
135
- In other words, pipelining does not mean "do everything for slot N earlier". It specifically moves **block production and block re-execution** earlier, while **checkpoint proposal, attestation gathering, and L1 submission** remain aligned with slot `N`.
135
+ In other words, pipelining moves **block production, block re-execution, proposal broadcast, and attestation collection** into the build slot, while **L1 submission** happens aligned with slot `N`. With default values (72s slot, 6s block, 2s p2p, 1s assemble), the last build-slot block finishes at `T = slotDuration - timeReservedAtEnd = 61s`, the proposer broadcasts the checkpoint at `T=62s` after `assembleTime=1s`, and attestations are in hand by `T=72s` (the slot boundary).
136
136
 
137
137
  **Example: building checkpoint 12 while wall-clock time is in slot 11**
138
138
  ```
139
139
  Slot 11 (wall clock):
140
140
  - Build blocks that will make up checkpoint 12
141
- - Validators re-execute the last block of checkpoint 12
142
141
  - Broadcast checkpoint 12 proposal
143
- - Collect checkpoint 12 attestations
142
+ - Validators re-execute the last block of checkpoint 12
143
+ - Collect checkpoint 12 attestations (all complete before slot 11 ends)
144
144
 
145
145
  Slot 12 (target/submission slot):
146
- - Collect attestations for checkpoint 12 until slot 12 reaches its L1 publish cutoff
147
- - Submit checkpoint 12 to L1
146
+ - Submit checkpoint 12 to L1 at the slot boundary
148
147
  ```
149
148
 
150
- For timetable purposes, this changes two things:
149
+ For timetable purposes:
151
150
 
152
- - `maxNumberOfBlocks` is computed by reserving only the final validator re-execution sub-slot
153
- - `initializeDeadline` no longer subtracts checkpoint finalization time; it only requires enough time for initialization, execution, and validator re-execution
151
+ - `maxNumberOfBlocks` is computed by reserving assembly + round-trip p2p + last-block re-execution at the end of the slot
152
+ - `initializeDeadline` no longer subtracts checkpoint finalization time; it only requires enough time for initialization and two execution windows
154
153
 
155
154
  In code, that means:
156
155
 
@@ -162,7 +161,7 @@ initializeDeadline (pipelining) =
162
161
  slotDuration - initializationOffset - 2 * minExecutionTime
163
162
  ```
164
163
 
165
- The fixed sub-slot deadlines themselves do not change. Pipelining only changes how much of the slot is considered available for block building.
164
+ The fixed sub-slot deadlines themselves do not change. Pipelining only changes how much of the slot is considered available for block building, and when the broadcast and attestation windows close.
166
165
 
167
166
  ## The Sequencer's Work
168
167