mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
THE BUG (CFT, not BFT): a proposer self-finalized its own block on its lone self-vote (ForceAccept) and a peer's REJECT was counted as ACCEPT for the proposer's own block (effectiveAccept = ... || IsOwnProposal). Followers fast-followed unverified gossip and courtesy-voted only back to the proposer (broken vote topology), so they could never reach threshold themselves. An equivocating proposer could finalize two valid roots at one height -> fork. THE FIX: - QuorumCert (engine/chain/quorum_cert.go): the alpha-of-K finality witness. Assembles from alpha distinct correctly-signed ACCEPT votes over the canonical position; Verify enforces threshold + strictly-increasing-distinct voters + per-vote signature via a pluggable VoteVerifier. Wire codec for gossip (quorum_cert_codec.go). Quasar bridge (quorum_cert_quasar.go): upgrades to protocol/quasar.WeightedQuorumCert with real ML-DSA records + weighted Merkle inclusion when the node supplies the PQ validator set; fails closed otherwise. PROVEN: quasar's own Verify accepts the bridged cert. - ForceAccept demoted to single-validator (K==1) only; refuses K>1 (fail-closed). - effectiveAccept REJECT->ACCEPT flip deleted. Vote signatures verified at ingestion (multi-validator): forged/unsigned/wrong-position votes dropped, so the count, the cert, and IsAccepted stay consistent and forgery-proof. - Topology rebuilt: followers broadcast SIGNED votes to ALL validators; whoever collects alpha assembles + gossips the cert; followers finalize on the verified cert (HandleIncomingCert) instead of fast-following. Liveness held: late/dropped Chits no longer freeze (cert gossip + re-request), no self-finality. - Fail-closed DEX guard (quorum_guard.go): RequireQuorumFinalityForValueDEX refuses value DEX unless Mode()==QuorumFinality (K>1 + verifier). - Start refuses K>1 without a verifier (forces the node bump to wire it). Gates (all pass, race-clean): TestConsensus_NoProposerSelfFinality, _AcceptRequiresQuorum, _EquivocatingProposerCannotFinalizeBothForks, _PartitionMinorityCannotFinalize, TestDEX_BFTQuorumFinalizesFill, _ByzantineProposerFakeFillRejected, TestLiveness_NoFreezeUnderLateChits, _DroppedProposerChitsStillFinalizeViaPeerCert, TestQuasarBridge_RealCertVerifies. 194 engine/chain tests pass.