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]>
74 lines
2.9 KiB
Go
74 lines
2.9 KiB
Go
// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package config
|
|
|
|
import "fmt"
|
|
|
|
// Profile is the user-facing chain security profile — a single string
|
|
// knob set in chain config (YAML) or env (CONSENSUS_PROFILE). One
|
|
// config selects one Profile; the wire byte that gets pinned into the
|
|
// cert envelope is derived from the string at config-load time.
|
|
//
|
|
// Three canonical bundles. PQ mode is binary: a chain is strict (or
|
|
// fips, the FIPS-aligned superset of strict) or it is permissive. There
|
|
// is no "hybrid" / "bls" / "classical" pseudo-profile — chains that
|
|
// genuinely need classical primitives pin
|
|
// ForkClassicalCompatUnsafeProfile (0x80) at the byte layer and own the
|
|
// audit consequence.
|
|
//
|
|
// strict — refuses every classical primitive at every layer:
|
|
// ecrecover, sha256, ripemd, blake2F, alt_bn128,
|
|
// BLS12-381 pairings, KZG, X25519. Production PQ chains.
|
|
// permissive — testnet / devnet. Strict-PQ schemes still pinned, but
|
|
// dev backends + fallbacks permitted. Never mainnet.
|
|
// fips — strict + every primitive restricted to FIPS-203 / 204
|
|
// / 205 with the canonical P3Q backend. FIPS-targeted
|
|
// deployments.
|
|
//
|
|
// Operators write the string in config files; protocol layers that
|
|
// need the wire byte call WireByte() (or read ProfileID off the
|
|
// resolved ChainSecurityProfile struct).
|
|
type Profile string
|
|
|
|
const (
|
|
profileStrict Profile = "strict"
|
|
profilePermissive Profile = "permissive"
|
|
profileFIPS Profile = "fips"
|
|
)
|
|
|
|
// String implements fmt.Stringer.
|
|
func (p Profile) String() string { return string(p) }
|
|
|
|
// IsStrict reports whether this profile enforces strict crypto policy
|
|
// — i.e. refuses every classical primitive at every layer. Single
|
|
// canonical entry point for "should this chain install AllForbidden()
|
|
// at the EVM precompile boundary?".
|
|
//
|
|
// Strict and FIPS return true; Permissive returns false.
|
|
func (p Profile) IsStrict() bool {
|
|
return p == profileStrict || p == profileFIPS
|
|
}
|
|
|
|
// Resolve returns the canonical ChainSecurityProfile for this Profile.
|
|
// The returned profile passes Validate() by construction; the caller
|
|
// receives a fresh pointer copy and may retain it without affecting
|
|
// other callers. Canonical immutable values live in profiles.go.
|
|
//
|
|
// Returns a typed error for unknown / empty profiles so chain-config
|
|
// loaders fail loudly at boot.
|
|
func (p Profile) Resolve() (*ChainSecurityProfile, error) {
|
|
switch p {
|
|
case profileStrict:
|
|
return StrictPQ(), nil
|
|
case profilePermissive:
|
|
return Permissive(), nil
|
|
case profileFIPS:
|
|
return FIPS(), nil
|
|
case "":
|
|
return nil, fmt.Errorf("consensus profile is empty; must be one of: permissive, strict, fips")
|
|
default:
|
|
return nil, fmt.Errorf("unknown consensus profile %q; must be one of: permissive, strict, fips", string(p))
|
|
}
|
|
}
|