mirror of
https://github.com/luxfi/consensus.git
synced 2026-08-07 10:44:08 +00:00
Mainnet C-Chain froze at 1082879 AFTER the canonical=inner roll (v1.34.14): pre-fix durable view-change locks were stored by OUTER proposervm wrapper id, and viewForLocked recovers them VERBATIM (never re-canonicalized). At 1082880 the fleet split 3/2 across two wrappers (outer-A on 3 nodes, outer-B on 2) of the SAME inner block I; under the Tendermint lock rule each node prevotes its stale outer alias, the prevotes split below alpha=4, no POL(I) forms, no cert, frozen. Transport is HEALTHY — a durable 3/2 split-lock can only form via working emit/gossip/receive/count. This is a persisted-state MIGRATION bug, not an algorithm or transport defect; the v1.34.14 canonical fix is correct and kept. Fix (owner rule: canonicalize-first). A boot-time, operator-gated, idempotent migration rewrites each persisted lock ABOVE the decided floor from its stale outer alias to the block's inner canonical (both wrappers -> the same inner I, so all nodes re-lock on I and finalize via precommit-of-lock, no POL even needed); a lock whose block is unresolvable is pruned (node boots unlocked, re-converges); a height already holding an alpha-of-K cert, or two wrappers resolving to DIFFERENT inners, STOPs the pass for manual recovery. Nothing at/below the floor is touched; the floor never lowers. 8-condition safety gate enforced in the pure planner. - lock_migration.go: pure planLockMigration + Runtime InspectLocks (read-only audit) / MigrateStaleLocks (apply); VM+tracked resolver. - reconcile.go: extract writeReconciledStateLocked (the shared atomic vote-guard write+swap the phantom-floor reconcile also uses — DRY). - integration.go: STUCK log now prints lock/prevoteTarget columns (lockIsStaleAlias) — the live self-diagnosis; + received-prevote trace. - cmd/voteguard: standalone CGO-free offline vote-guard inspector — the cross-pod split-lock audit gate operators run before any write. Tests (real fail->pass): stale-lock canonicalize + prune fallback + sibling recovery; never-touch <=floor; cert-exists STOP; divergent-inners STOP; idempotence; round_view stale-lock prevote suppression; n=5 alpha=4 multinode split-lock CONTROL frozen -> migration converges + finalizes + single-head (no double-finalize). Full engine/chain suite green (221s), race clean. Co-authored-by: Hanzo Dev <dev@hanzo.ai>