mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
3a6fb954 cached the Polaris fixture and the package still hit its 900s cap on
CI. That fix was real but partial — I had measured only the seven tests I ran
locally, not the package. Measuring the whole package showed the remaining
cost sitting in twoSLHDSA: two FIPS-205 keygens at ParamsM192s, minted twelve
times for the same two fixed IDs, same weights, same threshold.
Shared safely — every test that alters a cert copies first. RollupRoot is a
[32]byte, so `bad := *f.mc` is a genuine copy, and the tamper test re-decodes
from f.mc.CertSet into fresh memory. Nothing writes through the scenario's
pointers, and the full package proves it: 11601 tests, same count, all pass.
Measured on one host, full package, -count=1:
before any caching ~117s
Polaris cached only 90s
both cached 50.5s
CI runs the same work on much slower hardware — 900s there against 90s here —
so cutting the package's real work is what matters, not the wall clock on this
machine.
Co-authored-by: Hanzo Dev <[email protected]>
518 lines
21 KiB
Go
518 lines
21 KiB
Go
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// magnetar_quorum_test.go — proofs for Magnetar-Quorum (Track A): the trustless
|
|
// hash-based PQ lane. Each test pins one property of the claim:
|
|
//
|
|
// - Independent per-validator FIPS-205 SLH-DSA sigs -> MagnetarQuorumCert ->
|
|
// VerifyMagnetarQuorum passes, and each inner sig verifies under the STOCK
|
|
// FIPS-205 verifier (no Lux machinery in the per-signer check).
|
|
// - Tamper / sub-threshold / root-mismatch / non-hash-based -> hard reject.
|
|
// - The succinct STARK seam fails closed (audit-gated).
|
|
// - Suite dispatch can never cross lanes or downgrade the param set.
|
|
// - The POLARIS_HASH_PQ / POLARIS_MAX postures admit Magnetar ONLY as the
|
|
// trustless rollup, NEVER as a threshold sig.
|
|
// - Structural trustlessness: independent keys, no dealer / shared secret.
|
|
//
|
|
// Reuses the foundation's real-key SLH-DSA harness (newSLHDSASigner /
|
|
// buildScenario in quorum_cert_test.go) and the envelope harness (envPolicy /
|
|
// envValidators / newCertForBH in consensus_cert_test.go).
|
|
package quasar
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"testing"
|
|
|
|
magnetar "github.com/luxfi/magnetar/ref/go/pkg/magnetar"
|
|
)
|
|
|
|
// slhParam is the SLH-DSA-192s parameter byte the Magnetar leg is built under.
|
|
const slhParam = uint8(QuorumSchemeSLHDSA192s)
|
|
|
|
// magnetarDirectSuite is the production Direct SLH-DSA-192s Magnetar suite.
|
|
const magnetarDirectSuite = "Lux-Magnetar-SLHDSA192s-Direct-v1"
|
|
|
|
// twoSLHDSA builds a real 2-signer SLH-DSA-192s scenario (weights 60+60=120,
|
|
// threshold 100). Each signer holds an INDEPENDENT FIPS-205 keypair.
|
|
// twoSLHDSACache holds the one shared two-signer SLH-DSA scenario. Minting a
|
|
// signer is a FIPS-205 keygen at ParamsM192s (the SMALL-signature set, slowest
|
|
// to sign), and twelve tests in this package ask for the same pair — the same
|
|
// two fixed IDs, the same weights, the same threshold. That repetition is a
|
|
// large share of why `go test ./protocol/quasar` was being killed at its 900s
|
|
// cap on CI.
|
|
//
|
|
// Shared safely: every test that alters a cert copies first. RollupRoot is a
|
|
// [32]byte, so `bad := *f.mc` is a real copy; the tamper test re-decodes from
|
|
// f.mc.CertSet into fresh memory. Nothing writes through the scenario's
|
|
// pointers.
|
|
//
|
|
// A plain var needs no lock: nothing in protocol/quasar calls t.Parallel().
|
|
var twoSLHDSACache *scenario
|
|
|
|
func twoSLHDSA(t *testing.T) scenario {
|
|
t.Helper()
|
|
if twoSLHDSACache != nil {
|
|
return *twoSLHDSACache
|
|
}
|
|
signers := []*testSigner{
|
|
newSLHDSASigner(t, 0x01, 60),
|
|
newSLHDSASigner(t, 0x02, 60),
|
|
}
|
|
sc := buildScenario(t, signers, 100, nil)
|
|
twoSLHDSACache = &sc
|
|
return sc
|
|
}
|
|
|
|
// magnetarFixture wraps an SLH-DSA scenario as a complete Magnetar-leg
|
|
// ConsensusCert + policy + validator set + the decoded MagnetarQuorumCert.
|
|
type magnetarFixture struct {
|
|
sc scenario
|
|
mc *MagnetarQuorumCert
|
|
store *envStore
|
|
validators *envValidators
|
|
policy *envPolicy
|
|
cert *ConsensusCert
|
|
msg []byte
|
|
}
|
|
|
|
// buildMagnetarFixture assembles a Direct Magnetar-Quorum cert over an SLH-DSA
|
|
// scenario and the envelope that verifies it (single Magnetar leg required).
|
|
func buildMagnetarFixture(t *testing.T, sc scenario) magnetarFixture {
|
|
t.Helper()
|
|
|
|
mc, err := BuildMagnetarQuorumCert(magnetarDirectSuite, sc.cert)
|
|
if err != nil {
|
|
t.Fatalf("BuildMagnetarQuorumCert: %v", err)
|
|
}
|
|
|
|
magLeg := LegSpec{Kind: LegMagnetarSLHDSA, ParamSetID: slhParam}
|
|
policy := &envPolicy{
|
|
required: []LegSpec{magLeg},
|
|
allow: map[legModeParam]bool{
|
|
{LegMagnetarSLHDSA, EvidenceMagnetarRollup, slhParam}: true,
|
|
},
|
|
thresholdWeight: sc.cert.QuorumThreshold,
|
|
classical: map[ClassicalScheme]bool{},
|
|
}
|
|
store := &envStore{policy: policy}
|
|
validators := &envValidators{
|
|
root: sc.cert.ValidatorSetRoot,
|
|
epoch: sc.env.Epoch,
|
|
cfg: sc.cfg, // empty AllowedSchemes => SLH-DSA admitted; MinThreshold re-pinned by leg
|
|
env: sc.env,
|
|
classKeys: map[ClassicalScheme][]byte{},
|
|
}
|
|
|
|
cert := newCertForBH(policy, sc.cert.ChainID, sc.cert.Epoch, sc.cert.Height, sc.cert.Round,
|
|
sc.cert.ValueHash, sc.cert.ValidatorSetRoot,
|
|
[]LegEvidence{{
|
|
Leg: magLeg,
|
|
Mode: EvidenceMagnetarRollup,
|
|
Payload: mc.Encode(),
|
|
}})
|
|
cert.AggregateWeight = sc.cert.AggregateWeight
|
|
|
|
return magnetarFixture{
|
|
sc: sc,
|
|
mc: mc,
|
|
store: store,
|
|
validators: validators,
|
|
policy: policy,
|
|
cert: cert,
|
|
msg: consensusCertMessage(cert, HashRequiredLegs(policy.RequiredLegs())),
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Happy path — the trustless statement holds.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// TestMagnetarQuorum_HappyPath proves independent SLH-DSA sigs roll up into a
|
|
// MagnetarQuorumCert that VerifyMagnetarQuorum (standalone) and the leg verifier
|
|
// both accept.
|
|
func TestMagnetarQuorum_HappyPath(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
|
|
if err := VerifyMagnetarQuorum(f.policy, f.validators, f.cert, f.msg, f.mc); err != nil {
|
|
t.Fatalf("VerifyMagnetarQuorum rejected a valid cert: %v", err)
|
|
}
|
|
|
|
// The LegEvidence dispatch form must agree.
|
|
ev := f.cert.Evidence[0]
|
|
if err := VerifyMagnetarQuorumLeg(f.policy, f.validators, f.cert, f.msg, ev); err != nil {
|
|
t.Fatalf("VerifyMagnetarQuorumLeg rejected a valid leg: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestMagnetarQuorum_EndToEndConsensusCert proves the leg verifies through the
|
|
// full policy-gated VerifyConsensusCert envelope (POLARIS-style Magnetar leg).
|
|
func TestMagnetarQuorum_EndToEndConsensusCert(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
if err := VerifyConsensusCert(f.store, f.validators, f.cert); err != nil {
|
|
t.Fatalf("VerifyConsensusCert rejected a valid Magnetar-leg cert: %v", err)
|
|
}
|
|
}
|
|
|
|
// TestMagnetarQuorum_StockFIPS205Interop proves the headline trustless claim:
|
|
// every signer record verifies under the STOCK FIPS-205 verifier (magnetar's
|
|
// thin VerifyCtx over circl/slhdsa) with NO Lux cert machinery. This is what
|
|
// makes the lane dealer-free and independently auditable.
|
|
func TestMagnetarQuorum_StockFIPS205Interop(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
|
|
inner, err := UnmarshalWeightedQuorumCert(f.mc.CertSet)
|
|
if err != nil {
|
|
t.Fatalf("decode inner SLH-DSA cert set: %v", err)
|
|
}
|
|
if len(inner.Signers) == 0 {
|
|
t.Fatal("inner cert carries no signer records")
|
|
}
|
|
for i := range inner.Signers {
|
|
rec := &inner.Signers[i]
|
|
if rec.Scheme.FIPS() != "205" {
|
|
t.Fatalf("record %d is not FIPS-205: scheme %s", i, rec.Scheme)
|
|
}
|
|
pk := &magnetar.PublicKey{Mode: magnetar.ModeM192s, Bytes: rec.PublicKey}
|
|
sig := &magnetar.Signature{Mode: magnetar.ModeM192s, Bytes: rec.Signature}
|
|
// The SLH-DSA leg signs under the EMPTY FIPS-205 context (the round-digest
|
|
// message carries the domain binding) — match contextForScheme.
|
|
if err := magnetar.VerifyCtx(magnetar.ParamsM192s, pk, f.sc.message, nil, sig); err != nil {
|
|
t.Fatalf("record %d: STOCK FIPS-205 verifier rejected: %v", i, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Tamper / threshold rejection.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// TestMagnetarQuorum_RootMismatchRejected proves a rollup root that does not
|
|
// commit to the carried cert set is rejected (the commitment binding).
|
|
func TestMagnetarQuorum_RootMismatchRejected(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
bad := *f.mc
|
|
bad.RollupRoot[0] ^= 0xFF
|
|
err := VerifyMagnetarQuorum(f.policy, f.validators, f.cert, f.msg, &bad)
|
|
if !errors.Is(err, ErrMagnetarRootMismatch) {
|
|
t.Fatalf("root-mismatch err = %v, want ErrMagnetarRootMismatch", err)
|
|
}
|
|
}
|
|
|
|
// TestMagnetarQuorum_TamperedSigRejected proves flipping a byte of an inner
|
|
// SLH-DSA signature (and re-binding the root over the tampered set, so the
|
|
// commitment passes) is caught by the composed stock-FIPS-205 verify.
|
|
func TestMagnetarQuorum_TamperedSigRejected(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
|
|
inner, err := UnmarshalWeightedQuorumCert(f.mc.CertSet)
|
|
if err != nil {
|
|
t.Fatalf("decode inner: %v", err)
|
|
}
|
|
inner.Signers[0].Signature[10] ^= 0xFF // corrupt a real FIPS-205 signature
|
|
tamperedSet, err := inner.MarshalBinary()
|
|
if err != nil {
|
|
t.Fatalf("re-marshal: %v", err)
|
|
}
|
|
bad := &MagnetarQuorumCert{
|
|
SuiteID: magnetarDirectSuite,
|
|
RollupRoot: MagnetarRollupRoot(magnetarDirectSuite, tamperedSet), // commitment still binds
|
|
CertSet: tamperedSet,
|
|
}
|
|
err = VerifyMagnetarQuorum(f.policy, f.validators, f.cert, f.msg, bad)
|
|
if !errors.Is(err, ErrQCSigInvalid) {
|
|
t.Fatalf("tampered-sig err = %v, want ErrQCSigInvalid (surfaced from the inner verify)", err)
|
|
}
|
|
}
|
|
|
|
// TestMagnetarQuorum_SubThresholdRejected proves a quorum below the policy
|
|
// weight floor is rejected — the BFT threshold is the verifier's, not the
|
|
// cert's. Build a 2-signer scenario whose Σweight (120) is below a 200 floor.
|
|
func TestMagnetarQuorum_SubThresholdRejected(t *testing.T) {
|
|
// Σweight = 120; quorum threshold 200 -> the inner cert is below threshold.
|
|
signers := []*testSigner{
|
|
newSLHDSASigner(t, 0x01, 60),
|
|
newSLHDSASigner(t, 0x02, 60),
|
|
}
|
|
sc := buildScenario(t, signers, 200, nil) // threshold > Σweight
|
|
f := buildMagnetarFixture(t, sc)
|
|
err := VerifyMagnetarQuorum(f.policy, f.validators, f.cert, f.msg, f.mc)
|
|
if !errors.Is(err, ErrQCBelowThreshold) {
|
|
t.Fatalf("sub-threshold err = %v, want ErrQCBelowThreshold", err)
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Cross-family diversity — the hash-based lane verifies ONLY SLH-DSA.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// TestMagnetarQuorum_BuildRejectsMLDSA proves the constructor refuses to build a
|
|
// Magnetar cert from a lattice (ML-DSA) weighted-quorum cert.
|
|
func TestMagnetarQuorum_BuildRejectsMLDSA(t *testing.T) {
|
|
sc := fourMLDSA(t) // a real ML-DSA-65 weighted-quorum cert
|
|
_, err := BuildMagnetarQuorumCert(magnetarDirectSuite, sc.cert)
|
|
if !errors.Is(err, ErrMagnetarNotHashBased) {
|
|
t.Fatalf("build-from-ML-DSA err = %v, want ErrMagnetarNotHashBased", err)
|
|
}
|
|
}
|
|
|
|
// TestMagnetarQuorum_VerifyRejectsMLDSA proves the verifier refuses a Magnetar
|
|
// cert whose (well-committed) cert set carries lattice records — a single
|
|
// Module-LWE break can never satisfy the hash-based diversity requirement.
|
|
func TestMagnetarQuorum_VerifyRejectsMLDSA(t *testing.T) {
|
|
mldsaSc := fourMLDSA(t)
|
|
certSet, err := mldsaSc.cert.MarshalBinary()
|
|
if err != nil {
|
|
t.Fatalf("marshal ML-DSA cert: %v", err)
|
|
}
|
|
// A hand-crafted Magnetar cert whose root correctly commits to an ML-DSA set.
|
|
mc := &MagnetarQuorumCert{
|
|
SuiteID: magnetarDirectSuite,
|
|
RollupRoot: MagnetarRollupRoot(magnetarDirectSuite, certSet),
|
|
CertSet: certSet,
|
|
}
|
|
// Verify against an envelope/validators bound to the ML-DSA scenario so the
|
|
// ONLY thing wrong is the scheme family (not position / merkle / threshold).
|
|
magLeg := LegSpec{Kind: LegMagnetarSLHDSA, ParamSetID: slhParam}
|
|
policy := &envPolicy{
|
|
required: []LegSpec{magLeg},
|
|
allow: map[legModeParam]bool{{LegMagnetarSLHDSA, EvidenceMagnetarRollup, slhParam}: true},
|
|
thresholdWeight: mldsaSc.cert.QuorumThreshold,
|
|
classical: map[ClassicalScheme]bool{},
|
|
}
|
|
validators := &envValidators{
|
|
root: mldsaSc.cert.ValidatorSetRoot, epoch: mldsaSc.env.Epoch,
|
|
cfg: mldsaSc.cfg, env: mldsaSc.env, classKeys: map[ClassicalScheme][]byte{},
|
|
}
|
|
cert := newCertForBH(policy, mldsaSc.cert.ChainID, mldsaSc.cert.Epoch, mldsaSc.cert.Height,
|
|
mldsaSc.cert.Round, mldsaSc.cert.ValueHash, mldsaSc.cert.ValidatorSetRoot, nil)
|
|
err = VerifyMagnetarQuorum(policy, validators, cert, []byte("M"), mc)
|
|
if !errors.Is(err, ErrMagnetarNotHashBased) {
|
|
t.Fatalf("verify-ML-DSA-set err = %v, want ErrMagnetarNotHashBased", err)
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Succinct seam — fails closed until audited.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// TestMagnetarQuorum_STARKSeamFailsClosed proves the succinct (STARK/FRI) suite
|
|
// pins its statement but fails closed; the raw set stays challengeable via
|
|
// Direct. Succinctness is the optimization seam, not a trust requirement.
|
|
func TestMagnetarQuorum_STARKSeamFailsClosed(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
starkCert := &MagnetarQuorumCert{
|
|
SuiteID: "Lux-Magnetar-SLHDSA192s-STARK-v1",
|
|
RollupRoot: f.mc.RollupRoot,
|
|
Proof: []byte("a-succinct-proof-that-must-not-be-trusted-yet"),
|
|
}
|
|
err := VerifyMagnetarQuorum(f.policy, f.validators, f.cert, f.msg, starkCert)
|
|
if !errors.Is(err, ErrMagnetarBackendNotAuditGated) {
|
|
t.Fatalf("STARK-seam err = %v, want ErrMagnetarBackendNotAuditGated", err)
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Suite dispatch safety — never cross lanes / downgrade params.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// TestMagnetarQuorum_RejectsForeignSuite proves a P3Q ML-DSA suite id cannot be
|
|
// dispatched to the Magnetar verifier.
|
|
func TestMagnetarQuorum_RejectsForeignSuite(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
foreign := *f.mc
|
|
foreign.SuiteID = "Lux-P3Q-MLDSA65-Direct-v1" // a real suite, wrong lane
|
|
err := VerifyMagnetarQuorum(f.policy, f.validators, f.cert, f.msg, &foreign)
|
|
if !errors.Is(err, ErrSuiteLaneMismatch) {
|
|
t.Fatalf("foreign-suite err = %v, want ErrSuiteLaneMismatch", err)
|
|
}
|
|
}
|
|
|
|
// TestMagnetarQuorum_RejectsUnknownSuite proves an unregistered suite is a hard
|
|
// reject (fail closed).
|
|
func TestMagnetarQuorum_RejectsUnknownSuite(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
unknown := *f.mc
|
|
unknown.SuiteID = "Lux-Magnetar-SLHDSA999s-Direct-v1"
|
|
err := VerifyMagnetarQuorum(f.policy, f.validators, f.cert, f.msg, &unknown)
|
|
if !errors.Is(err, ErrUnknownSuite) {
|
|
t.Fatalf("unknown-suite err = %v, want ErrUnknownSuite", err)
|
|
}
|
|
}
|
|
|
|
// TestMagnetarQuorum_LegParamPin proves the leg verifier pins the leg's param
|
|
// set against the suite: a 256s suite under a 192s leg spec is rejected.
|
|
func TestMagnetarQuorum_LegParamPin(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
// Re-build the cert set under the 256s suite id so the root commits, then
|
|
// present it on a 192s leg.
|
|
mismatch := &MagnetarQuorumCert{
|
|
SuiteID: "Lux-Magnetar-SLHDSA256s-Direct-v1",
|
|
RollupRoot: MagnetarRollupRoot("Lux-Magnetar-SLHDSA256s-Direct-v1", f.mc.CertSet),
|
|
CertSet: f.mc.CertSet,
|
|
}
|
|
ev := LegEvidence{
|
|
Leg: LegSpec{Kind: LegMagnetarSLHDSA, ParamSetID: slhParam}, // 192s leg
|
|
Mode: EvidenceMagnetarRollup,
|
|
Payload: mismatch.Encode(),
|
|
}
|
|
err := VerifyMagnetarQuorumLeg(f.policy, f.validators, f.cert, f.msg, ev)
|
|
if !errors.Is(err, ErrSuiteParamMismatch) {
|
|
t.Fatalf("leg-param-pin err = %v, want ErrSuiteParamMismatch", err)
|
|
}
|
|
}
|
|
|
|
// TestMagnetarQuorum_RejectsWrongLegKind proves the leg verifier refuses a
|
|
// non-Magnetar leg kind.
|
|
func TestMagnetarQuorum_RejectsWrongLegKind(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
ev := LegEvidence{
|
|
Leg: LegSpec{Kind: LegPulsarMLDSA, ParamSetID: slhParam}, // wrong kind
|
|
Mode: EvidenceMagnetarRollup,
|
|
Payload: f.mc.Encode(),
|
|
}
|
|
err := VerifyMagnetarQuorumLeg(f.policy, f.validators, f.cert, f.msg, ev)
|
|
if !errors.Is(err, ErrDisallowedEvidenceMode) {
|
|
t.Fatalf("wrong-leg-kind err = %v, want ErrDisallowedEvidenceMode", err)
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Policy table — POLARIS postures, trustless admission only.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// TestMagnetarQuorum_PolarisPolicyTiers proves the two POLARIS postures require
|
|
// the right leg kinds and admit Magnetar ONLY as the trustless rollup, NEVER as
|
|
// a threshold sig (the reveal-and-aggregate exclusion).
|
|
func TestMagnetarQuorum_PolarisPolicyTiers(t *testing.T) {
|
|
const thr = 1000
|
|
|
|
hash := NewQuasarEvidencePolicy(PolicyPolarisHashPQ, uint8(QuorumSchemeMLDSA65), thr)
|
|
if got := legKinds(hash.RequiredLegs()); !sameKinds(got, []LegKind{LegClassical, LegPulsarMLDSA, LegMagnetarSLHDSA}) {
|
|
t.Fatalf("POLARIS_HASH_PQ legs = %v, want Beam∧Pulsar∧Magnetar", got)
|
|
}
|
|
|
|
maxp := NewQuasarEvidencePolicy(PolicyPolarisMax, uint8(QuorumSchemeMLDSA65), thr)
|
|
if got := legKinds(maxp.RequiredLegs()); !sameKinds(got, []LegKind{LegClassical, LegPulsarMLDSA, LegCoronaLattice, LegMagnetarSLHDSA}) {
|
|
t.Fatalf("POLARIS_MAX legs = %v, want Beam∧Pulsar∧Corona∧Magnetar", got)
|
|
}
|
|
|
|
magLeg := LegSpec{Kind: LegMagnetarSLHDSA, ParamSetID: slhParam}
|
|
for _, p := range []*QuasarEvidencePolicy{hash, maxp} {
|
|
// Admitted: the trustless rollup under the SLH-DSA param.
|
|
if !p.Allows(magLeg, EvidenceMagnetarRollup, slhParam) {
|
|
t.Fatalf("%s must admit the Magnetar rollup", p.Mode())
|
|
}
|
|
// Forbidden: a threshold-sig over the Magnetar leg (reveal-and-aggregate).
|
|
if p.Allows(magLeg, EvidenceThresholdSig, slhParam) {
|
|
t.Fatalf("%s must NOT admit a Magnetar threshold sig (reveal-and-aggregate TCB)", p.Mode())
|
|
}
|
|
// Forbidden: wrong param set.
|
|
if p.Allows(magLeg, EvidenceMagnetarRollup, uint8(QuorumSchemeMLDSA65)) {
|
|
t.Fatalf("%s must reject a non-SLH-DSA Magnetar param", p.Mode())
|
|
}
|
|
}
|
|
|
|
// A non-POLARIS posture must never admit the Magnetar leg at all.
|
|
strict := NewQuasarEvidencePolicy(PolicyStrictQuasar, uint8(QuorumSchemeMLDSA65), thr)
|
|
if strict.Allows(magLeg, EvidenceMagnetarRollup, slhParam) {
|
|
t.Fatal("STRICT_QUASAR must not admit the Magnetar leg")
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Structural trustlessness — independent keys, no dealer / shared secret.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// TestMagnetarQuorum_NoDealerNoSharedSecret proves the lane is structurally
|
|
// dealer-free: two DISJOINT sets of independently-generated validator keypairs
|
|
// each produce a valid Magnetar cert with NO shared key material, and the inner
|
|
// records expose only public keys + signatures (never a seed / share / group
|
|
// key). There is no construction step that forms a shared secret.
|
|
func TestMagnetarQuorum_NoDealerNoSharedSecret(t *testing.T) {
|
|
// Two committees with completely independent keypairs (fresh keygen each).
|
|
fA := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
signersB := []*testSigner{
|
|
newSLHDSASigner(t, 0x11, 70),
|
|
newSLHDSASigner(t, 0x12, 70),
|
|
}
|
|
fB := buildMagnetarFixture(t, buildScenario(t, signersB, 100, nil))
|
|
|
|
if err := VerifyMagnetarQuorum(fA.policy, fA.validators, fA.cert, fA.msg, fA.mc); err != nil {
|
|
t.Fatalf("committee A rejected: %v", err)
|
|
}
|
|
if err := VerifyMagnetarQuorum(fB.policy, fB.validators, fB.cert, fB.msg, fB.mc); err != nil {
|
|
t.Fatalf("committee B rejected: %v", err)
|
|
}
|
|
|
|
// Structural: the committees share NO public key (independent keypairs).
|
|
innerA, _ := UnmarshalWeightedQuorumCert(fA.mc.CertSet)
|
|
innerB, _ := UnmarshalWeightedQuorumCert(fB.mc.CertSet)
|
|
for i := range innerA.Signers {
|
|
for j := range innerB.Signers {
|
|
if bytes.Equal(innerA.Signers[i].PublicKey, innerB.Signers[j].PublicKey) {
|
|
t.Fatal("committees share a public key — independent keygen violated")
|
|
}
|
|
}
|
|
}
|
|
// Structural: each committee's own signers hold distinct keys (no shared key).
|
|
if bytes.Equal(innerA.Signers[0].PublicKey, innerA.Signers[1].PublicKey) {
|
|
t.Fatal("two signers in one committee share a public key — not independent")
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Codec round-trip.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// TestMagnetarQuorum_CodecRoundTrip proves the wire codec is a deterministic
|
|
// bijection and rejects trailing bytes (fail-closed, no panic).
|
|
func TestMagnetarQuorum_CodecRoundTrip(t *testing.T) {
|
|
f := buildMagnetarFixture(t, twoSLHDSA(t))
|
|
wire := f.mc.Encode()
|
|
got, err := DecodeMagnetarQuorumCert(wire)
|
|
if err != nil {
|
|
t.Fatalf("decode: %v", err)
|
|
}
|
|
if got.SuiteID != f.mc.SuiteID || got.RollupRoot != f.mc.RollupRoot ||
|
|
!bytes.Equal(got.CertSet, f.mc.CertSet) || !bytes.Equal(got.Proof, f.mc.Proof) {
|
|
t.Fatal("round-trip mismatch")
|
|
}
|
|
if !bytes.Equal(got.Encode(), wire) {
|
|
t.Fatal("re-encode is not byte-identical (non-canonical codec)")
|
|
}
|
|
// Trailing byte -> fail closed.
|
|
if _, err := DecodeMagnetarQuorumCert(append(wire, 0x00)); !errors.Is(err, ErrEvidenceWireCorrupt) {
|
|
t.Fatalf("trailing-byte err = %v, want ErrEvidenceWireCorrupt", err)
|
|
}
|
|
}
|
|
|
|
// --- small test helpers (leg-kind comparison) ---
|
|
|
|
func legKinds(legs []LegSpec) []LegKind {
|
|
out := make([]LegKind, len(legs))
|
|
for i, l := range legs {
|
|
out[i] = l.Kind
|
|
}
|
|
return out
|
|
}
|
|
|
|
func sameKinds(a, b []LegKind) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
seen := make(map[LegKind]int, len(a))
|
|
for _, k := range a {
|
|
seen[k]++
|
|
}
|
|
for _, k := range b {
|
|
seen[k]--
|
|
}
|
|
for _, v := range seen {
|
|
if v != 0 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|