mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
The four finality concepts as DISTINCT authorization tiers that never collapse, named in our astrophysics ontology (no generic BFT / Cosmos vocabulary): Photon in flight, being sampled authorizes nothing Wave the forming Nova preference authorizes nothing Nova beta-ignition, sampler accepts authorizes LOCAL execution (reorgable) Quasar 2/3-stake certificate authorizes bridges / DEX / cross-chain Horizon PQ-sealed, irreversible authorizes irreversible settlement finality.go: the Finality enum + AuthorizesLocalExecution/Export/IrreversibleSettlement boundary methods (the anti-collapse invariant as code: a block below Quasar can never be exported as deterministically final). quorum.go: reconciled to the Nova tier ONLY — NovaQuorum(n)=floor(n/2)+1 (majority, crash-tolerant, drives Nova ignition / local exec), CrashTolerance, NovaBeta. Deleted the node-count CertQuorum/ByzantineTolerance I had added: the Quasar tier has exactly ONE definition and it is config.TwoThirdsStakeFloor / EqualStakeSupermajorityThreshold (strict >2/3 stake, distinct signers via QuorumCert.VerifyWeighted) — never re-expressed as a count. TestNova_Below_Quasar proves the two tiers stay distinct (Nova majority < Quasar 2/3; n=5: 3 vs 4). Removed the dead config.Parameters.ViewChange field (Phase A deleted everything that read it) and its stale test assignments — no Tendermint vocabulary left in runtime config. Whole-repo build + ladder/quorum tests green. Co-authored-by: Hanzo Dev <[email protected]>
69 lines
2.7 KiB
Go
69 lines
2.7 KiB
Go
// Copyright (C) 2019-2026, Lux Industries, Inc. All rights reserved.
|
||
// See the file LICENSE for licensing terms.
|
||
|
||
// b1_cert_no_viewchange_test.go — the B1 premise, made explicit.
|
||
//
|
||
// B1 (owner decision 2026-07-09): keep the ⅔-stake α-of-K quorum cert as the SOLE finality
|
||
// decider (it is the real, working BFT finality) and DELETE the Tendermint view-change/lock/POL
|
||
// liveness layer bolted on top. The view-change exists ONLY to converge COMPETING siblings under
|
||
// the anyone-can-propose storm; with ONE proposer per height (the node-side windower fix, the B1
|
||
// gate) there are no competing siblings, so α canonical signatures align on the single block and
|
||
// the cert finalizes with NO view-change.
|
||
//
|
||
// This pins that premise directly: n=5, ViewChange EXPLICITLY DISABLED, one block per height, the
|
||
// fleet finalizes every height via the α-of-K cert with a single head. It is the standing proof
|
||
// that deleting the view-change removes only the storm-convergence layer, never the decider — the
|
||
// cert path is complete on its own. (The mainstream multinode suite already runs at this default;
|
||
// this makes the B1 contract an explicit, named regression rather than incidental coverage.)
|
||
|
||
package chain
|
||
|
||
import (
|
||
"testing"
|
||
|
||
"github.com/luxfi/ids"
|
||
)
|
||
|
||
func TestB1_CertFinalizesWithoutViewChange_OneProposerPerHeight(t *testing.T) {
|
||
p := prodParams5()
|
||
|
||
net := newSimNet(t, 5, p)
|
||
|
||
// One proposer per height (rotated) — the post-storm-fix regime: no competing siblings, so
|
||
// every honest node signs the SAME canonical block and α=4 signatures assemble one cert.
|
||
const heights = 6
|
||
parentID := ids.Empty
|
||
parentRoot := simGenesisRoot()
|
||
for h := uint64(1); h <= heights; h++ {
|
||
blk := newHonestBlock(parentID, parentRoot, h, "b1-one-proposer")
|
||
net.build(int(h%5), blk) // a single deterministic proposer builds this height
|
||
if !waitFor(emergeTO, func() bool {
|
||
all, fork := net.finalizedEverywhere(blk)
|
||
return all && !fork
|
||
}) {
|
||
t.Fatalf("B1: height %d must finalize via the α-of-K cert with ViewChange OFF; heads=%v",
|
||
h, net.headsAtHeight(h))
|
||
}
|
||
if seen := net.headsAtHeight(h); len(seen) != 1 {
|
||
t.Fatalf("B1: single head required at height %d (the cert is the decider), got %v", h, seen)
|
||
}
|
||
parentID, parentRoot = blk.ID(), blk.stateRoot
|
||
}
|
||
|
||
// Every node finalized the identical chain — the cert alone gave BFT agreement, no view-change.
|
||
for h := uint64(1); h <= heights; h++ {
|
||
var first ids.ID
|
||
for i, n := range net.nodes {
|
||
got, ok := n.rt.FinalizedBlockAtHeight(h)
|
||
if !ok {
|
||
t.Fatalf("B1: node %d missing finalized height %d", i, h)
|
||
}
|
||
if i == 0 {
|
||
first = got
|
||
} else if got != first {
|
||
t.Fatalf("B1: divergence at height %d — node %d has %s, node 0 has %s", h, i, got, first)
|
||
}
|
||
}
|
||
}
|
||
}
|