Documentation
¶
Overview ¶
Package pq defines the strict post-quantum profile that constrains which cryptographic operations a Quasar node accepts.
The package contains no cryptographic primitives. It expresses a policy:
Profile is the value. Eight Forbid* flags, one per cryptographic primitive family. nil and the zero value both mean classical semantics; Strict sets every flag true.
Op is the operation a precompile reports. Sixteen stable identifiers cover the EVM precompile families plus polynomial commitments.
Refuse is the gate. Every constrained operation calls it once at the top of its entry point and otherwise proceeds in its own lane. The profile does not know how the operations compute; the operations do not know how the profile is selected.
One way only: one variable holds the active profile, one function installs it, one function reads it, one function gates each call.
pq.SetActive(pq.Strict()) // chain bootstrap if err := pq.Refuse(pq.OpEcrecover); err != nil // every precompile
Profile values are immutable. Two helpers construct the canonical presets:
- Strict forbids every classical primitive family
- Permissive admits every operation
Profile.Hash is the SHA3-256 of the canonical encoding. Consensus emits this hash into block headers so any observer can verify which profile a block was produced under.
Environment override: when QUASAR_STRICT_PQ is set to a truthy value, FromEnv returns Strict; otherwise it returns Permissive. Mainnet binaries set this in their entrypoint.
Index ¶
Constants ¶
const EnvVar = "QUASAR_STRICT_PQ"
EnvVar is the single environment variable that selects the active profile at startup. Production binaries read it once in main and install the result via SetActive.
Variables ¶
var ( ErrEcrecoverForbidden = errors.New("ecrecover forbidden by chain security profile (PQ)") ErrP256VerifyForbidden = errors.New("p256Verify forbidden by chain security profile (PQ)") ErrSHA256Forbidden = errors.New("sha256 forbidden by chain security profile (PQ)") ErrRIPEMD160Forbidden = errors.New("ripemd160 forbidden by chain security profile (PQ)") ErrBlake2FForbidden = errors.New("blake2F forbidden by chain security profile (PQ)") ErrBn256Forbidden = errors.New("alt_bn128 (BN254) family forbidden by chain security profile (PQ)") ErrBLS12381Forbidden = errors.New("BLS12-381 family forbidden by chain security profile (PQ)") ErrKZGForbidden = errors.New("KZG point evaluation forbidden by chain security profile (PQ)") )
Family errors. Each names the specific primitive family it refuses; dashboards and replay tools attribute violations to the right family.
var ErrClassicalAuthForbidden = errors.New(
"pq: classical authentication forbidden under strict-PQ mode")
ErrClassicalAuthForbidden is the umbrella sentinel returned by every consumer-layer gate when a strict-PQ chain is presented classical authentication material. errors.Is(err, pq.ErrClassicalAuthForbidden) works across luxfi/warp, luxfi/zap, lux/dex, luxfi/evm, lux/fhe — audit pipelines grep ONE identifier across every refusal site in the system.
Per-family precompile errors (ErrEcrecoverForbidden, etc.) live alongside this sentinel in refuse.go; they fire INSIDE a contract execution, this one fires at the chain-level authentication boundary (envelope / order / handshake / tx pool).
Functions ¶
func RequireMode ¶ added in v1.0.3
func RequireMode(evidence PQEvidencer, verify Verify) error
RequireMode is the strict-PQ-only variant: refuses if no PQ evidence is attached regardless of mode. Use this when the CALLER has already decided "I am a strict-PQ consumer, refuse without evidence." Equivalent to:
ValidateMode(ModeStrictPQ, evidence, verify)
Exists as a separate name so call sites that mean "strict-PQ only, no hybrid fallback" are grep-able.
func ValidateMode ¶ added in v1.0.3
func ValidateMode(mode Mode, evidence PQEvidencer, verify Verify) error
ValidateMode is the canonical strict-PQ admission gate. One function dispatches the entire mode policy:
ModeClassical: returns nil (PQ evidence ignored).
ModeHybrid: evidence present → validate via the supplied Verify; evidence absent → return nil (caller logs stale-PQ warning; classical verification path remains the trust root).
ModeStrictPQ: evidence absent → ErrClassicalAuthForbidden; evidence present → validate via the supplied Verify.
verify may be nil — the gate still enforces the "evidence present under strict-PQ" invariant but skips the verification call. Useful for callers that want the gate to run BEFORE the expensive verification work (e.g. a quick reject of envelopes missing MLDSACertSet at the receive boundary; full verification happens later).
evidence may be nil — equivalent to "no PQ material attached" (HasPQEvidence returns false implicitly).
Types ¶
type Mode ¶ added in v1.0.2
type Mode int
Mode is the chain-wide strict-PQ posture. A chain pins exactly one Mode at genesis and never flips it at runtime without a hard fork.
ModeClassical: BLS Beam / ECDSA tx sigs / secp256k1 SignedOrder trusted as auth root. MLDSACertSet / SignedOrderPQ ignored even if present.
ModeHybrid: validates MLDSACertSet / SignedOrderPQ when present, falls back to classical with a stale-PQ warning when absent. Safe migration middle — operator turns ON PQ validation today and turns OFF classical trust later.
ModeStrictPQ: REFUSES every classical authentication root. MLDSACertSet REQUIRED on Warp envelopes; SignedOrderPQ REQUIRED on DEX orders; MLDSATxType REQUIRED on EVM tx-pool admission; ML-DSA-65 channel binding REQUIRED on ZAP connections; PN9QP27_STD128Q params REQUIRED on FHE. Canonical Liquid default; strict Lux + Zoo profile.
const ( // ModeClassical is the default for legacy chains with no // ML-DSA validator material yet generated. ModeClassical Mode = iota // ModeHybrid validates PQ material when present, accepts // classical-only with a stale-PQ warning. ModeHybrid // ModeStrictPQ refuses every classical authentication root. ModeStrictPQ )
func ModeFromPQFlag ¶ added in v1.0.2
ModeFromPQFlag lifts a chain-config "pq" boolean (the same flag liquidity/operator writes into /data/configs/chains/<id>/config.json) to a Mode. true → ModeStrictPQ; false → ModeClassical.
Intentionally binary: a chain that wants strict-PQ shouldn't have a fallback path opened by a future operator turning the same flag from true → "hybrid". Strict-PQ is a one-way door. Operators that want hybrid pin the profile via ModeFromString using the explicit "hybrid" string.
func ModeFromString ¶ added in v1.0.2
ModeFromString parses an operator-supplied profile string. Refuses unknown values rather than defaulting; the gate at every layer assumes the mode is well-known.
func (Mode) IsPQAware ¶ added in v1.0.2
IsPQAware reports whether this mode VALIDATES PQ material when the peer presents it. Both ModeHybrid and ModeStrictPQ return true; ModeClassical ignores PQ material even when present.
func (Mode) IsPostQuantum ¶ added in v1.0.2
IsPostQuantum reports whether this mode REFUSES classical-only authentication. Only ModeStrictPQ returns true; hybrid is PQ- AWARE (validates PQ when present) but not PQ-only.
func (Mode) Profile ¶ added in v1.0.2
Profile returns the EVM-precompile-level Profile that this Mode installs. ModeStrictPQ → Strict() (every classical primitive refused at the precompile boundary); ModeClassical + ModeHybrid → Permissive() (every primitive admitted). Hybrid validates PQ authentication at higher layers (envelope / order / handshake) but doesn't refuse classical primitives inside contracts.
type Op ¶
type Op uint8
Op names a classical cryptographic primitive a profile may refuse. Op values are categorical at the precompile level: Byzantium and Istanbul variants of the same operation report the same Op.
Stable identifiers. Append-only.
const ( OpUnknown Op = iota // Asymmetric signatures. OpEcrecover // ecrecover (0x01) OpP256Verify // p256Verify (0x100, RIP-7212) // Hash / compression. OpSHA256 // 0x02 OpRIPEMD160 // 0x03 OpBlake2F // 0x09 (Blake2b compression — not BLAKE3) // alt_bn128 (BN254). OpBn256Add // 0x06 OpBn256ScalarMul // 0x07 OpBn256Pairing // 0x08 // BLS12-381 (EIP-2537). OpBLS12381G1Add // 0x0b OpBLS12381G1MSM // 0x0c OpBLS12381G2Add // 0x0d OpBLS12381G2MSM // 0x0e OpBLS12381Pairing // 0x0f OpBLS12381MapG1 // 0x10 OpBLS12381MapG2 // 0x11 // Polynomial commitment. OpKZGPointEval // 0x0a (Cancun) )
The complete set of recognised operations.
type PQEvidencer ¶ added in v1.0.3
type PQEvidencer interface {
HasPQEvidence() bool
}
PQEvidencer is the per-input contract: does the input carry the post-quantum authentication material the gate needs?
- warp.EnvelopeV2 → HasPQEvidence = HasMLDSACertSet()
- zap.Attestation → HasPQEvidence = att != nil && len(Sig) > 0
- dex.SignedOrderPQ → HasPQEvidence = true (the type itself is the evidence)
- dex.SignedOrder → HasPQEvidence = false (classical, no PQ evidence)
- lqd tx (MLDSATxType) → HasPQEvidence = tx.Type() == MLDSATxType
Nil-safe: the gate checks for a nil PQEvidencer before calling HasPQEvidence, so consumers can pass nil to mean "no evidence attached at all".
type Profile ¶
type Profile struct {
// Asymmetric signatures.
ForbidEcrecover bool // ecrecover at 0x01 (secp256k1 recovery)
ForbidP256Verify bool // p256Verify at 0x100 (RIP-7212, secp256r1)
// Non-SHA3 hash / compression precompiles.
ForbidSHA256 bool // 0x02
ForbidRIPEMD160 bool // 0x03
ForbidBlake2F bool // 0x09 (Blake2b compression — not BLAKE3)
// Pairing-friendly curves, per family.
ForbidBn256 bool // alt_bn128 at 0x06–0x08 (BN254)
ForbidBLS12381 bool // EIP-2537 at 0x0b–0x11
// Polynomial commitment.
ForbidKZG bool // kzgPointEvaluation at 0x0a (Cancun)
}
Profile selects which classical operations the strict-PQ boundary admits. A small immutable value; safe to copy and to publish in block headers via Profile.Hash.
Each Forbid* field names a cryptographic primitive family — not an abstract category. A chain operator typically sets every field at once via Strict; a nil profile means "admit every operation".
Flag layout matches the EVM precompile addresses one-to-one so a node binary can install a profile, the EVM can refuse a precompile, and an observer can read Profile.Hash from a block header — all describing the same eight booleans.
func DecodeProfile ¶
DecodeProfile reconstructs a profile from its canonical encoding. Returns (nil, false) on unknown version or non-zero reserved bytes.
func FromEnv ¶
func FromEnv() *Profile
FromEnv returns Strict when EnvVar is set to a truthy value (case-insensitive) and Permissive otherwise.
func Permissive ¶
func Permissive() *Profile
Permissive returns a profile with every Forbid* flag false. The zero value Profile{} is observationally equivalent and a nil *Profile is the canonical "no profile installed" state — all three admit every operation.
func Strict ¶
func Strict() *Profile
Strict returns the canonical strict-PQ profile: every Forbid* flag is true. Mainnet PQ chains install this.
func (*Profile) Encode ¶
Encode returns the canonical 16-byte encoding of a profile.
byte 0 version (currently 2) byte 1 flags: bit i = the i'th Forbid* field bytes 2..15 reserved, must be zero
New primitive families extend the flags region; renaming or reordering fields requires a version bump.
func (*Profile) Forbids ¶
Forbids reports whether the profile refuses op. A nil profile returns false (classical semantics).
func (*Profile) Hash ¶
Hash returns the SHA3-256 of the canonical encoding. Block producers publish this hash so observers can confirm which profile a block was produced under.
func (*Profile) RefuseUnder ¶ added in v1.0.1
RefuseUnder reports whether p admits op. Returns nil when admissible (including when p is nil — classical semantics) or family-specific error otherwise. RefuseUnder(OpUnknown) always returns nil.
This is the canonical, per-profile gate. Callers should hold a *Profile (typically from chain config) and call this method directly.
type Verify ¶ added in v1.0.3
type Verify func() error
Verify is the per-consumer verification closure. The gate invokes it ONLY after confirming the evidence is present. Each consumer captures whatever inputs the verification needs (transcript hash, pubkey, validator-set membership check) in the closure — the gate doesn't know or care about the shape.
Returning nil = evidence verified. Returning non-nil = the gate propagates the error verbatim.