@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.
- package/dest/config.d.ts +2 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +12 -7
- package/dest/publisher/sequencer-publisher.d.ts +1 -1
- package/dest/publisher/sequencer-publisher.d.ts.map +1 -1
- package/dest/publisher/sequencer-publisher.js +2 -2
- package/dest/sequencer/checkpoint_proposal_job.d.ts +8 -2
- package/dest/sequencer/checkpoint_proposal_job.d.ts.map +1 -1
- package/dest/sequencer/checkpoint_proposal_job.js +189 -19
- package/dest/sequencer/metrics.d.ts +3 -1
- package/dest/sequencer/metrics.d.ts.map +1 -1
- package/dest/sequencer/metrics.js +7 -0
- package/dest/sequencer/sequencer.d.ts +12 -4
- package/dest/sequencer/sequencer.d.ts.map +1 -1
- package/dest/sequencer/sequencer.js +33 -8
- package/dest/test/utils.d.ts +1 -1
- package/dest/test/utils.d.ts.map +1 -1
- package/dest/test/utils.js +7 -6
- package/package.json +27 -27
- package/src/config.ts +11 -4
- package/src/publisher/sequencer-publisher.ts +2 -4
- package/src/sequencer/README.md +20 -21
- package/src/sequencer/checkpoint_proposal_job.ts +211 -17
- package/src/sequencer/metrics.ts +9 -0
- package/src/sequencer/sequencer.ts +37 -9
- package/src/test/utils.ts +28 -10
|
@@ -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(
|
|
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(
|
|
776
|
-
this.
|
|
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
|
-
|
|
794
|
+
stateSlotNumber: oldStateSlotNumber,
|
|
795
|
+
secondsIntoSlot,
|
|
796
|
+
...stateChanged && {
|
|
797
|
+
stateDurationMs: Math.ceil(stateDurationMs)
|
|
798
|
+
}
|
|
779
799
|
});
|
|
780
800
|
this.emit('state-changed', {
|
|
781
|
-
oldState
|
|
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.
|
|
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,
|
package/dest/test/utils.d.ts
CHANGED
|
@@ -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,
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90ZXN0L3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUdBLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUM1RSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzVELE9BQU8sS0FBSyxFQUFFLEdBQUcsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV0QyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDcEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxxQkFBcUIsRUFBRSxrQkFBa0IsRUFBb0IsTUFBTSxtQkFBbUIsQ0FBQztBQU8vRyxPQUFPLEVBQWUsZUFBZSxFQUFFLEtBQUssRUFBRSxFQUFvQyxNQUFNLGtCQUFrQixDQUFDO0FBRTNHLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBR3BELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBRTdGOztHQUVHO0FBQ0gsd0JBQXNCLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FNckU7QUFFRDs7R0FFRztBQUNILHdCQUFzQixTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxFQUFFLGVBQWUsRUFBRSxlQUFlLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQWdCN0Y7QUFFRDs7R0FFRztBQUNILHdCQUFnQixjQUFjLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUluRTtBQUVEOztHQUVHO0FBQ0gsd0JBQXVCLGNBQWMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcscUJBQXFCLENBQUMsRUFBRSxDQUFDLENBSW5GO0FBRUQ7O0dBRUc7QUFDSCx3QkFBZ0Isb0JBQW9CLENBQUMsTUFBTSxFQUFFLGVBQWUsR0FBRyxvQkFBb0IsRUFBRSxDQUdwRjtBQXVCRDs7R0FFRztBQUNILHdCQUFnQixtQkFBbUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEdBQUcsYUFBYSxDQVd2RjtBQUVEOztHQUVHO0FBQ0gsd0JBQWdCLHdCQUF3QixDQUN0QyxLQUFLLEVBQUUsT0FBTyxFQUNkLG1CQUFtQixFQUFFLFNBQVMsRUFDOUIsY0FBYyxDQUFDLEVBQUUsU0FBUyxFQUMxQixxQkFBcUIsR0FBRSxNQUFXLEdBQ2pDLGtCQUFrQixDQWdCcEI7QUFFRDs7OztHQUlHO0FBQ0gsd0JBQWdCLDJCQUEyQixDQUN6QyxLQUFLLEVBQUUsT0FBTyxFQUNkLFNBQVMsRUFBRSxTQUFTLEVBQ3BCLE1BQU0sRUFBRSxVQUFVLEVBQ2xCLHFCQUFxQixHQUFFLE1BQVcsR0FDakMscUJBQXFCLENBYXZCO0FBRUQ7OztHQUdHO0FBQ0gsd0JBQXNCLGdCQUFnQixDQUNwQyxHQUFHLEVBQUUsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUNuQixlQUFlLEVBQUUsZUFBZSxFQUNoQyxPQUFPLEVBQUUsTUFBTSxFQUNmLE9BQU8sRUFBRSxFQUFFLEdBQ1YsT0FBTyxDQUFDO0lBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUFDO0lBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQTtDQUFFLENBQUMsQ0FLeEMifQ==
|
package/dest/test/utils.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dest/test/utils.js
CHANGED
|
@@ -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
|
-
//
|
|
90
|
-
attestation.
|
|
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.
|
|
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.
|
|
30
|
-
"@aztec/bb-prover": "0.0.1-commit.
|
|
31
|
-
"@aztec/blob-client": "0.0.1-commit.
|
|
32
|
-
"@aztec/blob-lib": "0.0.1-commit.
|
|
33
|
-
"@aztec/constants": "0.0.1-commit.
|
|
34
|
-
"@aztec/epoch-cache": "0.0.1-commit.
|
|
35
|
-
"@aztec/ethereum": "0.0.1-commit.
|
|
36
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
37
|
-
"@aztec/l1-artifacts": "0.0.1-commit.
|
|
38
|
-
"@aztec/node-keystore": "0.0.1-commit.
|
|
39
|
-
"@aztec/noir-acvm_js": "0.0.1-commit.
|
|
40
|
-
"@aztec/noir-contracts.js": "0.0.1-commit.
|
|
41
|
-
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.
|
|
42
|
-
"@aztec/noir-types": "0.0.1-commit.
|
|
43
|
-
"@aztec/p2p": "0.0.1-commit.
|
|
44
|
-
"@aztec/protocol-contracts": "0.0.1-commit.
|
|
45
|
-
"@aztec/prover-client": "0.0.1-commit.
|
|
46
|
-
"@aztec/simulator": "0.0.1-commit.
|
|
47
|
-
"@aztec/slasher": "0.0.1-commit.
|
|
48
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
49
|
-
"@aztec/telemetry-client": "0.0.1-commit.
|
|
50
|
-
"@aztec/validator-client": "0.0.1-commit.
|
|
51
|
-
"@aztec/validator-ha-signer": "0.0.1-commit.
|
|
52
|
-
"@aztec/world-state": "0.0.1-commit.
|
|
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.
|
|
59
|
-
"@aztec/kv-store": "0.0.1-commit.
|
|
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
|
-
|
|
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
|
-
|
|
108
|
+
...optionalNumberConfigHelper(),
|
|
106
109
|
},
|
|
107
110
|
maxDABlockGas: {
|
|
108
111
|
env: 'SEQ_MAX_DA_BLOCK_GAS',
|
|
109
112
|
description: 'The maximum DA block gas.',
|
|
110
|
-
|
|
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
|
-
|
|
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.
|
|
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 =
|
|
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(
|
package/src/sequencer/README.md
CHANGED
|
@@ -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
|
|
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
|
|
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 =
|
|
114
|
-
timeAvailableForBlocks = 72s - 2s -
|
|
115
|
-
numberOfBlocks = floor(
|
|
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
|
|
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,
|
|
127
|
-
- **Target slot N**:
|
|
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,
|
|
132
|
-
- **
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
147
|
-
- Submit checkpoint 12 to L1
|
|
146
|
+
- Submit checkpoint 12 to L1 at the slot boundary
|
|
148
147
|
```
|
|
149
148
|
|
|
150
|
-
For timetable purposes
|
|
149
|
+
For timetable purposes:
|
|
151
150
|
|
|
152
|
-
- `maxNumberOfBlocks` is computed by reserving
|
|
153
|
-
- `initializeDeadline` no longer subtracts checkpoint finalization time; it only requires enough time for initialization
|
|
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
|
|