v1.3.8 — Strict round-quorum (rolling-restart safety)
v1.3.8 — Strict round-quorum (rolling-restart safety)
Eliminates the rolling-restart fork cascade documented in the
2026-04-09 postmortem under "follow-up: rolling restart safety". After
v1.3.7 deployed via auto-update, the chain repeatedly fragmented into
2-validator pairs every time a node restarted. This release fixes the
underlying cause.
Root cause
narwhal.advanceRound() had three "emergency recovery" code paths that
let a validator advance to the next consensus round with 0 or 1
parent certs after a wall-clock timeout:
// Bootstrap (rounds 2-10):
if stuckDuration > 15*time.Second && prevRoundCerts == 0 {
minCertsForRecovery = 0 // <-- dangerous
}
// Round 11+:
if stuckDuration > 60*time.Second && prevRoundCerts >= 1 {
minCertsForRecovery = 1 // <-- dangerous
}
if stuckDuration > 120*time.Second && prevRoundCerts == 0 {
minCertsForRecovery = 0 // <-- very dangerous
}When a validator restarted (auto-update, manual restart, crash) and
hit the bootstrap delay alone — even briefly — these paths would let
it advance through rounds with empty parent sets, producing proposals
that the rest of the network could not link to. From the network's
view, the restarted validator looked like a divergent fork.
The fix
narwhal.go advanceRound(): removed all three emergency-recovery
paths. The new rule is one line:
minCertsForRecovery := f + 1 // 2 of 4 for n=4For n=4 / f=1 that's 2 certs (the BFT minimum for "real progress").
There is no fallback. If quorum cannot form, the validator stalls —
which is the correct BFT behaviour. Liveness without quorum is
impossible by definition; producing rounds in isolation isn't liveness,
it's silent forking.
The bootstrap peer-wait in runRounds() is also tightened: max wait
60s → 120s, with a 500ms poll interval, so a validator coming up after
its peers gets more time to discover them before consensus starts.
Trade-off
Liveness is now strictly bounded by quorum. If 2 of 4 validators are
down at the same time, the chain stalls until at least one comes back
(needs 2/4 active validators for n=4 quorum=3 since the local node
counts as one). This is the correct BFT behaviour.
The previous "advance with 0 certs" path traded safety for liveness in
the wrong direction — it produced a chain that appeared to make
progress but was actually four parallel single-validator chains. This
release restores the safety guarantee.
Upgrade notes
Drop-in upgrade. No chain data wipe required. Auto-updater pulls
this within 5 minutes.
Important: after deploying, do a coordinated restart so that all 4
validators come up with fresh DAG state at roughly the same time. The
strict-quorum rule means a single validator can't bootstrap alone; if
3 of 4 validators come up before the 4th, they'll start producing
together, and the 4th will join cleanly when it's ready.
Verification on testnet
Will be verified on the public 4-validator Hyperspace A1 testnet
immediately after publication. See the post-deploy report in the
release thread.