Files
consensus/engine
zeekayandHanzo Dev ea148281df fix(chain): α must mean α DISTINCT validators — ProcessVote takes the voter
ProcessVote(ctx, blockID, accept) did not take the voter, so the α predicate
could not tell one validator answering four times from four validators
answering once. block.acceptVotes was a bare counter incremented per arrival.
With K=5/α=4 one validator replaying its own valid signed vote drove the tally
to 4 and the block was accepted — measured, not theorised:

  before: one voter, four arrivals -> {voteCount:1 acceptVotes:4 accepted:true}
  after:  one voter, four arrivals -> {voteCount:1 acceptVotes:1 accepted:false}

No malice needed: polls are re-solicited and peers do answer twice.

- voter is now a REQUIRED parameter of ProcessVote (origin as a parameter, the
  same shape the vote-signature gate needs). The 4 production call sites pass
  vote.NodeID or t.nodeID (self-vote).
- acceptVoters/rejectVoters are SETS and acceptVotes()/rejectVotes() derive from
  them, so a count can never drift from the identities it summarises.
- driver.RecordVote is gated on the α predicate. β counts consecutive polls that
  EACH reached α; advancing it per vote collapses βα agreements to β. Latent
  today (the Nova cert road decides first) — hardening, not a behaviour change.
- PendingBlock.VoteCount/RejectCount deduped per NodeID at the engine tally.

Tests drive the real handleVote path with real signatures, and each fix is
sabotage-controlled (reverting it fails the test).

TestRED_INT_DoubleCount_SelfLowStake explicitly relied on the double-count to
exercise the stake road ("self's auto-vote + node1's replays push acceptVotes
well past α=3"). Replays can no longer inflate the count at all, which is the
stronger property, so it now asserts that directly.

MEASURED AND NOT FIXED HERE: with K=5/α=4/β=2, VM.Accept fires at THREE distinct
signed accepts — the Nova cert quorum ⌊n/2⌋+1=3 decides below α. That is the
known nova-majority-cert-safety-hole (intersection 2α−n = 1, not > f=1),
reproduced mechanically for the first time. Owner-gated, fix order C→A→B.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-31 20:56:06 -07:00
..
2025-12-19 08:49:11 -08:00