Files
zeekay 823c7baf09 quasar: decomplect PulsarKeyEra -> KeyEra (value-not-place, one type all lanes)
The compact group-key era was named for a place (Pulsar) when it is a
generic value serving every threshold lane, scheme-qualified. Drop the
Pulsar prefix and generalise the verifier so ONE type + ONE entry point
covers both the Pulsar (FIPS-204 ML-DSA) and Corona (Ring-LWE Ringtail)
lanes. Pure decomplect: same behaviour, value-not-place naming.

- Type:  PulsarKeyEra -> KeyEra  (file pulsar_key_era.go -> key_era.go)
- Field: MLDSAPubKey []byte -> GroupPubKey []byte  (scheme-interpreted via
  SchemeID; not ML-DSA-specific). The unrelated Validator.MLDSAPubKey
  (*mldsa.PublicKey, a per-validator identity key) is left untouched.
- Registry: PulsarKeyEraRegistry -> KeyEraRegistry (lane-agnostic; holds
  Pulsar and Corona eras alike), NewPulsarKeyEraRegistry -> NewKeyEraRegistry.

Generalised verifier dispatch:
- VerifyThresholdLeg(ev, M, era) is the ONE compact-threshold verify entry
  point. It resolves the era's lane through the suite registry
  (era.eraSuite, Pulsar|Corona only) and routes the group-signature check
  to that lane's boring verifier: pulsarwire.VerifyBytes for Pulsar,
  coronaThreshold.Verify for Corona (via new verifyCoronaGroupKeyLeg, which
  decodes the era's wire-byte group key and reuses verifyCoronaLeg). Both
  the era scheme and the evidence suite are resolved through the registry
  and must name the SAME lane + param set, so no suite string can reach the
  wrong verifier (reuses LookupSuite/resolveSuiteForLane lane safety).
- VerifyPulsar is retained as a thin Pulsar-suite wrapper that refuses any
  non-Pulsar era at the door, then defers to VerifyThresholdLeg.

Tests: existing boring-verifier + suite-dispatch-safety (VerifyPulsar) and
dualpq tests hold unchanged; KeyEra registry test now proves lane-agnostic
acceptance (corona era registers, non-threshold Beam refused); new
TestCompact_VerifyThresholdLeg_CoronaLane proves a corona-suite era
verifies via the corona path through the same KeyEra/dispatch with a real
multi-node Ring-LWE signature, and that a pulsar suite can never reach the
corona verifier.

GOWORK=off go build ./... green; go test ./protocol/quasar/ green.
2026-06-27 12:38:58 -07:00

701 lines
30 KiB
Go

// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
// compact_cert_test.go — the COMPACT-CERTIFICATE evidence layer proof corpus.
//
// What this file proves, with REAL crypto (no fakes):
//
// 1. A STRICT_QUASAR cert (Beam ∧ Pulsar ∧ Corona) over ONE canonical M
// verifies — real BLS aggregate, real FIPS-204 ML-DSA, real multi-node
// Ring-LWE threshold.
// 2. Each named posture enforces its required legs / permitted modes:
// BLS_FAST = Beam only; HYBRID accepts Pulsar OR P3Q; RECOVERY accepts P3Q
// and REFUSES the Pulsar threshold mode; STRICT refuses the P3Q mode.
// 3. COMPACTNESS: the Beam/Pulsar/Corona legs are O(1) in committee size — a
// cert for 1000 validators is the SAME size as for 4, and orders of
// magnitude smaller than the O(N) naive "1000 raw ML-DSA certs" object.
// 4. Dispatch safety + boring VerifyPulsar: wrong-era, suite-mismatch,
// cross-lane suite, unknown suite and a corrupt signature all reject with
// distinct typed errors; no suite string reaches the wrong verifier.
// 5. The P3Q fallback path verifies a rollup root (Direct) over a REAL
// validator-set-bound MLDSACertSet (a WeightedQuorumCert), and rejects a
// tampered root, a corrupt cert set, a sub-threshold floor, an un-opted-in
// classical proof, and an unaudited succinct backend.
package quasar
import (
"errors"
"testing"
"github.com/luxfi/crypto/bls"
)
// ----------------------------------------------------------------------------
// Shared compact-cert builders.
// ----------------------------------------------------------------------------
const compactThreshold = uint64(100)
// compactHeader builds a fixed cert header for a posture with the given signer
// root, and returns the header + validator-set root + the canonical message M
// every compact leg signs.
func compactHeader(policy *QuasarEvidencePolicy, signerRoot [32]byte) (*ConsensusCert, [48]byte, []byte) {
var vsetRoot [48]byte
for i := range vsetRoot {
vsetRoot[i] = 0x33
}
var bh [32]byte
for i := range bh {
bh[i] = 0xC0
}
cert := &ConsensusCert{
Version: consensusCertVersion,
Profile: 1,
ChainID: 9,
Epoch: 9,
Height: 9,
Round: 9,
BlockHash: bh,
ValidatorSetRoot: vsetRoot,
PolicyID: policy.EvidencePolicyID(),
RequiredLegsRoot: HashRequiredLegs(policy.RequiredLegs()),
SignerRoot: signerRoot,
KeyEraID: 7,
}
return cert, vsetRoot, consensusCertMessage(cert, cert.RequiredLegsRoot)
}
// fixedSignerRoot is the threshold-leg signer root (the threshold accountability
// echoes it; it is bound into M).
func fixedSignerRoot() [32]byte {
var s [32]byte
for i := range s {
s[i] = 0x5A
}
return s
}
// beamEvidence builds a Beam (BLS aggregate) LegEvidence.
func beamEvidence(aggSig []byte) LegEvidence {
return LegEvidence{
Leg: LegSpec{Kind: LegClassical, ParamSetID: blsParam},
Mode: EvidenceClassicalAggregate,
Payload: encodeClassicalAggregatePayload(&ClassicalAggregatePayload{
Scheme: ClassicalSchemeBLS12381, Payload: aggSig,
}),
}
}
// pulsarThresholdEvidence builds a compact Pulsar (FIPS-204 ML-DSA threshold)
// LegEvidence with accountability bound to signerRoot.
func pulsarThresholdEvidence(pulsarSig []byte, signerRoot [32]byte) LegEvidence {
return LegEvidence{
Leg: LegSpec{Kind: LegPulsarMLDSA, ParamSetID: pqParam},
Mode: EvidenceThresholdSig,
Payload: encodeThresholdSigPayload(&ThresholdSigPayload{
Signature: pulsarSig,
Accountability: &ThresholdAccountability{SignerRoot: signerRoot, AggregateWeight: 150},
}),
}
}
// coronaThresholdEvidence builds a compact Corona (Ring-LWE threshold)
// LegEvidence.
func coronaThresholdEvidence(coronaSigBytes []byte, signerRoot [32]byte) LegEvidence {
return LegEvidence{
Leg: LegSpec{Kind: LegCoronaLattice, ParamSetID: pqParam},
Mode: EvidenceThresholdSig,
Payload: encodeThresholdSigPayload(&ThresholdSigPayload{
Signature: coronaSigBytes,
Accountability: &ThresholdAccountability{SignerRoot: signerRoot, AggregateWeight: 150},
}),
}
}
// aggN builds a real BLS aggregate over n signers of msg, returning the
// aggregate pubkey (compressed) and aggregate signature bytes. Aggregate SIZE
// is independent of n — the basis of the Beam leg's O(1) compactness.
func aggN(t *testing.T, msg []byte, n int) (aggPub, aggSig []byte) {
t.Helper()
pubs := make([]*bls.PublicKey, 0, n)
sigs := make([]*bls.Signature, 0, n)
for i := 0; i < n; i++ {
sk, err := bls.NewSecretKey()
if err != nil {
t.Fatalf("bls keygen: %v", err)
}
sig, err := sk.Sign(msg)
if err != nil {
t.Fatalf("bls sign: %v", err)
}
pubs = append(pubs, sk.PublicKey())
sigs = append(sigs, sig)
}
apk, err := bls.AggregatePublicKeys(pubs)
if err != nil {
t.Fatalf("aggregate pubkeys: %v", err)
}
asig, err := bls.AggregateSignatures(sigs)
if err != nil {
t.Fatalf("aggregate sigs: %v", err)
}
return bls.PublicKeyToCompressedBytes(apk), bls.SignatureToBytes(asig)
}
// p3qSuiteDirect is the production P3Q ML-DSA-65 Direct suite id.
const p3qSuiteDirect = "Lux-P3Q-MLDSA65-Direct-v1"
// p3qDirectCert builds a {Beam, P3Q-Direct} cert for the given posture. The P3Q
// leg wraps a REAL validator-set-bound WeightedQuorumCert (fourMLDSA, Σweight
// 100, threshold 100) — the MLDSACertSet — in a rollup-root commitment. Returns
// the store, validators (carrying the weighted config/envelope the inner verify
// needs), the cert, M, and the inner WeightedQuorumCert bytes.
func p3qDirectCert(t *testing.T, policy *QuasarEvidencePolicy) (*envStore, *envValidators, *ConsensusCert, []byte, []byte) {
t.Helper()
sc := fourMLDSA(t)
innerWire, err := sc.cert.MarshalBinary()
if err != nil {
t.Fatalf("marshal inner weighted cert: %v", err)
}
cert := &ConsensusCert{
Version: consensusCertVersion,
Profile: 1,
ChainID: sc.cert.ChainID,
Epoch: sc.cert.Epoch,
Height: sc.cert.Height,
Round: sc.cert.Round,
BlockHash: sc.cert.ValueHash,
ValidatorSetRoot: sc.cert.ValidatorSetRoot,
PolicyID: policy.EvidencePolicyID(),
RequiredLegsRoot: HashRequiredLegs(policy.RequiredLegs()),
SignerRoot: fixedSignerRoot(),
KeyEraID: 7,
AggregateWeight: sc.cert.AggregateWeight,
}
msg := consensusCertMessage(cert, cert.RequiredLegsRoot)
aggPub, aggSig := aggN(t, msg, 3)
p3q := LegEvidence{
Leg: LegSpec{Kind: LegPulsarMLDSA, ParamSetID: pqParam},
Mode: EvidenceP3QRollup,
Payload: encodeP3QRollupPayload(&P3QRollupPayload{
SuiteID: p3qSuiteDirect,
RollupRoot: P3QRollupRoot(p3qSuiteDirect, innerWire),
CertSet: innerWire,
}),
}
cert.Evidence = []LegEvidence{beamEvidence(aggSig), p3q}
store := &envStore{policy: policy}
validators := &envValidators{
root: sc.cert.ValidatorSetRoot, epoch: sc.env.Epoch, cfg: sc.cfg, env: sc.env,
classKeys: map[ClassicalScheme][]byte{ClassicalSchemeBLS12381: aggPub},
}
return store, validators, cert, msg, innerWire
}
// ----------------------------------------------------------------------------
// 1. STRICT_QUASAR — Beam ∧ Pulsar ∧ Corona over one M.
// ----------------------------------------------------------------------------
func TestCompact_StrictQuasar_AllThreeLegsVerify(t *testing.T) {
if testing.Short() {
t.Skip("skipping STRICT_QUASAR Corona-DKG integration under -short")
}
policy := NewQuasarEvidencePolicy(PolicyStrictQuasar, pqParam, compactThreshold)
store := &envStore{policy: policy}
cert, vsetRoot, msg := compactHeader(policy, fixedSignerRoot())
aggPub, aggSig := aggN(t, msg, 4)
pulsarSig, pulsarGK := signPulsarLegFIPS204(t, msg)
coronaSig, coronaGK, _ := signCoronaLegMultiNode(t, dualPQThreshold, dualPQThreshold, dualPQN, msg)
cert.Evidence = []LegEvidence{
beamEvidence(aggSig),
pulsarThresholdEvidence(pulsarSig, cert.SignerRoot),
coronaThresholdEvidence(EncodeCoronaSig(coronaSig), cert.SignerRoot),
}
validators := &envValidators{
root: vsetRoot, epoch: 9,
classKeys: map[ClassicalScheme][]byte{ClassicalSchemeBLS12381: aggPub},
pulsarKey: pulsarGK, coronaKey: coronaGK,
}
if err := VerifyConsensusCert(store, validators, cert); err != nil {
t.Fatalf("STRICT_QUASAR (Beam ∧ Pulsar ∧ Corona) cert rejected: %v", err)
}
// Missing Corona ⇒ rejected (AND-mode).
noCorona := *cert
noCorona.Evidence = cert.Evidence[:2]
if err := VerifyConsensusCert(store, validators, &noCorona); err == nil {
t.Fatal("STRICT_QUASAR accepted a cert missing the Corona leg")
}
}
// ----------------------------------------------------------------------------
// 2. Policy-mode required-legs enforcement.
// ----------------------------------------------------------------------------
func TestCompact_PolicyModes_RequiredLegsEnforced(t *testing.T) {
// --- BLS_FAST: Beam-only verifies; nothing else required. ---
t.Run("BLS_FAST_BeamOnly", func(t *testing.T) {
policy := NewQuasarEvidencePolicy(PolicyBLSFast, pqParam, compactThreshold)
store := &envStore{policy: policy}
cert, vsetRoot, msg := compactHeader(policy, fixedSignerRoot())
aggPub, aggSig := aggN(t, msg, 3)
cert.Evidence = []LegEvidence{beamEvidence(aggSig)}
validators := &envValidators{root: vsetRoot, epoch: 9, classKeys: map[ClassicalScheme][]byte{ClassicalSchemeBLS12381: aggPub}}
if err := VerifyConsensusCert(store, validators, cert); err != nil {
t.Fatalf("BLS_FAST Beam-only rejected: %v", err)
}
})
// --- HYBRID accepts the Pulsar threshold mode. ---
t.Run("HYBRID_AcceptsPulsar", func(t *testing.T) {
policy := NewQuasarEvidencePolicy(PolicyHybridPQCheckpoint, pqParam, compactThreshold)
store := &envStore{policy: policy}
cert, vsetRoot, msg := compactHeader(policy, fixedSignerRoot())
aggPub, aggSig := aggN(t, msg, 3)
pulsarSig, pulsarGK := signPulsarLegFIPS204(t, msg)
cert.Evidence = []LegEvidence{beamEvidence(aggSig), pulsarThresholdEvidence(pulsarSig, cert.SignerRoot)}
validators := &envValidators{root: vsetRoot, epoch: 9, classKeys: map[ClassicalScheme][]byte{ClassicalSchemeBLS12381: aggPub}, pulsarKey: pulsarGK}
if err := VerifyConsensusCert(store, validators, cert); err != nil {
t.Fatalf("HYBRID Beam+Pulsar rejected: %v", err)
}
})
// --- HYBRID accepts the P3Q rollup mode for the SAME PQ leg (the OR). ---
t.Run("HYBRID_AcceptsP3Q", func(t *testing.T) {
policy := NewQuasarEvidencePolicy(PolicyHybridPQCheckpoint, pqParam, compactThreshold)
store, validators, cert, _, _ := p3qDirectCert(t, policy)
if err := VerifyConsensusCert(store, validators, cert); err != nil {
t.Fatalf("HYBRID Beam+P3Q rejected: %v", err)
}
})
// --- RECOVERY accepts P3Q but REFUSES the Pulsar threshold mode. ---
t.Run("RECOVERY_RefusesPulsarMode", func(t *testing.T) {
policy := NewQuasarEvidencePolicy(PolicyRecoveryMode, pqParam, compactThreshold)
store := &envStore{policy: policy}
cert, vsetRoot, msg := compactHeader(policy, fixedSignerRoot())
aggPub, aggSig := aggN(t, msg, 3)
pulsarSig, pulsarGK := signPulsarLegFIPS204(t, msg)
// Present a Pulsar threshold sig where the posture allows ONLY P3Q.
cert.Evidence = []LegEvidence{beamEvidence(aggSig), pulsarThresholdEvidence(pulsarSig, cert.SignerRoot)}
validators := &envValidators{root: vsetRoot, epoch: 9, classKeys: map[ClassicalScheme][]byte{ClassicalSchemeBLS12381: aggPub}, pulsarKey: pulsarGK}
if err := VerifyConsensusCert(store, validators, cert); !errors.Is(err, ErrDisallowedEvidenceMode) {
t.Fatalf("RECOVERY accepted a Pulsar threshold leg: err = %v, want ErrDisallowedEvidenceMode", err)
}
})
// --- STRICT REFUSES the P3Q mode for the PQ leg (wants the compact sig). ---
t.Run("STRICT_RefusesP3QMode", func(t *testing.T) {
policy := NewQuasarEvidencePolicy(PolicyStrictQuasar, pqParam, compactThreshold)
store, validators, cert, _, _ := p3qDirectCert(t, policy)
// p3qDirectCert gives {Beam, P3Q}; STRICT forbids the P3Q mode AND
// additionally requires Corona — either way it must reject.
if err := VerifyConsensusCert(store, validators, cert); err == nil {
t.Fatal("STRICT accepted a P3Q PQ leg")
}
})
}
// ----------------------------------------------------------------------------
// 3. COMPACTNESS — O(1) in committee size, not O(N).
// ----------------------------------------------------------------------------
func TestCompact_O1NotON_For1000Validators(t *testing.T) {
msg := []byte("compact-size canonical finality message for the O(1) proof")
// Beam aggregate size is INVARIANT under committee growth: aggregating 4 vs
// 64 signers yields the SAME aggregate-signature byte length. This is the
// structural basis of the Beam leg's O(1) compactness.
_, agg4 := aggN(t, msg, 4)
_, agg64 := aggN(t, msg, 64)
if len(agg4) != len(agg64) {
t.Fatalf("Beam aggregate not O(1): |agg(4)|=%d |agg(64)|=%d", len(agg4), len(agg64))
}
// One compact Pulsar (ML-DSA-65 threshold) signature — the on-chain object
// for the WHOLE committee, regardless of size.
pulsarSig, _ := signPulsarLegFIPS204(t, msg)
oneSig := len(pulsarSig)
if oneSig == 0 {
t.Fatal("empty pulsar signature")
}
// The compact checkpoint footprint (Beam + Pulsar evidence payloads) does
// NOT reference committee size — build it once; it is identical "for" any N.
beam := beamEvidence(agg4)
pulsar := pulsarThresholdEvidence(pulsarSig, fixedSignerRoot())
compact := len(beam.Payload) + len(pulsar.Payload)
// The NAIVE anti-pattern (what we MUST NOT store): 1000 raw per-validator
// ML-DSA certs. Grows linearly in committee size.
const committee = 1000
naive := committee * oneSig
if naive/compact < 100 {
t.Fatalf("compact cert is not >=100x smaller than the naive O(N) object: compact=%d naive=%d ratio=%d",
compact, naive, naive/compact)
}
t.Logf("compact checkpoint footprint (Beam+Pulsar) = %d bytes (O(1) in committee size)", compact)
t.Logf("naive 1000-raw-ML-DSA-cert object = %d bytes (O(N))", naive)
t.Logf("compression ratio at N=1000 = %dx", naive/compact)
// Explicit O(1): the compact footprint computed "for" N=4 and "for" N=1000
// is byte-identical, because no compact leg carries per-validator data.
footprintFor := func(_ int) int { return len(beam.Payload) + len(pulsar.Payload) }
if footprintFor(4) != footprintFor(committee) {
t.Fatal("compact footprint depends on committee size — not O(1)")
}
}
// ----------------------------------------------------------------------------
// 4. The deliberately boring VerifyPulsar + dispatch safety.
// ----------------------------------------------------------------------------
func TestCompact_VerifyPulsar_BoringAndDispatchSafe(t *testing.T) {
var signerSet [48]byte
for i := range signerSet {
signerSet[i] = 0x21
}
M := QuasarFinalityMessage(QuasarFinalityParams{
ChainID: 9, Epoch: 9, Height: 9, Round: 9, KeyEraID: 7, EvidencePolicyID: 1,
SignerSetID: signerSet, Profile: 1,
})
pulsarSig, pulsarGK := signPulsarLegFIPS204(t, M)
era := KeyEra{
ChainID: 9, SignerSetID: signerSet, KeyEraID: 7, Generation: 1,
PChainHeight: 1000, GroupPubKey: pulsarGK, Threshold: 100,
SchemeID: "Lux-Pulsar-TALUS-MLDSA65", KeygenMode: "talus-mpc",
}
good := PulsarEvidence{SuiteID: "Lux-Pulsar-TALUS-MLDSA65", KeyEraID: 7, Generation: 1, SignerSetID: signerSet, Signature: pulsarSig}
if err := VerifyPulsar(good, M, era); err != nil {
t.Fatalf("boring VerifyPulsar rejected a valid era signature: %v", err)
}
// reject is a one-line negative assertion: mutate a fresh copy of `good`,
// expect a specific typed error.
reject := func(name string, mutate func(*PulsarEvidence), want error) {
t.Helper()
bad := good
mutate(&bad)
if err := VerifyPulsar(bad, M, era); !errors.Is(err, want) {
t.Fatalf("%s: err = %v, want %v", name, err, want)
}
}
reject("wrong KeyEraID", func(e *PulsarEvidence) { e.KeyEraID = 8 }, ErrWrongEra)
reject("wrong Generation", func(e *PulsarEvidence) { e.Generation = 2 }, ErrWrongEra)
reject("wrong SignerSetID", func(e *PulsarEvidence) { e.SignerSetID[0] ^= 0xFF }, ErrWrongEra)
// suite mismatch: a valid Pulsar suite, but not the era's scheme.
reject("suite != era scheme", func(e *PulsarEvidence) { e.SuiteID = "Lux-Pulsar-TALUS-MLDSA87" }, ErrSuiteMismatch)
// DISPATCH SAFETY: a Corona suite id can NEVER reach the Pulsar verifier.
reject("corona suite at pulsar verifier", func(e *PulsarEvidence) { e.SuiteID = "Lux-Corona-Ringtail-L3-v1" }, ErrSuiteLaneMismatch)
reject("unknown suite", func(e *PulsarEvidence) { e.SuiteID = "Lux-Nonsense-vX" }, ErrUnknownSuite)
reject("corrupt signature", func(e *PulsarEvidence) {
e.Signature = append([]byte(nil), pulsarSig...)
e.Signature[len(e.Signature)/2] ^= 0xFF
}, ErrBadSignature)
// wrong M (replay to a different finality position) — the sig no longer verifies.
otherM := QuasarFinalityMessage(QuasarFinalityParams{ChainID: 9, Epoch: 9, Height: 10, Round: 9, KeyEraID: 7, SignerSetID: signerSet, Profile: 1})
if !errors.Is(VerifyPulsar(good, otherM, era), ErrBadSignature) {
t.Fatal("a signature for one M verified under a different M (replay)")
}
}
// ----------------------------------------------------------------------------
// 4a. ONE KeyEra + ONE VerifyThresholdLeg entry point serves the Corona lane.
// A corona-suite era verifies through the SAME type + dispatch as Pulsar —
// value-not-place: the lane is selected by the era's scheme, not its type.
// ----------------------------------------------------------------------------
func TestCompact_VerifyThresholdLeg_CoronaLane(t *testing.T) {
var signerSet [48]byte
for i := range signerSet {
signerSet[i] = 0x33
}
M := QuasarFinalityMessage(QuasarFinalityParams{
ChainID: 11, Epoch: 4, Height: 4, Round: 4, KeyEraID: 2, EvidencePolicyID: 1,
SignerSetID: signerSet, Profile: 1,
})
// A REAL multi-node Corona (Ring-LWE, t-of-n) threshold signature + the
// matching group key — the dual-PQ corona helper, same as the dualpq test.
coronaSig, coronaGK, _ := signCoronaLegMultiNode(t, dualPQThreshold, dualPQThreshold, dualPQN, M)
gkBytes, err := coronaGK.MarshalBinary()
if err != nil {
t.Fatalf("corona group key MarshalBinary: %v", err)
}
const coronaSuite = "Lux-Corona-Ringtail-L3-v1"
era := KeyEra{
ChainID: 11, SignerSetID: signerSet, KeyEraID: 2, Generation: 0,
PChainHeight: 500, GroupPubKey: gkBytes, Threshold: 100,
SchemeID: coronaSuite, KeygenMode: "talus-mpc",
}
good := PulsarEvidence{
SuiteID: coronaSuite, KeyEraID: 2, Generation: 0,
SignerSetID: signerSet, Signature: EncodeCoronaSig(coronaSig),
}
// THE PROOF: the SAME KeyEra type and the SAME VerifyThresholdLeg entry
// point route a Corona-suite era through the Corona (Ring-LWE) verifier —
// no CoronaKeyEra type, no second verify entry point.
if err := VerifyThresholdLeg(good, M, era); err != nil {
t.Fatalf("corona-lane era rejected via the unified dispatch: %v", err)
}
// The Pulsar wrapper must REFUSE a Corona era at the door (lane gate): a
// Corona scheme can never reach the Pulsar verify path.
if err := VerifyPulsar(good, M, era); !errors.Is(err, ErrSuiteLaneMismatch) {
t.Fatalf("VerifyPulsar accepted a corona era: err = %v, want ErrSuiteLaneMismatch", err)
}
// Dispatch safety + boring rejects, each a distinct typed error.
reject := func(name string, mutate func(*PulsarEvidence), want error) {
t.Helper()
bad := good
mutate(&bad)
if err := VerifyThresholdLeg(bad, M, era); !errors.Is(err, want) {
t.Fatalf("%s: err = %v, want %v", name, err, want)
}
}
// A Pulsar suite id can NEVER reach the Corona verifier.
reject("pulsar suite at corona era", func(e *PulsarEvidence) { e.SuiteID = "Lux-Pulsar-TALUS-MLDSA65" }, ErrSuiteLaneMismatch)
// A different (valid) Corona suite that is not the era's scheme.
reject("suite != era scheme", func(e *PulsarEvidence) { e.SuiteID = "Lux-Corona-Ringtail-L5-v1" }, ErrSuiteMismatch)
reject("unknown suite", func(e *PulsarEvidence) { e.SuiteID = "Lux-Nonsense-vX" }, ErrUnknownSuite)
reject("wrong KeyEraID", func(e *PulsarEvidence) { e.KeyEraID = 9 }, ErrWrongEra)
reject("wrong SignerSetID", func(e *PulsarEvidence) { e.SignerSetID[0] ^= 0xFF }, ErrWrongEra)
reject("corrupt corona signature", func(e *PulsarEvidence) {
e.Signature = append([]byte(nil), good.Signature...)
e.Signature[len(e.Signature)/2] ^= 0xFF
}, ErrBadSignature)
// Wrong M (replay to a different finality position) — the corona signature
// no longer verifies under the era group key.
otherM := QuasarFinalityMessage(QuasarFinalityParams{ChainID: 11, Epoch: 4, Height: 5, Round: 4, KeyEraID: 2, SignerSetID: signerSet, Profile: 1})
if !errors.Is(VerifyThresholdLeg(good, otherM, era), ErrBadSignature) {
t.Fatal("a corona signature for one M verified under a different M (replay)")
}
}
// ----------------------------------------------------------------------------
// 4b. Suite registry — exhaustive dispatch-safety invariant.
// ----------------------------------------------------------------------------
func TestCompact_SuiteRegistry_DispatchSafety(t *testing.T) {
// Every registered suite resolves to EXACTLY its lane's (LegKind, Mode).
for _, s := range productionSuites {
got, ok := LookupSuite(s.ID)
if !ok {
t.Fatalf("suite %q not resolvable", s.ID)
}
lane, ok := laneByKind[got.Kind]
if !ok {
t.Fatalf("suite %q names unknown kind %q", s.ID, got.Kind)
}
if got.Leg != lane.leg || got.Mode != lane.mode {
t.Fatalf("suite %q maps to (%s,%s), lane is (%s,%s)", s.ID, got.Leg, got.Mode, lane.leg, lane.mode)
}
}
// Cross-lane resolution is refused for every (suite, foreign-lane) pair.
lanes := []EvidenceKind{EvidenceBeamBLS, EvidencePulsarThresholdMLDSA, EvidenceCoronaRingtail, EvidenceP3QMLDSARollup}
for _, s := range productionSuites {
for _, want := range lanes {
_, err := resolveSuiteForLane(s.ID, want, 0)
if want == s.Kind {
if err != nil {
t.Fatalf("suite %q refused for its OWN lane %q: %v", s.ID, want, err)
}
} else if !errors.Is(err, ErrSuiteLaneMismatch) {
t.Fatalf("suite %q (lane %q) NOT refused for foreign lane %q: %v", s.ID, s.Kind, want, err)
}
}
}
// Unknown suite and param mismatch reject.
if _, err := resolveSuiteForLane("does-not-exist", EvidencePulsarThresholdMLDSA, 0); !errors.Is(err, ErrUnknownSuite) {
t.Fatalf("unknown suite: %v", err)
}
if _, err := resolveSuiteForLane("Lux-Pulsar-TALUS-MLDSA44", EvidencePulsarThresholdMLDSA, uint8(QuorumSchemeMLDSA65)); !errors.Is(err, ErrSuiteParamMismatch) {
t.Fatalf("param mismatch not caught: %v", err)
}
}
// ----------------------------------------------------------------------------
// 5. P3Q rollup fallback path.
// ----------------------------------------------------------------------------
func TestCompact_P3QRollup_DirectPath(t *testing.T) {
policy := NewQuasarEvidencePolicy(PolicyRecoveryMode, pqParam, compactThreshold)
store, validators, cert, msg, innerWire := p3qDirectCert(t, policy)
// Happy path: RECOVERY = Beam ∧ P3Q verifies end-to-end over a real
// validator-set-bound MLDSACertSet.
if err := VerifyConsensusCert(store, validators, cert); err != nil {
t.Fatalf("RECOVERY Beam+P3Q rejected: %v", err)
}
p3qLeg := cert.Evidence[1] // [Beam, P3Q]
if err := VerifyP3QRollupLeg(policy, validators, cert, msg, p3qLeg); err != nil {
t.Fatalf("valid P3Q rollup rejected: %v", err)
}
// Tampered rollup root — commitment binding fails before any inner verify.
badRootPayload := &P3QRollupPayload{SuiteID: p3qSuiteDirect, CertSet: innerWire}
badRootPayload.RollupRoot = P3QRollupRoot(p3qSuiteDirect, innerWire)
badRootPayload.RollupRoot[0] ^= 0xFF
badRoot := LegEvidence{Leg: p3qLeg.Leg, Mode: EvidenceP3QRollup, Payload: encodeP3QRollupPayload(badRootPayload)}
if err := VerifyP3QRollupLeg(policy, validators, cert, msg, badRoot); !errors.Is(err, ErrP3QRootMismatch) {
t.Fatalf("tampered root: err = %v, want ErrP3QRootMismatch", err)
}
// Corrupt the MLDSACertSet (a signature byte). The rollup root is recomputed
// over the corrupted bytes (so the commitment passes) — the inner
// validator-set-bound verify must then reject.
corruptWire := append([]byte(nil), innerWire...)
corruptWire[len(corruptWire)/2] ^= 0xFF
corrupt := LegEvidence{Leg: p3qLeg.Leg, Mode: EvidenceP3QRollup, Payload: encodeP3QRollupPayload(&P3QRollupPayload{
SuiteID: p3qSuiteDirect, RollupRoot: P3QRollupRoot(p3qSuiteDirect, corruptWire), CertSet: corruptWire,
})}
if err := VerifyP3QRollupLeg(policy, validators, cert, msg, corrupt); err == nil {
t.Fatal("corrupt MLDSACertSet accepted")
}
// Sub-threshold floor: a posture whose weight floor (200) exceeds the
// MLDSACertSet's Σweight (100). The inner weighted verify pins the floor and
// rejects — the threshold is enforced THROUGH the P3Q leg.
highPolicy := NewQuasarEvidencePolicy(PolicyRecoveryMode, pqParam, 200)
if err := VerifyP3QRollupLeg(highPolicy, validators, cert, msg, p3qLeg); err == nil {
t.Fatal("P3Q rollup accepted below the threshold floor")
}
}
func TestCompact_P3QRollup_SuccinctGated(t *testing.T) {
policy := NewQuasarEvidencePolicy(PolicyRecoveryMode, pqParam, compactThreshold)
cert, _, msg := compactHeader(policy, fixedSignerRoot())
validators := &envValidators{root: cert.ValidatorSetRoot, epoch: 9}
succinctLeg := func(suiteID string) LegEvidence {
return LegEvidence{
Leg: LegSpec{Kind: LegPulsarMLDSA, ParamSetID: pqParam},
Mode: EvidenceP3QRollup,
Payload: encodeP3QRollupPayload(&P3QRollupPayload{
SuiteID: suiteID,
RollupRoot: P3QRollupRoot(suiteID, []byte("committed-statement")),
Proof: []byte("succinct-proof-bytes"),
}),
}
}
// STARK (PQ-succinct): audit-gated, fails closed.
if err := VerifyP3QRollupLeg(policy, validators, cert, msg, succinctLeg("Lux-P3Q-MLDSA65-STARK-v1")); !errors.Is(err, ErrP3QBackendNotAuditGated) {
t.Fatalf("STARK P3Q: err = %v, want ErrP3QBackendNotAuditGated", err)
}
// Groth16 (classical succinct): refused unless the policy opts in.
groth := succinctLeg("Lux-P3Q-MLDSA65-Groth16-v1")
if err := VerifyP3QRollupLeg(policy, validators, cert, msg, groth); !errors.Is(err, ErrClassicalProofAssumptionRefused) {
t.Fatalf("Groth16 P3Q without opt-in: err = %v, want ErrClassicalProofAssumptionRefused", err)
}
// With explicit opt-in, the classical assumption is accepted but the backend
// is still unaudited ⇒ fail closed (PQ-safe raw data challengeable).
optIn := NewQuasarEvidencePolicy(PolicyRecoveryMode, pqParam, compactThreshold).WithClassicalProofAssumption()
if err := VerifyP3QRollupLeg(optIn, validators, cert, msg, groth); !errors.Is(err, ErrP3QBackendNotAuditGated) {
t.Fatalf("Groth16 P3Q with opt-in: err = %v, want ErrP3QBackendNotAuditGated", err)
}
}
// ----------------------------------------------------------------------------
// 6. KeyEra registry + the one-M property.
// ----------------------------------------------------------------------------
func TestCompact_KeyEraRegistry(t *testing.T) {
reg := NewKeyEraRegistry()
var ss [48]byte
ss[0] = 0x09
M := []byte("era registry message")
_, gk := signPulsarLegFIPS204(t, M)
era := KeyEra{ChainID: 9, SignerSetID: ss, KeyEraID: 1, Generation: 0, GroupPubKey: gk, SchemeID: "Lux-Pulsar-TALUS-MLDSA65"}
if err := reg.Register(era); err != nil {
t.Fatalf("register: %v", err)
}
if err := reg.Register(era); err != nil {
t.Fatalf("idempotent re-register: %v", err)
}
got, err := reg.Lookup(9, ss, 1, 0)
if err != nil {
t.Fatalf("lookup: %v", err)
}
if got.SchemeID != era.SchemeID {
t.Fatal("lookup returned a different era")
}
// Conflicting key under same coordinates rejected.
conflict := era
conflict.GroupPubKey = append([]byte(nil), gk...)
conflict.GroupPubKey[0] ^= 0xFF
if err := reg.Register(conflict); !errors.Is(err, ErrEraConflict) {
t.Fatalf("conflict: err = %v, want ErrEraConflict", err)
}
// Not-found.
if _, err := reg.Lookup(9, ss, 2, 0); !errors.Is(err, ErrEraNotFound) {
t.Fatalf("not-found: err = %v, want ErrEraNotFound", err)
}
// The registry is LANE-AGNOSTIC: a Corona (Ring-LWE) era registers fine —
// KeyEra serves every threshold lane, not just Pulsar. Registration checks
// the lane + a non-empty key; the full Corona group-signature verify is
// proven in TestCompact_VerifyThresholdLeg_CoronaLane.
coronaEra := KeyEra{ChainID: 9, SignerSetID: ss, KeyEraID: 2, Generation: 0, GroupPubKey: []byte("corona-group-key"), SchemeID: "Lux-Corona-Ringtail-L3-v1"}
if err := reg.Register(coronaEra); err != nil {
t.Fatalf("corona era registration refused (registry must be lane-agnostic): %v", err)
}
// A NON-threshold lane (Beam classical aggregate) has no compact group-key
// era and is refused at registration.
bad := era
bad.SchemeID = "Lux-Beam-BLS12381-v1"
if err := reg.Register(bad); !errors.Is(err, ErrSuiteLaneMismatch) {
t.Fatalf("non-threshold era scheme: err = %v, want ErrSuiteLaneMismatch", err)
}
}
// TestCompact_OneCanonicalMessage proves QuasarFinalityMessage and the
// envelope's consensusCertMessage produce byte-identical M for the same tuple —
// all lanes provably sign the SAME M.
func TestCompact_OneCanonicalMessage(t *testing.T) {
policy := NewQuasarEvidencePolicy(PolicyStrictQuasar, pqParam, compactThreshold)
cert, vsetRoot, envMsg := compactHeader(policy, fixedSignerRoot())
typed := QuasarFinalityMessage(QuasarFinalityParams{
ChainID: cert.ChainID,
Epoch: cert.Epoch,
Height: cert.Height,
Round: cert.Round,
BlockID: cert.BlockHash,
StateRoot: cert.StateRoot,
SignerSetID: vsetRoot,
KeyEraID: cert.KeyEraID,
EvidencePolicyID: cert.PolicyID,
RequiredLegsRoot: cert.RequiredLegsRoot,
SignerRoot: cert.SignerRoot,
Profile: cert.Profile,
})
if string(typed) != string(envMsg) {
t.Fatal("QuasarFinalityMessage != consensusCertMessage for the same tuple — two finality messages")
}
// Changing the key era changes M (era binding).
cert2 := *cert
cert2.KeyEraID = 8
if string(consensusCertMessage(&cert2, cert2.RequiredLegsRoot)) == string(envMsg) {
t.Fatal("KeyEraID is not bound into M")
}
}