Files
consensus/engine
zeekayandHanzo Dev 03fdcfe71e engine/chain: canonical-equivalent siblings are aliases, not forks
The block-1082879 mainnet freeze: 600+ outer proposervm wrappers of ONE
inner block piled up at a height and never converged. Two determinism
holes in the fork-choice let different validators pick different
representatives, so prevotes never aligned and no POL/cert ever formed.

1. convergedWinnerAtHeightLocked chose the winner among EQUAL-canonical
   siblings by Go map-iteration order (`canon.Compare(winnerCanon) < 0`
   never updates on a tie) — nondeterministic per node. Add the outer-id
   tie-break so equal-canonical aliases resolve to the SAME winner
   everywhere.

2. It grouped children by the OUTER parentID. A forked parent (same inner
   block, different outer wrappers) split its children across groups, and
   the view-change pass keyed `parents[height]=parentID` last-writer-wins
   in random map order — so nodes computed winners over different sibling
   subsets. Group by the parent CANONICAL identity instead; enumerate
   distinct (height, parent-canonical) groups with a deterministic
   lowest-outer-id representative.

parentIsProvenLoserLocked gets the same canonical-grandparent grouping so
every fork-choice / winner / parent path collapses aliases to one
deterministic representative before making progress decisions. Outer IDs
stay transport aliases only.

New canonical_representative_test.go pins it: equal-canonical winner
determinism over 600 wrappers x 400 randomized maps, forked-parent
children converging as one group, genuine-fork non-merge, accepted-tip
children matched. All fail on the pre-fix code (proven by stash), pass
after. Safety unchanged: an equal-canonical alias (sc==pc) is never a
loser; only strictly-lower canonicals win; no vote manufactured.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-03 21:07:04 -07:00
..
2025-12-19 08:49:11 -08:00