Repository navigation
feat(qbft_manager): shorten proposer QBFT round timeout to 1.5s (SIP-102) #1324
Description
Goal
Shorten the proposer QBFT quick-round timeout from 2s to 1.5s (SIP-102), and add a --legacy-proposer-round-timeout flag that restores 2s, matching go-ssv #3044. Target the epbs RC so both clients run 1.5s on Sepolia from its Gloas fork (epoch 353024, 2026-10-06 13:53 UTC).
Context and motivation
Gloas moves the attestation deadline from 4s to 3s into the slot. A proposer QBFT instance starts about 1.1s to 1.5s into the slot (RANDAO pre-consensus, proposer delay, block fetch). With a 2s round, a round change starts round 2 after the deadline, so a round change that is usually recoverable today usually misses the slot. The SIP projects network-wide missed proposals at about 42 a month with 2s and about 26 a month with 1.5s.
On epbs at 9f9b183:
anchor/qbft_manager/src/timeout.rs:8setsQUICK_TIMEOUTto 2s for both timer modes.single_round_timeout(timeout.rs:50) servesTimeoutMode::Relative.TimeoutMode::Relativeis documented as block-proposal timing (anchor/qbft_manager/src/lib.rs:62), and its only production constructor is the proposer path indecide_abstract_block(anchor/validator_store/src/lib.rs:971). Every other duty usesSlotTime, which this change leaves alone.- The relative timer starts when the instance starts and restarts on a local timeout or on a network round advance (
anchor/qbft_manager/src/instance.rs). This already matches SIP-102's rule that each round is timed from when that round starts. - The proposer round cap is 2 (
anchor/common/ssv_types/src/msgid.rs:82). At round-2 expiry,end_roundcompletes the instance as timed out (anchor/common/qbft/src/lib.rs:1233). go-ssv #3041 does the same.
go-ssv merged #3044 into epbs-gloas on 2026-09-28. It is not fork-gated and adds LegacyProposerRoundTimeout (default false) as the rollback path. go-ssv calls it a committee-wide parameter: a rollback only takes effect once at most f operators of a committee still run 1.5s. In committees where Anchor runs more than f operators, go-ssv's flag cannot roll the committee back, so Anchor needs the same switch.
Suggested approach
- Give
TimeoutMode::Relativethe per-round duration, and use it insingle_round_timeoutfor quick rounds. Export 1.5s and 2s constants fromqbft_manager. - Add a
--legacy-proposer-round-timeoutbool CLI flag whose help text carries go-ssv's committee-wide warning. Resolve it inclientconfig, log at info when it is set, and pass the resulting duration throughAnchorValidatorStore::newto the proposerTimeoutMode::Relative. - No fork gate, matching go-ssv.
Acceptance criteria
- A proposer QBFT instance runs 1.5s rounds by default: round 1 from instance start, round 2 from round-2 entry, then gives up at the existing cap of 2.
- With
--legacy-proposer-round-timeout, proposer rounds are 2s, and startup logs that the legacy timeout is active. SlotTimeduties (committee, aggregator, sync committee, aggregator committee) keep their current timing.- No message validation change, no round-cap change.
- Regenerated CLI reference (
make cli-reference-update).
Tests
qbft_managerpaused-time timer tests:Relativecompletes a two-round instance in 3s with the SIP-102 value and 4s with the legacy value. ExistingRelativeexpectations are updated.validator_store: the proposer path throughsign_blockhands QBFT the configured timeout, both default and legacy.client:from_cliresolves 1.5s by default and 2s with the flag.
Notes
- No message-validator change. A role-aware round estimate in
consensus_message.rswould change nothing for the proposer. The allowed range is round 1 up to estimate +MAX_ALLOWED_ROUNDS_FUTURE(3), and the estimate is at least 1, so the upper limit is at least 4, which is above the cap of 2 (consensus_message.rs:313,:370). - No fork gate. go-ssv applies 1.5s unconditionally, so gating only Anchor would create committees running mixed timers before Gloas.
- Residual risks accepted:
- A round 1 that would have decided between 1.5s and 2.0s is now cut off. go-ssv's slowest observed mainnet round 1 was 1148ms. Anchor's round-1 durations under Gloas have not been measured yet, and Sepolia is where to measure them.
- During a mixed-version rollout, a single 1.5s operator with one other operator offline can lose a round-1 quorum that 2s timers would reach. The SIP's "never worse than today" claim does not hold in that case.
- Open SIP wording point: SIP-102 says an instance stays in round 2 until it decides or the duty ends. Both clients give up at round-2 expiry instead.
Issues are directionally correct, not prescriptive; verify symbols at PR time.
Activity
shane-moore commentedon Sep 29, 2026
Closed by #1325, merged to
epbs.