Files
consensus/config/bridge_profile_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

488 lines
17 KiB
Go

// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package config
import (
"errors"
"testing"
)
// TestBridgeProfileID_String pins the wire-name table so a rename is
// immediately visible in CI.
func TestBridgeProfileID_String(t *testing.T) {
cases := []struct {
id BridgeProfileID
want string
}{
{BridgeProfileIDNone, "none"},
{BridgeProfileIDLuxStrictPQ, "lux-strict-pq-bridge"},
{BridgeProfileIDClassicalCompat, "bridge-classical-compat-unsafe"},
}
for _, c := range cases {
if got := c.id.String(); got != c.want {
t.Errorf("BridgeProfileID(0x%x).String() = %q, want %q", uint32(c.id), got, c.want)
}
}
unknown := BridgeProfileID(0x1234)
if got := unknown.String(); got != "bridge-profile(0x00001234)" {
t.Errorf("unknown BridgeProfileID.String() = %q, want bridge-profile(0x00001234)", got)
}
}
// TestLuxStrictPQBridgeProfile_Fields pins every field of the canonical
// strict-PQ bridge profile. Any rename / renumbering trips this test.
func TestLuxStrictPQBridgeProfile_Fields(t *testing.T) {
p := strictPQBridgeProfile
if p.ProfileID != 0x01 {
t.Errorf("ProfileID = 0x%x, want 0x01", p.ProfileID)
}
if p.Name != "LUX_STRICT_PQ_BRIDGE" {
t.Errorf("Name = %q, want LUX_STRICT_PQ_BRIDGE", p.Name)
}
if p.SourceFinalityScheme != SigSchemePulsar65 {
t.Errorf("SourceFinalityScheme = %s, want pulsar-m-65", p.SourceFinalityScheme)
}
if p.DestFinalityScheme != SigSchemePulsar65 {
t.Errorf("DestFinalityScheme = %s, want pulsar-m-65", p.DestFinalityScheme)
}
if p.ProofPolicyID != ProofPolicySTARKFRISHA3PQ {
t.Errorf("ProofPolicyID = %s, want stark-fri-sha3-pq", p.ProofPolicyID)
}
if p.BridgeAdminScheme != ContractAuthMLDSA87 {
t.Errorf("BridgeAdminScheme = %s, want ml-dsa-87", p.BridgeAdminScheme)
}
if p.BridgePauseScheme != ContractAuthMultisigMLDSA {
t.Errorf("BridgePauseScheme = %s, want multisig-ml-dsa", p.BridgePauseScheme)
}
if p.HashSuiteID != HashSuiteSHA3NIST {
t.Errorf("HashSuiteID = %s, want sha3-nist", p.HashSuiteID)
}
if !p.PostQuantumEndToEnd {
t.Errorf("PostQuantumEndToEnd = false, want true")
}
}
// TestBridgeProfile_StrictPQ_AllForbidBitsTrue — every classical-allow
// gate on the canonical strict-PQ profile MUST be false. The test name
// matches the spec: pinning all `Allows*` to false is what makes the
// profile E2E-PQ.
func TestBridgeProfile_StrictPQ_AllForbidBitsTrue(t *testing.T) {
p := strictPQBridgeProfile
if p.AllowsClassicalAdmin {
t.Errorf("AllowsClassicalAdmin = true, want false on strict-PQ")
}
if p.AllowsBLSAggregate {
t.Errorf("AllowsBLSAggregate = true, want false on strict-PQ")
}
if p.AllowsKZGCommitment {
t.Errorf("AllowsKZGCommitment = true, want false on strict-PQ")
}
if p.AllowsGroth16Wrap {
t.Errorf("AllowsGroth16Wrap = true, want false on strict-PQ")
}
if p.AllowsPairingPrecompile {
t.Errorf("AllowsPairingPrecompile = true, want false on strict-PQ")
}
}
// TestBridgeClassicalCompat_Fields pins every field of the
// classical-compat profile. The label MUST advertise PQ=false; a
// strict-PQ verifier MUST refuse classical-compat deposits via this
// gate (callers).
func TestBridgeClassicalCompat_Fields(t *testing.T) {
p := bridgeClassicalCompat
if p.ProfileID != 0x90 {
t.Errorf("ProfileID = 0x%x, want 0x90", p.ProfileID)
}
if p.Name != "BRIDGE_CLASSICAL_COMPAT_UNSAFE" {
t.Errorf("Name = %q, want BRIDGE_CLASSICAL_COMPAT_UNSAFE", p.Name)
}
if p.PostQuantumEndToEnd {
t.Errorf("PostQuantumEndToEnd = true, want false on classical-compat")
}
if !p.AllowsClassicalAdmin {
t.Errorf("AllowsClassicalAdmin = false, want true on classical-compat")
}
if !p.AllowsBLSAggregate {
t.Errorf("AllowsBLSAggregate = false, want true on classical-compat")
}
if !p.AllowsKZGCommitment {
t.Errorf("AllowsKZGCommitment = false, want true on classical-compat")
}
if !p.AllowsGroth16Wrap {
t.Errorf("AllowsGroth16Wrap = false, want true on classical-compat")
}
if !p.AllowsPairingPrecompile {
t.Errorf("AllowsPairingPrecompile = false, want true on classical-compat")
}
}
// TestBridgeProfile_PostQuantumEndToEnd_Inference — E2E PQ is true ONLY
// when both source+dest are PQ finality AND every Allows* gate is false
// AND every contract-auth/proof-policy is PQ-positive. The matrix below
// exhaustively walks the one-bit-off cases.
func TestBridgeProfile_PostQuantumEndToEnd_Inference(t *testing.T) {
// Baseline: the canonical strict-PQ profile — every field flipped to
// its strict-PQ value. computeImpliedPQ MUST return true.
base := func() BridgeProfile {
p := strictPQBridgeProfile
return p
}
b := base()
if !b.computeImpliedPQ() {
t.Fatalf("baseline strict-PQ profile computeImpliedPQ() = false, want true")
}
// Each subtest flips exactly one field to a classical / non-PQ
// value and asserts the inference flips to false.
t.Run("flip_source_finality_to_BLS", func(t *testing.T) {
p := base()
p.SourceFinalityScheme = SigSchemeBLS12381
if p.computeImpliedPQ() {
t.Errorf("source=BLS classical, computeImpliedPQ() = true, want false")
}
})
t.Run("flip_dest_finality_to_BLS", func(t *testing.T) {
p := base()
p.DestFinalityScheme = SigSchemeBLS12381
if p.computeImpliedPQ() {
t.Errorf("dest=BLS classical, computeImpliedPQ() = true, want false")
}
})
t.Run("flip_proof_policy_to_Groth16", func(t *testing.T) {
p := base()
p.ProofPolicyID = ProofPolicyGroth16BN254Forbid
if p.computeImpliedPQ() {
t.Errorf("policy=Groth16, computeImpliedPQ() = true, want false")
}
})
t.Run("flip_proof_policy_to_KZG", func(t *testing.T) {
p := base()
p.ProofPolicyID = ProofPolicyPLONKKZGForbid
if p.computeImpliedPQ() {
t.Errorf("policy=KZG, computeImpliedPQ() = true, want false")
}
})
t.Run("flip_admin_scheme_to_ECDSA", func(t *testing.T) {
p := base()
p.BridgeAdminScheme = ContractAuthECDSAUnsafe
if p.computeImpliedPQ() {
t.Errorf("admin=ECDSA, computeImpliedPQ() = true, want false")
}
})
t.Run("flip_pause_scheme_to_BLS", func(t *testing.T) {
p := base()
p.BridgePauseScheme = ContractAuthBLSUnsafe
if p.computeImpliedPQ() {
t.Errorf("pause=BLS, computeImpliedPQ() = true, want false")
}
})
t.Run("flip_allows_classical_admin", func(t *testing.T) {
p := base()
p.AllowsClassicalAdmin = true
if p.computeImpliedPQ() {
t.Errorf("AllowsClassicalAdmin=true, computeImpliedPQ() = true, want false")
}
})
t.Run("flip_allows_bls_aggregate", func(t *testing.T) {
p := base()
p.AllowsBLSAggregate = true
if p.computeImpliedPQ() {
t.Errorf("AllowsBLSAggregate=true, computeImpliedPQ() = true, want false")
}
})
t.Run("flip_allows_kzg", func(t *testing.T) {
p := base()
p.AllowsKZGCommitment = true
if p.computeImpliedPQ() {
t.Errorf("AllowsKZGCommitment=true, computeImpliedPQ() = true, want false")
}
})
t.Run("flip_allows_groth16", func(t *testing.T) {
p := base()
p.AllowsGroth16Wrap = true
if p.computeImpliedPQ() {
t.Errorf("AllowsGroth16Wrap=true, computeImpliedPQ() = true, want false")
}
})
t.Run("flip_allows_pairing", func(t *testing.T) {
p := base()
p.AllowsPairingPrecompile = true
if p.computeImpliedPQ() {
t.Errorf("AllowsPairingPrecompile=true, computeImpliedPQ() = true, want false")
}
})
}
// TestBridgeProfile_Validate_LuxStrictPQRejectsBLS — a profile that
// declares PQ=true but pins BLS as a finality scheme MUST be rejected by
// Validate.
func TestBridgeProfile_Validate_LuxStrictPQRejectsBLS(t *testing.T) {
p := strictPQBridgeProfile
p.SourceFinalityScheme = SigSchemeBLS12381
err := p.Validate()
if err == nil {
t.Fatalf("Validate() = nil, want classical-under-strict refusal")
}
if !errors.Is(err, ErrBridgeProfileClassicalUnderStrict) {
t.Errorf("err = %v, want ErrBridgeProfileClassicalUnderStrict", err)
}
}
// TestBridgeProfile_Validate_LuxStrictPQRejectsKZG — same, KZG flag.
func TestBridgeProfile_Validate_LuxStrictPQRejectsKZG(t *testing.T) {
p := strictPQBridgeProfile
p.AllowsKZGCommitment = true
err := p.Validate()
if err == nil {
t.Fatalf("Validate() = nil, want classical-under-strict refusal")
}
if !errors.Is(err, ErrBridgeProfileClassicalUnderStrict) {
t.Errorf("err = %v, want ErrBridgeProfileClassicalUnderStrict", err)
}
}
// TestBridgeProfile_Validate_LuxStrictPQRejectsGroth16 — same, Groth16 flag.
func TestBridgeProfile_Validate_LuxStrictPQRejectsGroth16(t *testing.T) {
p := strictPQBridgeProfile
p.AllowsGroth16Wrap = true
err := p.Validate()
if err == nil {
t.Fatalf("Validate() = nil, want classical-under-strict refusal")
}
if !errors.Is(err, ErrBridgeProfileClassicalUnderStrict) {
t.Errorf("err = %v, want ErrBridgeProfileClassicalUnderStrict", err)
}
}
// TestBridgeProfile_Validate_StrictPQRejectsClassicalProofPolicy — a
// profile that declares PQ=true but pins a Groth16 ProofPolicy MUST be
// rejected. This covers the proof-policy axis distinctly from the
// Allows* flags above.
func TestBridgeProfile_Validate_StrictPQRejectsClassicalProofPolicy(t *testing.T) {
p := strictPQBridgeProfile
p.ProofPolicyID = ProofPolicyGroth16BN254Forbid
err := p.Validate()
if err == nil {
t.Fatalf("Validate() = nil, want classical-under-strict refusal")
}
if !errors.Is(err, ErrBridgeProfileClassicalUnderStrict) {
t.Errorf("err = %v, want ErrBridgeProfileClassicalUnderStrict", err)
}
}
// TestBridgeProfile_Validate_RejectsZeroProfileID — the zero value is
// not a valid bridge profile.
func TestBridgeProfile_Validate_RejectsZeroProfileID(t *testing.T) {
p := BridgeProfile{}
err := p.Validate()
if err == nil {
t.Fatalf("Validate() = nil, want field-unset error")
}
if !errors.Is(err, ErrBridgeProfileFieldUnset) {
t.Errorf("err = %v, want ErrBridgeProfileFieldUnset", err)
}
}
// TestBridgeProfile_Validate_RejectsMislabelledClassicalAsStrict — a
// classical-compat profile cannot pretend to be strict-PQ. A profile
// with classical fields but PostQuantumEndToEnd=true MUST be rejected.
func TestBridgeProfile_Validate_RejectsMislabelledClassicalAsStrict(t *testing.T) {
p := bridgeClassicalCompat
p.PostQuantumEndToEnd = true // operator lies about posture
err := p.Validate()
if err == nil {
t.Fatalf("Validate() = nil, want refusal — operator cannot mislabel classical bridge as strict-PQ")
}
if !errors.Is(err, ErrBridgeProfileClassicalUnderStrict) {
t.Errorf("err = %v, want ErrBridgeProfileClassicalUnderStrict", err)
}
}
// TestBridgeProfile_Validate_RejectsMislabelledStrictAsClassical — the
// inverse: a strict-PQ profile cannot be labelled non-PQ; operators
// must use the explicit classical-compat profile.
func TestBridgeProfile_Validate_RejectsMislabelledStrictAsClassical(t *testing.T) {
p := strictPQBridgeProfile
p.PostQuantumEndToEnd = false
err := p.Validate()
if err == nil {
t.Fatalf("Validate() = nil, want refusal")
}
if !errors.Is(err, ErrBridgeProfileFieldInvalid) {
t.Errorf("err = %v, want ErrBridgeProfileFieldInvalid", err)
}
}
// TestBridgeProfile_RefuseClassicalAdmin_StrictPQRefuses — calling
// RefuseClassicalAdmin under the strict-PQ profile MUST return an
// error; under classical-compat it MUST return nil.
func TestBridgeProfile_RefuseClassicalAdmin_StrictPQRefuses(t *testing.T) {
p := strictPQBridgeProfile
if err := p.RefuseClassicalAdmin(); err == nil {
t.Errorf("strict-PQ RefuseClassicalAdmin() = nil, want refusal")
} else if !errors.Is(err, ErrBridgeProfileForbidden) {
t.Errorf("err = %v, want ErrBridgeProfileForbidden", err)
}
compat := bridgeClassicalCompat
if err := compat.RefuseClassicalAdmin(); err != nil {
t.Errorf("classical-compat RefuseClassicalAdmin() = %v, want nil", err)
}
}
// TestBridgeProfile_RefuseBLSAggregate_StrictPQRefuses — same shape for
// BLS aggregates.
func TestBridgeProfile_RefuseBLSAggregate_StrictPQRefuses(t *testing.T) {
p := strictPQBridgeProfile
if err := p.RefuseBLSAggregate(); err == nil {
t.Errorf("strict-PQ RefuseBLSAggregate() = nil, want refusal")
} else if !errors.Is(err, ErrBridgeProfileForbidden) {
t.Errorf("err = %v, want ErrBridgeProfileForbidden", err)
}
compat := bridgeClassicalCompat
if err := compat.RefuseBLSAggregate(); err != nil {
t.Errorf("classical-compat RefuseBLSAggregate() = %v, want nil", err)
}
}
// TestBridgeProfile_RefuseKZGCommitment_StrictPQRefuses — KZG.
func TestBridgeProfile_RefuseKZGCommitment_StrictPQRefuses(t *testing.T) {
p := strictPQBridgeProfile
if err := p.RefuseKZGCommitment(); err == nil {
t.Errorf("strict-PQ RefuseKZGCommitment() = nil, want refusal")
} else if !errors.Is(err, ErrBridgeProfileForbidden) {
t.Errorf("err = %v, want ErrBridgeProfileForbidden", err)
}
compat := bridgeClassicalCompat
if err := compat.RefuseKZGCommitment(); err != nil {
t.Errorf("classical-compat RefuseKZGCommitment() = %v, want nil", err)
}
}
// TestBridgeProfile_RefuseGroth16Wrap_StrictPQRefuses — Groth16.
func TestBridgeProfile_RefuseGroth16Wrap_StrictPQRefuses(t *testing.T) {
p := strictPQBridgeProfile
if err := p.RefuseGroth16Wrap(); err == nil {
t.Errorf("strict-PQ RefuseGroth16Wrap() = nil, want refusal")
} else if !errors.Is(err, ErrBridgeProfileForbidden) {
t.Errorf("err = %v, want ErrBridgeProfileForbidden", err)
}
compat := bridgeClassicalCompat
if err := compat.RefuseGroth16Wrap(); err != nil {
t.Errorf("classical-compat RefuseGroth16Wrap() = %v, want nil", err)
}
}
// TestBridgeProfile_RefusePairingPrecompile_StrictPQRefuses — pairing
// precompile (EVM 0x08).
func TestBridgeProfile_RefusePairingPrecompile_StrictPQRefuses(t *testing.T) {
p := strictPQBridgeProfile
if err := p.RefusePairingPrecompile(); err == nil {
t.Errorf("strict-PQ RefusePairingPrecompile() = nil, want refusal")
} else if !errors.Is(err, ErrBridgeProfileForbidden) {
t.Errorf("err = %v, want ErrBridgeProfileForbidden", err)
}
compat := bridgeClassicalCompat
if err := compat.RefusePairingPrecompile(); err != nil {
t.Errorf("classical-compat RefusePairingPrecompile() = %v, want nil", err)
}
}
// TestBridgeWithdraw_RefusesECDSAUnderStrictPQ — the spec test name:
// a withdraw call site that gates ecrecover behind RefuseClassicalAdmin
// MUST refuse the operation under the strict-PQ profile. This test
// stands in for the integration site (the actual ecrecover lives in
// the bridge package; the consensus test pins the gate behaviour).
func TestBridgeWithdraw_RefusesECDSAUnderStrictPQ(t *testing.T) {
// Simulate the bridge code path: a withdraw handler receives an
// inbound ECDSA signature; it MUST consult RefuseClassicalAdmin
// before calling ecrecover.
p := strictPQBridgeProfile
if err := p.RefuseClassicalAdmin(); err == nil {
t.Fatalf("withdraw handler under strict-PQ did not refuse ECDSA — call site would invoke ecrecover")
}
// Same path under classical-compat: the gate returns nil, the
// call site proceeds (and is expected to emit the
// bridge_classical_compat_total metric, which is a concern of the
// bridge package, not consensus).
compat := bridgeClassicalCompat
if err := compat.RefuseClassicalAdmin(); err != nil {
t.Fatalf("withdraw handler under classical-compat refused ECDSA, want nil: %v", err)
}
}
// TestBridgeProfile_NilReceiver — every gate method MUST refuse a nil
// profile rather than panicking. Defence in depth: a misconfigured
// caller that forgot to set the profile pointer hits a typed error,
// not a nil-pointer panic.
func TestBridgeProfile_NilReceiver(t *testing.T) {
var p *BridgeProfile
for name, fn := range map[string]func() error{
"Validate": p.Validate,
"RequireAdminPQ": p.RequireAdminPQ,
"RefuseClassicalAdmin": p.RefuseClassicalAdmin,
"RefuseBLSAggregate": p.RefuseBLSAggregate,
"RefuseKZGCommitment": p.RefuseKZGCommitment,
"RefuseGroth16Wrap": p.RefuseGroth16Wrap,
"RefusePairingPrecompile": p.RefusePairingPrecompile,
} {
err := fn()
if err == nil {
t.Errorf("nil-receiver %s() = nil, want ErrBridgeProfileNil", name)
} else if !errors.Is(err, ErrBridgeProfileNil) {
t.Errorf("nil-receiver %s() = %v, want ErrBridgeProfileNil", name, err)
}
}
}
// TestBridgeProfile_RequireAdminPQ_AcceptsPQAdmin — RequireAdminPQ
// returns nil when the profile's BridgeAdminScheme is post-quantum.
func TestBridgeProfile_RequireAdminPQ_AcceptsPQAdmin(t *testing.T) {
p := strictPQBridgeProfile
if err := p.RequireAdminPQ(); err != nil {
t.Errorf("RequireAdminPQ on strict-PQ profile = %v, want nil", err)
}
}
// TestBridgeProfile_IsPostQuantumEndToEnd_Accessor — the public accessor
// matches the field. Pins the contract: callers MUST consult this
// rather than re-derive.
func TestBridgeProfile_IsPostQuantumEndToEnd_Accessor(t *testing.T) {
if !strictPQBridgeProfile.IsPostQuantumEndToEnd() {
t.Errorf("strict-PQ IsPostQuantumEndToEnd() = false, want true")
}
if bridgeClassicalCompat.IsPostQuantumEndToEnd() {
t.Errorf("classical-compat IsPostQuantumEndToEnd() = true, want false")
}
}
// TestBridgeProfile_HelperPredicates pins the local helper predicates
// against representative wire bytes so any renumbering trips CI.
func TestBridgeProfile_HelperPredicates(t *testing.T) {
// sigSchemeIsPostQuantum
if !sigSchemeIsPostQuantum(SigSchemePulsar65) {
t.Errorf("sigSchemeIsPostQuantum(PulsarM65) = false, want true")
}
if !sigSchemeIsPostQuantum(SigSchemeMLDSA65) {
t.Errorf("sigSchemeIsPostQuantum(MLDSA65) = false, want true")
}
if sigSchemeIsPostQuantum(SigSchemeBLS12381) {
t.Errorf("sigSchemeIsPostQuantum(BLS12381) = true, want false")
}
// sigSchemeIsClassical
if !sigSchemeIsClassical(SigSchemeBLS12381) {
t.Errorf("sigSchemeIsClassical(BLS12381) = false, want true")
}
if sigSchemeIsClassical(SigSchemePulsar65) {
t.Errorf("sigSchemeIsClassical(PulsarM65) = true, want false")
}
}