mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
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]>