Files
consensus/engine
zeekay a93027c81e feat(chain): sibling-tolerant finality — cert-driven reorg replaces the per-height admission gate (v1.30.0)
THE BUG (fresh-net deadlock). The engine forked avalanchego's Snowman model by adding
a hard per-height finality gate (markFinalizedLocked invariant (c): a finalized block's
parent MUST equal the current finalized tip) AND never reorged. When a cert finalized
one child of a parent while production/preference had explored a SIBLING and built on
it, the winner finalized but the losing sibling subtree was NEVER pruned and preference
never reorged — so production ran away on the losing branch and every cert for it hit
"parent != finalized tip" forever (devnet: finalized stuck at height 1, blocks past 10,
every cert REFUSED). A refusal cannot reorg.

THE FIX (avalanchego-shaped). Siblings are TRACKED (admission already tolerated them);
when a cert SELECTS one, FinalizeBranch walks the certified branch from the finalized
tip, finalizes the whole contiguous path, and PRUNES the losing-sibling subtrees —
exactly topological.go's acceptPreferredChild (accept the path) + rejectTransitively
(prune the losers). The single-non-branching-chain property is now the OUTPUT of the
reorg, not a precondition refused at admission. The reorg IS the recovery.

- consensus.go: markFinalizedLocked → FinalizeBranch (branch walk + reorg/prune plan).
  KEPT as α-of-K-cert safety: one-finalized-block-per-height (ErrHeightAlreadyFinalized,
  equivocation evidence) and the conflicting/losing-branch refusal (renamed
  ErrParentNotFinalizedTip → ErrConflictsWithFinalizedBranch; now a branch check, not a
  blanket non-tip-parent refusal). Added ErrAncestorNotTracked (behind-node DEFER).
- Decomplected the count path: ProcessVote/Poll set block.accepted as a pure LIVENESS
  trigger; the per-height ledger is advanced ONLY by FinalizeBranch (the cert path).
- engine.go: acceptWithCertCore is the SOLE finalizer — calls FinalizeBranch and applies
  the plan (VM.Accept the path ascending, VM.Reject the pruned losers, SetPreference to
  the certified tip). New applyBranchFinalization helper.
- Removed dead one-off entrypoints AcceptViaCert / ForceAccept / consensus.AcceptBootstrapBlock;
  HandleIncomingCert + the K==1 path + Runtime.AcceptBootstrapBlock all route through the
  one finalize. Simplified ForcePreference (the gate-(c) desync defense is now moot).

Regression (RED→GREEN): TestSiblingReorg_CertPrunesLoserBranchAndContinues — two children
at one height from a finalized parent, cert one, winner descendants accepted, loser subtree
rejected, no permanent refusal, chain continues. Plus FinalizeBranch unit tests (multi-step
finalize, conflicting-branch refusal, missing-ancestor defer) and the decomplected count
path. Full engine/chain suite green incl -race; CGO_ENABLED=0.
2026-06-28 13:50:03 -07:00
..
2025-12-19 08:49:11 -08:00