mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
style: gofmt the tracked consensus suite
Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -60,12 +60,12 @@ type innerHeadBlock struct {
|
||||
accepts int64
|
||||
}
|
||||
|
||||
func (b *innerHeadBlock) ID() ids.ID { return b.outerID }
|
||||
func (b *innerHeadBlock) Parent() ids.ID { return b.parentID }
|
||||
func (b *innerHeadBlock) ParentID() ids.ID { return b.parentID }
|
||||
func (b *innerHeadBlock) Height() uint64 { return b.height }
|
||||
func (b *innerHeadBlock) Timestamp() time.Time { return time.Unix(0, 0) }
|
||||
func (b *innerHeadBlock) Status() uint8 { return 0 }
|
||||
func (b *innerHeadBlock) ID() ids.ID { return b.outerID }
|
||||
func (b *innerHeadBlock) Parent() ids.ID { return b.parentID }
|
||||
func (b *innerHeadBlock) ParentID() ids.ID { return b.parentID }
|
||||
func (b *innerHeadBlock) Height() uint64 { return b.height }
|
||||
func (b *innerHeadBlock) Timestamp() time.Time { return time.Unix(0, 0) }
|
||||
func (b *innerHeadBlock) Status() uint8 { return 0 }
|
||||
func (b *innerHeadBlock) Verify(context.Context) error { return nil }
|
||||
func (b *innerHeadBlock) Accept(context.Context) error {
|
||||
atomic.AddInt64(&b.accepts, 1)
|
||||
@@ -164,9 +164,9 @@ func TestStormAlias_PeerCertFinalizesLocalWrapper_EVMAccepts(t *testing.T) {
|
||||
t.Cleanup(func() { _ = follower.Stop(context.Background()) })
|
||||
rt := &Runtime{Transitive: follower, config: NetworkConfig{ChainID: chainID, Logger: log.Noop()}}
|
||||
|
||||
innerC := ids.GenerateTestID() // the shared inner execution block at height 1
|
||||
localOuter := ids.GenerateTestID() // THIS node's proposervm wrapper of innerC
|
||||
peerOuter := ids.GenerateTestID() // a DIFFERENT validator's wrapper of innerC
|
||||
innerC := ids.GenerateTestID() // the shared inner execution block at height 1
|
||||
localOuter := ids.GenerateTestID() // THIS node's proposervm wrapper of innerC
|
||||
peerOuter := ids.GenerateTestID() // a DIFFERENT validator's wrapper of innerC
|
||||
const H = uint64(1)
|
||||
|
||||
// This node tracks ONLY its own wrapper. It has verified innerC (blkLocal) but
|
||||
|
||||
@@ -68,9 +68,9 @@ func TestBFTCommittee_FormulaReproducesEveryPreset(t *testing.T) {
|
||||
params config.Parameters
|
||||
wantedAlpha int
|
||||
}{
|
||||
{"DefaultParams", config.DefaultParams(), 14}, // K=20 → 14
|
||||
{"MainnetParams", config.MainnetParams(), 15}, // K=21 → 15
|
||||
{"TestnetParams", config.TestnetParams(), 8}, // K=11 → 8
|
||||
{"DefaultParams", config.DefaultParams(), 14}, // K=20 → 14
|
||||
{"MainnetParams", config.MainnetParams(), 15}, // K=21 → 15
|
||||
{"TestnetParams", config.TestnetParams(), 8}, // K=11 → 8
|
||||
{"LocalBFTParams", config.LocalBFTParams(), 3}, // K=4 → 3
|
||||
}
|
||||
for _, tc := range cases {
|
||||
|
||||
@@ -30,16 +30,16 @@ type tBlock struct {
|
||||
valid bool
|
||||
}
|
||||
|
||||
func (b *tBlock) ID() ids.ID { return b.id }
|
||||
func (b *tBlock) Parent() ids.ID { return b.parent }
|
||||
func (b *tBlock) ParentID() ids.ID { return b.parent }
|
||||
func (b *tBlock) Height() uint64 { return b.height }
|
||||
func (b *tBlock) Timestamp() time.Time { return time.Unix(int64(b.height), 0) }
|
||||
func (b *tBlock) Status() uint8 { return 0 }
|
||||
func (b *tBlock) Verify(context.Context) error { return nil }
|
||||
func (b *tBlock) Accept(context.Context) error { return nil }
|
||||
func (b *tBlock) Reject(context.Context) error { return nil }
|
||||
func (b *tBlock) Bytes() []byte { return b.bytes }
|
||||
func (b *tBlock) ID() ids.ID { return b.id }
|
||||
func (b *tBlock) Parent() ids.ID { return b.parent }
|
||||
func (b *tBlock) ParentID() ids.ID { return b.parent }
|
||||
func (b *tBlock) Height() uint64 { return b.height }
|
||||
func (b *tBlock) Timestamp() time.Time { return time.Unix(int64(b.height), 0) }
|
||||
func (b *tBlock) Status() uint8 { return 0 }
|
||||
func (b *tBlock) Verify(context.Context) error { return nil }
|
||||
func (b *tBlock) Accept(context.Context) error { return nil }
|
||||
func (b *tBlock) Reject(context.Context) error { return nil }
|
||||
func (b *tBlock) Bytes() []byte { return b.bytes }
|
||||
|
||||
// chainOf builds a genesis→N chain. blocks[0] is genesis (height 0, parent Empty).
|
||||
// invalidAt (if > 0) marks that height's block invalid (a corrupt/forged block).
|
||||
@@ -67,13 +67,13 @@ func chainOf(n int, invalidAt uint64) ([]*tBlock, map[string]*tBlock) {
|
||||
// connecting / no-quorum cases, and `connectAfter` models the CANARY boot race (the beacon
|
||||
// set is still connecting for the first N frontier queries, then names the tip).
|
||||
type testPeer struct {
|
||||
byHeight []*tBlock
|
||||
byID map[ids.ID]*tBlock
|
||||
serveNothing bool // model a dead/withholding peer
|
||||
status FrontierStatus // status to report once "connected" (default FrontierNamed)
|
||||
connectAfter int // report FrontierConnecting for the first N queries, then `status`
|
||||
noQuorumFor int // after connecting, report FrontierNoQuorum for the next N queries (a TRANSIENT split that settles), then `status`
|
||||
frontierCalls int // observable: how many times the loop asked for the frontier
|
||||
byHeight []*tBlock
|
||||
byID map[ids.ID]*tBlock
|
||||
serveNothing bool // model a dead/withholding peer
|
||||
status FrontierStatus // status to report once "connected" (default FrontierNamed)
|
||||
connectAfter int // report FrontierConnecting for the first N queries, then `status`
|
||||
noQuorumFor int // after connecting, report FrontierNoQuorum for the next N queries (a TRANSIENT split that settles), then `status`
|
||||
frontierCalls int // observable: how many times the loop asked for the frontier
|
||||
}
|
||||
|
||||
func newTestPeer(chain []*tBlock) *testPeer {
|
||||
@@ -176,6 +176,7 @@ func (n *testNode) ParseBlock(_ context.Context, b []byte) (block.Block, error)
|
||||
func (n *testNode) LastAccepted(context.Context) (ids.ID, uint64, error) {
|
||||
return n.tipID, n.height, nil
|
||||
}
|
||||
|
||||
// Has reports STORE presence (the block can be served by GetBlock) — accepted or not.
|
||||
func (n *testNode) Has(_ context.Context, id ids.ID) bool { return n.have[id] }
|
||||
|
||||
@@ -224,7 +225,7 @@ func runBootstrap(t *testing.T, peer BlockSource, node Chain) error {
|
||||
Source: peer,
|
||||
Chain: node,
|
||||
MaxBlocksPerFetch: 256,
|
||||
RetryInterval: time.Millisecond, // keep the stall/connect paths fast in tests
|
||||
RetryInterval: time.Millisecond, // keep the stall/connect paths fast in tests
|
||||
ConnectDeadline: 200 * time.Millisecond, // bound the beacon-connectivity wait in tests
|
||||
})
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
@@ -358,8 +359,8 @@ func TestLoop_StaleNodeConvergesAfterDelayedBeaconConnect(t *testing.T) {
|
||||
func TestLoop_GenuinelyCaughtUp_CompletesPromptly(t *testing.T) {
|
||||
const N = 25
|
||||
chain, reg := chainOf(N, 0)
|
||||
peer := newTestPeer(chain) // FrontierNamed, tip = N
|
||||
node := newTestNode(reg, chain[N]) // already at N — holds the frontier tip
|
||||
peer := newTestPeer(chain) // FrontierNamed, tip = N
|
||||
node := newTestNode(reg, chain[N]) // already at N — holds the frontier tip
|
||||
|
||||
if err := runBootstrap(t, peer, node); err != nil {
|
||||
t.Fatalf("a genuinely caught-up node must complete promptly, got %v", err)
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
// 2. FuzzFinalizeDecision — the finalize / equivocation decision function. A random
|
||||
// stream of {hint, cert} operations over small pools of {height, canonical,
|
||||
// envelope} ids must NEVER panic and must NEVER violate the core invariant:
|
||||
// (INV) for every height H at most ONE canonical commitment is finalized, it
|
||||
// is immutable once set, a hint never finalizes, and equivocation is
|
||||
// raised IFF a DIFFERENT canonical is presented at a certified height.
|
||||
// (INV) for every height H at most ONE canonical commitment is finalized, it
|
||||
// is immutable once set, a hint never finalizes, and equivocation is
|
||||
// raised IFF a DIFFERENT canonical is presented at a certified height.
|
||||
package chain
|
||||
|
||||
import (
|
||||
|
||||
@@ -61,8 +61,8 @@ type pChainBlock struct {
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (b *pChainBlock) ID() ids.ID { return b.id }
|
||||
func (b *pChainBlock) Parent() ids.ID { return b.parentID }
|
||||
func (b *pChainBlock) ID() ids.ID { return b.id }
|
||||
func (b *pChainBlock) Parent() ids.ID { return b.parentID }
|
||||
func (b *pChainBlock) ParentID() ids.ID { return b.parentID }
|
||||
func (b *pChainBlock) Height() uint64 { return b.height }
|
||||
func (b *pChainBlock) PChainHeight() uint64 { return b.pChainHeight } // the boundary hook
|
||||
@@ -178,7 +178,9 @@ func newEpochSigners(n int) *epochSigners {
|
||||
return es
|
||||
}
|
||||
|
||||
func (es *epochSigners) pub(i int) ed25519.PublicKey { return es.keys[es.ids[i]].Public().(ed25519.PublicKey) }
|
||||
func (es *epochSigners) pub(i int) ed25519.PublicKey {
|
||||
return es.keys[es.ids[i]].Public().(ed25519.PublicKey)
|
||||
}
|
||||
func (es *epochSigners) signerFor(i int) VoteSigner {
|
||||
priv := es.keys[es.ids[i]]
|
||||
return voteSignerFunc(func(message []byte) ([]byte, error) { return ed25519.Sign(priv, message), nil })
|
||||
@@ -267,8 +269,8 @@ func TestPChainEpochFinality_RealWiring(t *testing.T) {
|
||||
rec := &recordingGossiper{}
|
||||
e := NewWithConfig(Config{Params: params5()},
|
||||
WithQuorumCert(chainID, es.ids[0], src, rec, es.signerFor(0)),
|
||||
WithStakeWeighting(src), // ⅔-by-stake, read at the epoch height
|
||||
WithValidatorSetRoot(src), // set-root stamped at the epoch height
|
||||
WithStakeWeighting(src), // ⅔-by-stake, read at the epoch height
|
||||
WithValidatorSetRoot(src), // set-root stamped at the epoch height
|
||||
)
|
||||
if err := e.Start(context.Background(), true); err != nil {
|
||||
t.Fatalf("Start: %v", err)
|
||||
@@ -481,4 +483,3 @@ func TestPChainEpochFinality_EmptyEpochFailsClosed(t *testing.T) {
|
||||
t.Fatalf("VM.Accept must NOT run for an empty-epoch block, got %d", blk.AcceptCalled())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,19 +7,19 @@
|
||||
// the epoch-blind height-only slot fix. The remaining defect was in the guard's LIFECYCLE,
|
||||
// not its key:
|
||||
//
|
||||
// 1. A node signs the winner A at height H (committedSlot{H}=A).
|
||||
// 2. A's α-of-K cert forms; the node finalizes H. The sole finalizer
|
||||
// (acceptWithCertCore) advanced the certified frontier to H, then PRUNED the
|
||||
// equivocation guard for every height <= H — INCLUDING H itself.
|
||||
// 3. A losing sibling B at height H with a DIFFERENT outer parent (a bare/pre-fork
|
||||
// envelope where the winner was proposervm-wrapped, or vice-versa) is NOT in
|
||||
// losingSubtrees(A) — losingSubtrees only rejects the OTHER CHILDREN OF A's parent —
|
||||
// so B stays tracked and UNDECIDED after A finalizes.
|
||||
// 4. The convergence pass then re-offers height H (its slot was just deleted), and
|
||||
// reserveSlotForSign(H, B) found an EMPTY slot and admitted B — this node's SECOND
|
||||
// signature at height H. Enough nodes doing this assembled a second α-of-K cert at H
|
||||
// → fatal EQUIVOCATION → os.Exit(1) fleet-wide (the live devnet artifact: the
|
||||
// conflicting cert's canonical == its envelope, i.e. exactly the bare sibling).
|
||||
// 1. A node signs the winner A at height H (committedSlot{H}=A).
|
||||
// 2. A's α-of-K cert forms; the node finalizes H. The sole finalizer
|
||||
// (acceptWithCertCore) advanced the certified frontier to H, then PRUNED the
|
||||
// equivocation guard for every height <= H — INCLUDING H itself.
|
||||
// 3. A losing sibling B at height H with a DIFFERENT outer parent (a bare/pre-fork
|
||||
// envelope where the winner was proposervm-wrapped, or vice-versa) is NOT in
|
||||
// losingSubtrees(A) — losingSubtrees only rejects the OTHER CHILDREN OF A's parent —
|
||||
// so B stays tracked and UNDECIDED after A finalizes.
|
||||
// 4. The convergence pass then re-offers height H (its slot was just deleted), and
|
||||
// reserveSlotForSign(H, B) found an EMPTY slot and admitted B — this node's SECOND
|
||||
// signature at height H. Enough nodes doing this assembled a second α-of-K cert at H
|
||||
// → fatal EQUIVOCATION → os.Exit(1) fleet-wide (the live devnet artifact: the
|
||||
// conflicting cert's canonical == its envelope, i.e. exactly the bare sibling).
|
||||
//
|
||||
// The fix is two-layered and this test pins both:
|
||||
// - PRUNE STRICTLY BELOW the finalized height (retain the tip's slot) — the in-memory belt.
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
// DUPLICATES (one inner block, two envelopes), never a fork.
|
||||
//
|
||||
// THE FIX, proven here:
|
||||
// PART A — vm.LastAccepted is a NON-AUTHORITATIVE recovery HINT, never finality.
|
||||
// finalizedTip/height advance ONLY on a verified QC (or bootstrap
|
||||
// frontier-trust). A locally-seeded sibling can never equivocate.
|
||||
// PART B — finality is defined over the CANONICAL execution commitment, not the
|
||||
// outer envelope. Two certs at one height conflict IFF their
|
||||
// canonical_block_id differs. Same canonical / different envelope =
|
||||
// duplicate alias.
|
||||
//
|
||||
// PART A — vm.LastAccepted is a NON-AUTHORITATIVE recovery HINT, never finality.
|
||||
// finalizedTip/height advance ONLY on a verified QC (or bootstrap
|
||||
// frontier-trust). A locally-seeded sibling can never equivocate.
|
||||
// PART B — finality is defined over the CANONICAL execution commitment, not the
|
||||
// outer envelope. Two certs at one height conflict IFF their
|
||||
// canonical_block_id differs. Same canonical / different envelope =
|
||||
// duplicate alias.
|
||||
//
|
||||
// THE INVARIANT (encoded + asserted): for every height H, at most ONE canonical
|
||||
// execution commitment may be finalized; all envelopes / VM aliases / seed states
|
||||
|
||||
@@ -153,8 +153,8 @@ func TestAdv_DivergentCanonicalNeverCollapsed(t *testing.T) {
|
||||
tipCanon := ids.GenerateTestID()
|
||||
led := seedLedger(tipOuter, tipCanon, 5)
|
||||
|
||||
inner6 := ids.GenerateTestID() // the TRUE height-6 execution the cert attests
|
||||
inner6evil := ids.GenerateTestID() // a DIFFERENT height-6 execution
|
||||
inner6 := ids.GenerateTestID() // the TRUE height-6 execution the cert attests
|
||||
inner6evil := ids.GenerateTestID() // a DIFFERENT height-6 execution
|
||||
inner7 := ids.GenerateTestID()
|
||||
wrapperEvil6 := ids.GenerateTestID() // wrapper of the WRONG execution, chains to tip
|
||||
wrapperA6 := ids.GenerateTestID() // absent wrapper of the TRUE inner6
|
||||
@@ -173,7 +173,7 @@ func TestAdv_DivergentCanonicalNeverCollapsed(t *testing.T) {
|
||||
if err == nil {
|
||||
for _, id := range plan.Accept {
|
||||
if id == wrapperEvil6 {
|
||||
t.Fatalf("FORK: collapsed a DIVERGENT-execution wrapper (inner6evil) in place of the "+
|
||||
t.Fatalf("FORK: collapsed a DIVERGENT-execution wrapper (inner6evil) in place of the " +
|
||||
"attested inner6 — two nodes would finalize different state at height 6")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/luxfi/consensus/engine/chain/block"
|
||||
"github.com/luxfi/consensus/config"
|
||||
"github.com/luxfi/consensus/engine/chain/block"
|
||||
"github.com/luxfi/ids"
|
||||
"github.com/luxfi/log"
|
||||
)
|
||||
@@ -45,9 +45,18 @@ type instrBlock struct {
|
||||
d *lockDetector
|
||||
}
|
||||
|
||||
func (b *instrBlock) Accept(ctx context.Context) error { b.d.check("block.Accept"); return b.trackingMockBlock.Accept(ctx) }
|
||||
func (b *instrBlock) Verify(ctx context.Context) error { b.d.check("block.Verify"); return b.trackingMockBlock.Verify(ctx) }
|
||||
func (b *instrBlock) Reject(ctx context.Context) error { b.d.check("block.Reject"); return b.trackingMockBlock.Reject(ctx) }
|
||||
func (b *instrBlock) Accept(ctx context.Context) error {
|
||||
b.d.check("block.Accept")
|
||||
return b.trackingMockBlock.Accept(ctx)
|
||||
}
|
||||
func (b *instrBlock) Verify(ctx context.Context) error {
|
||||
b.d.check("block.Verify")
|
||||
return b.trackingMockBlock.Verify(ctx)
|
||||
}
|
||||
func (b *instrBlock) Reject(ctx context.Context) error {
|
||||
b.d.check("block.Reject")
|
||||
return b.trackingMockBlock.Reject(ctx)
|
||||
}
|
||||
|
||||
// instrVM wraps a trackingMockVM and checks the invariant on every VM call-out, returning
|
||||
// instrumented blocks so block-level call-outs are covered too.
|
||||
|
||||
@@ -28,16 +28,16 @@ type failingBlock struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (b *failingBlock) ID() ids.ID { return b.id }
|
||||
func (b *failingBlock) Parent() ids.ID { return b.parentID }
|
||||
func (b *failingBlock) ParentID() ids.ID { return b.parentID }
|
||||
func (b *failingBlock) Height() uint64 { return b.height }
|
||||
func (b *failingBlock) Timestamp() time.Time { return time.Unix(0, 0) }
|
||||
func (b *failingBlock) Status() uint8 { return 0 }
|
||||
func (b *failingBlock) Bytes() []byte { return []byte{1} }
|
||||
func (b *failingBlock) Verify(context.Context) error { return b.err }
|
||||
func (b *failingBlock) Accept(context.Context) error { return nil }
|
||||
func (b *failingBlock) Reject(context.Context) error { return nil }
|
||||
func (b *failingBlock) ID() ids.ID { return b.id }
|
||||
func (b *failingBlock) Parent() ids.ID { return b.parentID }
|
||||
func (b *failingBlock) ParentID() ids.ID { return b.parentID }
|
||||
func (b *failingBlock) Height() uint64 { return b.height }
|
||||
func (b *failingBlock) Timestamp() time.Time { return time.Unix(0, 0) }
|
||||
func (b *failingBlock) Status() uint8 { return 0 }
|
||||
func (b *failingBlock) Bytes() []byte { return []byte{1} }
|
||||
func (b *failingBlock) Verify(context.Context) error { return b.err }
|
||||
func (b *failingBlock) Accept(context.Context) error { return nil }
|
||||
func (b *failingBlock) Reject(context.Context) error { return nil }
|
||||
|
||||
// TestMissingAncestorIsNotARejectedCert is the property the live wedge turned on.
|
||||
//
|
||||
|
||||
@@ -210,8 +210,8 @@ func TestRED_INT_DoubleCount_SelfLowStake(t *testing.T) {
|
||||
// defence — before it existed, those replays alone pushed acceptVotes past α and
|
||||
// stake-weighting was the ONLY thing standing between a replay and finality.
|
||||
if rt.HasEnoughResponsesForRetry(blk.id) {
|
||||
t.Fatalf("REPLAY INFLATED THE COUNT: 64 replays of ONE validator tripped the α=3 count "+
|
||||
"predicate. α must mean α DISTINCT validators; a voter that can advance the tally by "+
|
||||
t.Fatalf("REPLAY INFLATED THE COUNT: 64 replays of ONE validator tripped the α=3 count " +
|
||||
"predicate. α must mean α DISTINCT validators; a voter that can advance the tally by " +
|
||||
"repeating itself makes the count road forgeable by a single peer.")
|
||||
}
|
||||
|
||||
|
||||
@@ -360,10 +360,10 @@ func TestRecovery_OutOfOrderFollowerCatchesUpAndFinalizes(t *testing.T) {
|
||||
// relayCatchup re-delivers a requested missing block to the asking follower via
|
||||
// followVerifiedBlock — modelling the node-layer GetAncestors→Put round-trip.
|
||||
type relayCatchup struct {
|
||||
net *relayNetwork
|
||||
store map[ids.ID]*verifyOnceBlock
|
||||
mu sync.Mutex
|
||||
count int
|
||||
net *relayNetwork
|
||||
store map[ids.ID]*verifyOnceBlock
|
||||
mu sync.Mutex
|
||||
count int
|
||||
}
|
||||
|
||||
func (c *relayCatchup) RequestAncestors(_ ids.ID, _ ids.ID, missingBlockID ids.ID, from ids.NodeID) error {
|
||||
|
||||
@@ -79,7 +79,7 @@ func TestRed_LosingSiblingHoldsValidCert_NoVoteOnceDiscipline(t *testing.T) {
|
||||
// own B-vote is refused by reserveSlotForSign — B can never collect alpha SIGNED
|
||||
// accepts, so no conflicting cert can form. (Pre-fix, the self-vote plus injected
|
||||
// equivocations gave B a full alpha-of-K cert — the fork.)
|
||||
injectVotes(e, vs, posB, 1, 2, 3) // refused: 1,2,3 committed A; self committed A
|
||||
injectVotes(e, vs, posB, 1, 2, 3) // refused: 1,2,3 committed A; self committed A
|
||||
time.Sleep(300 * time.Millisecond) // let any (refused) vote plumbing settle
|
||||
|
||||
if e.IsAccepted(B.id) {
|
||||
|
||||
@@ -115,8 +115,8 @@ func TestRedScale_TwoThirdsStakeFloor_OverflowSafeToUint64Max(t *testing.T) {
|
||||
// 3·floor ≤ 2·total < 3·(floor+1). Check via big.Int (no wrap).
|
||||
three := big.NewInt(3)
|
||||
twoTotal := new(big.Int).Mul(new(big.Int).SetUint64(total), big.NewInt(2))
|
||||
lo := new(big.Int).Mul(new(big.Int).SetUint64(got), three) // 3·floor
|
||||
hi := new(big.Int).Mul(new(big.Int).SetUint64(got+1), three) // 3·(floor+1)
|
||||
lo := new(big.Int).Mul(new(big.Int).SetUint64(got), three) // 3·floor
|
||||
hi := new(big.Int).Mul(new(big.Int).SetUint64(got+1), three) // 3·(floor+1)
|
||||
if lo.Cmp(twoTotal) > 0 || twoTotal.Cmp(hi) >= 0 {
|
||||
t.Errorf("TwoThirdsStakeFloor(%d)=%d violates 3·floor ≤ 2·total < 3·(floor+1)", total, got)
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func TestBlue_SingleValidator_DecidesThroughFullRuntimePath(t *testing.T) {
|
||||
Gossiper: &recordingGossiper{}, // all sends return 0 (no peers) — the single-node condition
|
||||
VM: vm,
|
||||
Params: &p,
|
||||
VoteVerifier: rejectingVerifier{}, // wired like a value chain; rejects → the synthesize path
|
||||
VoteVerifier: rejectingVerifier{}, // wired like a value chain; rejects → the synthesize path
|
||||
VoteSigner: testAuth.signerFor(self),
|
||||
})
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -133,7 +133,7 @@ func (n *testNet) Ballots(_ context.Context, heights []uint64) ([]Ballot, uint64
|
||||
|
||||
var (
|
||||
_ VM[block.StateSummary] = (*testVM)(nil)
|
||||
_ Source = (*testNet)(nil)
|
||||
_ Source = (*testNet)(nil)
|
||||
)
|
||||
|
||||
// voter is one beacon in the ratification round.
|
||||
|
||||
@@ -36,7 +36,7 @@ func newStakeMap(vs *testValidatorSet, weights ...uint64) *stakeMap {
|
||||
|
||||
func (s *stakeMap) Weight(nodeID ids.NodeID, _ uint64) uint64 { return s.w[nodeID] }
|
||||
func (s *stakeMap) TotalStake(_ uint64) uint64 { return s.total }
|
||||
func (s *stakeMap) ValidatorCount(_ uint64) int { return len(s.w) }
|
||||
func (s *stakeMap) ValidatorCount(_ uint64) int { return len(s.w) }
|
||||
|
||||
// TestWeighted_LowStakeCoalitionRejected is the HIGH-3 core: 4 validators with
|
||||
// stake {97, 1, 1, 1} (total 100). A cert signed by the THREE low-stake nodes
|
||||
|
||||
@@ -148,9 +148,9 @@ func TestRedWinner_DistinctCanonicals_LowestWins(t *testing.T) {
|
||||
// diverge EXACTLY on the abandoned block.
|
||||
func TestRedWinner_DecidedAndAbandonedFiltering(t *testing.T) {
|
||||
parent := mkID(0xF000)
|
||||
lowest := &Block{id: mkID(100), parentID: parent, height: 1, canonicalID: mkID(1)} // lowest canonical
|
||||
mid := &Block{id: mkID(200), parentID: parent, height: 1, canonicalID: mkID(2)} // middle
|
||||
high := &Block{id: mkID(300), parentID: parent, height: 1, canonicalID: mkID(3)} // highest
|
||||
lowest := &Block{id: mkID(100), parentID: parent, height: 1, canonicalID: mkID(1)} // lowest canonical
|
||||
mid := &Block{id: mkID(200), parentID: parent, height: 1, canonicalID: mkID(2)} // middle
|
||||
high := &Block{id: mkID(300), parentID: parent, height: 1, canonicalID: mkID(3)} // highest
|
||||
decidedBlk := &Block{id: mkID(400), parentID: parent, height: 1, canonicalID: mkID(0)} // lowest of all, but DECIDED
|
||||
|
||||
blocks := []*Block{lowest, mid, high, decidedBlk}
|
||||
|
||||
@@ -26,15 +26,15 @@
|
||||
// Each lane is the REAL one:
|
||||
// - Beam : luxfi/crypto/bls aggregate verify (one aggregate signature)
|
||||
// - Pulsar : (a) TALUS compact threshold sig = ONE FIPS-204 ML-DSA-65 verify
|
||||
// (b) Sampled cert = r dealerless-committee ML-DSA-65 verifies
|
||||
// over the unbiasable-sortition plan (the default HYBRID_PQ,
|
||||
// n=8,t=7,m=12,r=8 = PulsarHybridPQv1)
|
||||
// (b) Sampled cert = r dealerless-committee ML-DSA-65 verifies
|
||||
// over the unbiasable-sortition plan (the default HYBRID_PQ,
|
||||
// n=8,t=7,m=12,r=8 = PulsarHybridPQv1)
|
||||
// - Corona : luxfi/threshold/protocols/corona Ring-LWE threshold verify
|
||||
// (O(1): one group signature, committee size only affects SIGN)
|
||||
// (O(1): one group signature, committee size only affects SIGN)
|
||||
// - Magnetar : VerifyMagnetarQuorum = N independent FIPS-205 SLH-DSA-192s
|
||||
// verifies (Track-A trustless rollup, O(N))
|
||||
// verifies (Track-A trustless rollup, O(N))
|
||||
// - P3Q : VerifyP3QRollupLeg Direct = N independent FIPS-204 ML-DSA-65
|
||||
// verifies (O(N) fallback rollup)
|
||||
// verifies (O(N) fallback rollup)
|
||||
//
|
||||
// Run:
|
||||
//
|
||||
@@ -532,9 +532,9 @@ func BenchmarkPQPolicyTiers_zzSummary(b *testing.B) {
|
||||
// Compose the five tiers. Pulsar lane in the tiers = the sampled cert (the
|
||||
// default HYBRID_PQ); the TALUS compact alternative is reported separately.
|
||||
type tier struct {
|
||||
name string
|
||||
cost laneCost
|
||||
legs string
|
||||
name string
|
||||
cost laneCost
|
||||
legs string
|
||||
}
|
||||
sum := func(parts ...laneCost) laneCost {
|
||||
var out laneCost
|
||||
|
||||
@@ -73,9 +73,9 @@ type envValidators struct {
|
||||
classKeys map[ClassicalScheme][]byte
|
||||
}
|
||||
|
||||
func (v *envValidators) Root() [48]byte { return v.root }
|
||||
func (v *envValidators) Epoch() uint64 { return v.epoch }
|
||||
func (v *envValidators) WeightedConfig() QuorumVerifierConfig { return v.cfg }
|
||||
func (v *envValidators) Root() [48]byte { return v.root }
|
||||
func (v *envValidators) Epoch() uint64 { return v.epoch }
|
||||
func (v *envValidators) WeightedConfig() QuorumVerifierConfig { return v.cfg }
|
||||
func (v *envValidators) WeightedEnvelope() QuorumMessageEnvelope { return v.env }
|
||||
func (v *envValidators) ThresholdGroupKey(kind LegKind) (ThresholdGroupKey, bool) {
|
||||
switch kind {
|
||||
|
||||
@@ -64,8 +64,8 @@ func TestDefaultParams_FailureProbability(t *testing.T) {
|
||||
// liveness slack at a precisely-quantified security cost.
|
||||
func TestLivenessSlackCostsSecurity(t *testing.T) {
|
||||
p := PulsarHybridPQv1.CaptureProbability()
|
||||
allOfR := SampledFailureProbability(p, 8, 8) // m=r=8 → p^8
|
||||
slack := SampledFailureProbability(p, 12, 8) // m=12, r=8
|
||||
allOfR := SampledFailureProbability(p, 8, 8) // m=r=8 → p^8
|
||||
slack := SampledFailureProbability(p, 12, 8) // m=12, r=8
|
||||
if slack.Cmp(allOfR) <= 0 {
|
||||
t.Fatalf("expected P_fail(m=12,r=8) > P_fail(m=8,r=8); got %s vs %s", slack.RatString(), allOfR.RatString())
|
||||
}
|
||||
|
||||
@@ -235,10 +235,10 @@ func FuzzUnmarshalWeightedQuorumCert(f *testing.F) {
|
||||
if wire, err := full.Compact().MarshalBinary(); err == nil {
|
||||
f.Add(wire)
|
||||
}
|
||||
f.Add([]byte{}) // empty
|
||||
f.Add([]byte{wqcKindFull}) // kind only, truncated
|
||||
f.Add([]byte{wqcKindCompact}) // compact kind only, truncated
|
||||
f.Add([]byte{0x99}) // bad kind
|
||||
f.Add([]byte{}) // empty
|
||||
f.Add([]byte{wqcKindFull}) // kind only, truncated
|
||||
f.Add([]byte{wqcKindCompact}) // compact kind only, truncated
|
||||
f.Add([]byte{0x99}) // bad kind
|
||||
// A full header claiming an enormous signer_count with no records.
|
||||
hdr := make([]byte, wqcHeaderSize)
|
||||
hdr[0] = wqcKindFull
|
||||
@@ -282,17 +282,17 @@ func TestCTO_MalformedNeverPanics(t *testing.T) {
|
||||
}
|
||||
|
||||
cases := map[string][]byte{
|
||||
"nil": nil,
|
||||
"empty": {},
|
||||
"kind_full_only": {wqcKindFull},
|
||||
"kind_compact_only": {wqcKindCompact},
|
||||
"bad_kind": {0x99, 0x00, 0x01},
|
||||
"single_zero": {0x00},
|
||||
"header_minus_one": good[:wqcHeaderSize-1],
|
||||
"good_plus_trailer": append(append([]byte(nil), good...), 0xDE, 0xAD),
|
||||
"all_0xFF_short": bytesRepeat(0xFF, 16),
|
||||
"all_0xFF_headerlen": bytesRepeat(0xFF, wqcHeaderSize),
|
||||
"all_0x00_headerlen": bytesRepeat(0x00, wqcHeaderSize),
|
||||
"nil": nil,
|
||||
"empty": {},
|
||||
"kind_full_only": {wqcKindFull},
|
||||
"kind_compact_only": {wqcKindCompact},
|
||||
"bad_kind": {0x99, 0x00, 0x01},
|
||||
"single_zero": {0x00},
|
||||
"header_minus_one": good[:wqcHeaderSize-1],
|
||||
"good_plus_trailer": append(append([]byte(nil), good...), 0xDE, 0xAD),
|
||||
"all_0xFF_short": bytesRepeat(0xFF, 16),
|
||||
"all_0xFF_headerlen": bytesRepeat(0xFF, wqcHeaderSize),
|
||||
"all_0x00_headerlen": bytesRepeat(0x00, wqcHeaderSize),
|
||||
}
|
||||
// Plus every truncation prefix of a valid full cert.
|
||||
for n := 0; n < len(good); n++ {
|
||||
|
||||
Reference in New Issue
Block a user