Skip to content

v1.3.6 — Remove catch-up wave skipping (determinism fix pt.4)

Choose a tag to compare

@twobitapps twobitapps released this 09 Apr 21:41
· 28 commits to main since this release

Remove catch-up wave skipping (determinism fix pt.4)

The final piece of the cross-validator determinism pipeline: the
isCatchingUp code paths in bullshark.tryCommitLocked() that let each
validator unilaterally skip waves once its local DAG advanced 8+ rounds
past the leader round.

Because the DAG advances asynchronously across validators, different
nodes entered catch-up mode at different rounds and skipped different
waves, producing divergent committed sequences — exactly the same class
of fork the v1.3.1–v1.3.5 fixes were addressing, just via a path I
missed in earlier iterations.

Fixed paths

bullshark.go — three former isCatchingUp branches all removed:

  1. leaderCert == nil + catching up → unconditional skip
    → now falls through to checkLeaderTimeoutLocked (DAG-based view
    change, identical across validators).

  2. support >= QuorumSize + catching up → commit bs.committedRound
    WITHOUT emitting a CommitDecision, effectively dropping the
    corresponding block on catching-up validators
    → now emits the same commit decision whether catching up or not.

  3. support < QuorumSize + catching up → unconditional skip
    → now falls through to checkInsufficientSupportTimeoutLocked
    (DAG-based, identical across validators).

Testnet verification

Coordinated restart on the 4-validator Digital Ocean testnet. Chain
expected to remain in full consensus indefinitely across all validators.

Upgrade notes

Chain data MUST be wiped (consensus semantics change — existing chains
may have committed waves under the old catch-up logic that don't replay
cleanly under the new one).