Files
consensus/config/zz_refute_k1_value_start_test.go
zeekayandHanzo Dev 4abf37c952 config: K is a number of draws, not a headcount
The live guard refused to start a chain whose K was below the number of
validators that existed. But sampling is stake-weighted: a validator is drawn in
proportion to what it staked, however many validators there are, and K only
sets how many draws a poll makes. Tying K to the headcount gave a validator
holding a billionth of the stake the same standing as one holding a fifth, and
refused to boot a producing chain because a small staker had joined.

The guard keeps what makes a committee safe — the overlap bound and at least
single-fault tolerance — and stops counting heads. The tier floor stays a
reported target: refusing to start does not add validators, it pins every node
on whatever it last booted.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-16 11:42:58 -07:00

37 lines
1.3 KiB
Go

// Copyright (C) 2019-2026, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package config
import (
"errors"
"testing"
)
// Probe: a sybil-protected chain cannot START with K==1 on ANY network at ANY
// live count. The node's chain manager runs exactly this predicate before it
// wires the engine, so if it refuses everywhere, the synthesized 1-of-1 cert is
// unreachable on every staked chain — including a sovereign L1 whose networkID
// is neither 1 nor 2.
func TestRefute_K1_neverStartsAValueChain(t *testing.T) {
p := SingleValidatorParams()
for _, networkID := range []uint32{1, 2, 3, 1337, 96369, 200200, 36963, 494949, 1872} {
for _, liveN := range []int{0, 1, 2, 4, 5, 11, 21} {
err := p.ValidateForLiveValueNetwork(networkID, liveN)
if !errors.Is(err, ErrKTooLowForValue) {
t.Fatalf("K=1 admitted on networkID=%d liveN=%d: err=%v", networkID, liveN, err)
}
}
}
}
// Probe: an operator override cannot sneak K==1 past the same predicate either —
// the manager applies overrides BEFORE validating, so this is the real call order.
func TestRefute_K1_overrideStillRefused(t *testing.T) {
p := MainnetParams()
p.K, p.AlphaPreference, p.AlphaConfidence = 1, 1, 1
if err := p.ValidateForLiveValueNetwork(1, 21); err == nil {
t.Fatal("K=1 override admitted on mainnet")
}
}