mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
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]>
37 lines
1.3 KiB
Go
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")
|
|
}
|
|
}
|