Files
consensus/engine
zeekayandHanzo Dev e606107190 fix(chain): count transport-authenticated Nova votes — α was unreachable
A Chits message has no signature field. On a K>1 chain every inbound peer
preference therefore died at the engine's signature gate, so α could never be
reached NO MATTER HOW MANY HONEST PEERS AGREED. Live evidence, per peer per
poll, forever:

  warn vote is UNSIGNED and cannot be counted — engine will drop it before the tally

testnet held at 16820 and devnet at 7323 in exactly that state: blocks built,
verified, preferred by everyone, tally zero.

The gate was correct to refuse what it was given. Lux's Vote carries NodeID as a
struct FIELD that any peer can set to any value, so counting it would make
finality forgeable by anyone able to send 32 bytes — the swarm's
TestSafety_UnsignedVoteIsNeverTallied is right about that and still passes.

What was missing is the thing that makes avalanchego's equivalent safe: it takes
the voter as `Chits(nodeID, requestID, …)`, a PARAMETER the router fills from the
authenticated connection. So origin is a parameter here too.

  ReceiveAuthenticatedVote(origin ids.NodeID, blockID ids.ID, accept bool)

- `transportAuthenticated` is UNEXPORTED, so no decoded value can carry it and no
  caller outside the package can forge it.
- NOVA (liveness) only. It never reaches recordCertVoteLocked, so it can never
  enter a QuorumCert: a cert travels to nodes that did not authenticate this
  connection, and for them only a signature means anything. Quasar is unchanged.
- Per-validator dedup from v1.36.17 applies, so an authenticated peer that
  answers a poll seven times still moves the tally once.

Each half is sabotage-controlled: dropping the flag fails the liveness test,
exempting all unsigned votes fails the payload-origin test.

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