Files
magnetar/DEPLOYMENT-RUNBOOK.md
T
Antje Worring df4c537c16 magnetar: remove proof-by-rename + circular proofs; honest threshold status
True no-reconstruction threshold SLH-DSA is impossible in the no-dealer /
no-preprocessing model a public, leaderless, permissionless chain needs
(Kondi-Kumar-Vanegas: extractable hash-based signatures cannot be thresholded
by black-box hash use). Stop pretending otherwise.

De-cheat:
  - DELETE the circular/vacuous proofs that manufactured false assurance:
    Magnetar_N1_Atom_Refinement.ec, Magnetar_N1_SHAKE_Expand.ec,
    Magnetar_N4_KeyDeriveStable.ec, lemmas/{Magnetar_CT,SLHDSA_Functional}.ec.
    The headline "strict-atom byte-equality" theorem was `apply <axiom that
    restates the theorem>`; the Lean side was `sorry`/`:= True`.
  - Re-open MAGNETAR-STRICT-ATOM (BLOCKERS): the public combiner DOES
    reconstruct the full FIPS 205 master every signature; the v1.1 "closure"
    only renamed identifiers. PROOF-CLAIMS / AXIOM-INVENTORY / TCB docs now say
    what the code does.
  - Re-label the name-grep "strict-atom" / "CT" checks as identifier-hygiene
    lint, NOT security or constant-time properties.
  - PVSS-DKG open-reveal (publishes the master to any observer) is gated as a
    TEST-ONLY path with HONEST LIMITATIONS; production does not rely on it.
  - Remove dead htRootCompute; staticcheck clean.

Honest three-leg posture (SPEC 1.0, BLOCKERS):
  - Permissionless production = INDEPENDENT FIPS 205 sigs + the weighted quorum
    certificate (luxfi/consensus), optionally STARK/FRI-compressed (luxfi/p3q).
    No key sharing, no reconstruction.
  - Trusted-hardware custody = TEE-attested combiner (trust-relocation, NOT MPC).
  - THBS-SE = RESEARCH-ONLY (transient seed reconstruction at the combiner);
    the T-SLH-DSA-MPC track (MPC over SHAKE) is the other research escape hatch.

Tests green (CGO=1, 71s). Net -923 lines.
2026-06-21 13:06:57 -07:00

11 KiB

Magnetar --- Deployment runbook

Operator-facing deployment guidance for Magnetar v1.0. READ THIS BEFORE DEPLOYING.

0. Choose your primitive

Magnetar v1.0 ships TWO distinct signing primitives with different trust models. Picking the wrong one is the single largest deployment risk.

Primitive Trust model No-leak / sound Use case
ValidatorSign + VerifyAggregateCert (per-validator standalone, standalone.go) Per-validator standalone keys, no shared seed, NO reconstruction YES (SOUND) Lux public-BFT validator quorum (PRODUCTION DEFAULT)
TEE-attested combiner pool (luxfi/threshold/protocols/slhdsa-tee) Seed reconstructed INSIDE a measured enclave on t hosts; trust-relocation (adds a host to the TCB), NOT MPC YES under attested-hardware trust Opt-in custody / single-signature certificates
NewThbsSeKey + ThbsSeRound1 + Combine (THBS-SE, thbsse.go) t-of-n committee, public combiner that RECONSTRUCTS the full FIPS 205 master every signature NO --- RESEARCH-GRADE; whoever runs Combine sees the seed (a host IS effectively in the TCB) Permissionless threshold ONLY where the combiner host is trusted by policy. NOT no-leak.

Quick decision

  • Public-BFT consensus on a Lux chain (mainnet, testnet, devnet, white-label) --> per-validator standalone. The consensus layer collects N validator signatures into a ValidatorAggregateCert and counts valid signers; the quorum policy decision lives at the consumer. Wire cost is N x |sigma|; Z-Chain Groth16 rollup compresses to ~192 bytes.

  • Permissionless threshold signing for verifier-side single-signature certificates --> THBS-SE. Read sec 2 below for the v1.0 honest open item on transient seed reconstruction at the public combiner.

  • HSM-attested MPC custody (M-Chain bridge custody, A-Chain confidential compute) --> NOT in this package. Operator-controlled MPC custody uses TEE-attestation-gated variants shipped under luxfi/threshold/protocols/{slhdsa,mldsa,rlwe}-tee via the lux/mpc sibling tree.

1. Per-validator standalone (production primary)

1.1 Keygen

Each validator runs PerValidatorKeypair ONCE on its own host:

sk, pk, err := magnetar.PerValidatorKeypair(params, rng)
  • params SHOULD be magnetar.ParamsM192s (smallest signatures at NIST PQ category 3, >=192-bit classical security). Use ParamsM192f only if signing latency is the dominant constraint and you can absorb the 2.2x larger signature; use ParamsM256s only if you need category 5 (>=256-bit classical security).
  • rng SHOULD be crypto/rand.Reader (nil also works; the function defaults to crypto/rand.Reader). Pass a deterministic reader ONLY for KAT reproducibility.

Persist (sk, pk) durably. Losing sk means dropping out of the quorum until rotating to a fresh keypair. Standard HSM-backed key storage applies; CIRCL slhdsa private keys are ~96 bytes at ModeM192s.

Register pk in the validator-set commitment via the consensus layer's normal key-registration ceremony.

1.2 Signing

sig, err := magnetar.ValidatorSign(sk, nil, message)

Pass nil for the RNG to get the deterministic variant (FIPS 205 SignDeterministic). The output is the raw params.SignatureSize bytes; the consensus layer's wire format wraps them.

Bind chain-id / block-height / consensus epoch into the message upstream of this call --- the consensus layer's transcript-hash pattern handles this (see luxfi/consensus QuasarCert).

1.3 Verification

cert, _ := magnetar.BuildAggregateCert(params, signers, pubKeys, sigs)
count, err := magnetar.VerifyAggregateCert(cert, message, knownValidators)
if count >= quorumThreshold { ... }
  • knownValidators is the consensus layer's authoritative NodeID -> pubkey map.
  • The function returns the COUNT of valid signers. Unknown / pubkey-mismatched signers are counted as INVALID (not fatal --- a defense against impersonation that does not abort the entire batch).
  • The quorum decision lives at the consumer.

2. THBS-SE (permissionless threshold)

2.1 v1.0 honest open item

THBS-SE v1.0 routes the final FIPS 205 byte production via a PUBLIC COMBINER that holds the seed for the duration of one slhdsa.SignDeterministic call and zeroizes. The combiner role is PUBLIC --- anyone can be the combiner --- and there is no long-lived secret material outside party-local Shamir leaves.

This is materially stronger than a TEE-attested privileged-aggregator model (no host is in the TCB; the combiner is a pure function any peer can run on its own substrate).

This is materially weaker than the strict invariant "no party or combiner EVER reconstructs SK.seed, even transiently in memory" --- a peer-local memory-disclosure adversary at exactly the combine moment could observe the seed. The strict-atom-assembly path is the v1.1 work item tracked at BLOCKERS.md::MAGNETAR-STRICT-ATOM-V11.

Operational implications. If your threat model includes "peer-local memory-disclosure adversary at the precise sub-second combine moment," do NOT deploy THBS-SE v1.0 for new committee ceremonies. Either:

  1. Wait for v1.1 strict-atom-assembly.
  2. Route the threshold signing via the TEE-attested variants at luxfi/threshold/protocols/slhdsa-tee (operator-controlled MPC custody, host in TCB by policy).
  3. Use per-validator standalone instead --- the public-BFT primary has no seed reconstruction at any point.

2.2 Setup

key, err := magnetar.NewThbsSeKey(params, threshold, committee, setupRng)
  • params and the threshold t are the same shape as per-validator standalone.
  • committee MUST be sorted ascending by NodeID with distinct non-zero IDs.
  • setupRng defaults to crypto/rand.Reader.

v1.0 reference uses a deterministic-dealer setup. The dealer is in the TCB FOR SETUP ONLY; once NewThbsSeKey returns, no party (including the dealer) holds the master seed. The returned *ThbsSeKey carries: the public key PublicKey, the per-party shares Shares[], the setup transcript SetupTranscript, and metadata (Threshold, N, Params).

Production deployments needing the leaderless PVSS-DKG variant route through the sibling luxfi/threshold DKG package; that DKG produces shares in the SAME wire-shape envelope. See BLOCKERS.md::MAGNETAR-PVSS-DKG-V11 for the v1.1 closure path.

2.3 Signing rounds

Each party runs:

r1, r2, err := magnetar.ThbsSeRound1(params, share, binding, msg, guard, rng)
  • binding is the slot tuple (chain_id, epoch, slot, height, committee_id, message_domain).
  • guard is a *ThbsSeSlotGuard the party persists across calls.
  • Idempotent replay: re-calling with the same (binding, msg) returns the persisted (r1, r2). A genuine equivocation attempt (same slot, different message) returns *ThbsSeEquivocationError carrying slashable evidence.

The party broadcasts r1 (the commit) and, after the Round-1 quorum is observable, r2 (the reveal).

2.4 Combine

Any peer (validator, block proposer, RPC node, passive watcher) can run:

sig, evidences, err := magnetar.Combine(magnetar.ThbsSeCombineInput{
    Key: key, Binding: binding, Message: msg,
    Round1: r1s, Round2: r2s,
})
  • err == nil and evidences empty: the signature was produced from >=t honest reveals.
  • err == nil and evidences non-empty: the signature was produced from >=t honest reveals, AND some malformed reveals were observed; the consensus layer can slash the named parties via VerifyThbsSeShareEvidence.
  • err == ErrInsufficientQuor: fewer than t valid reveals were observed. evidences carries the malformed-share evidence the consensus layer can act on before retrying.

2.5 Verification

ok := magnetar.VerifyBytesCtx(gpkBytes, message, ctxFromSlot(binding), sigBytes)

The VerifyBytesCtx helper is bytes-in, bool-out: it strips the MAGS/MAGG envelopes and routes through the FIPS 205 verifier verbatim. Any unmodified slhdsa verifier accepts the inner FIPS 205 bytes.

3. Operational hardening

3.1 RNG sourcing

crypto/rand.Reader on Linux/macOS reads from getrandom(2) / /dev/urandom. On non-trivial deployments, additionally:

  • Use the OS kernel's hardware-RNG entropy when available (/dev/hwrng on Linux with a HW source like RDRAND, the TPM, or a Yubikey-Bio).
  • For HSM-backed keys, route keygen through the HSM's FIPS 140-validated RNG.

3.2 Slot-guard persistence

The ThbsSeSlotGuard is in-memory only. For production deployments that must survive restarts, persist the guard's state to disk between Round-1 broadcasts (mirrored from SlotGuard.Record(slotID, digest, r1, r2) --- ALL four fields are required to verify slashing evidence after restart).

3.3 Equivocation slashing

VerifyThbsSeEvidence is a pure function. The consensus layer's slashing pipeline:

  1. Receive ThbsSeEvidence blob via gossip / on-chain submission.
  2. Verify via VerifyThbsSeEvidence(params, ev, msgPrior, msgNew, bindingPrior, bindingNew).
  3. If valid, slash the party named in ev.PartyID.

The evidence blob is sufficient on its own --- no committee state, no re-running of the protocol, no membership-proof gymnastics required.

3.4 Mode-mixing prevention

Magnetar's wire codec rejects mode-mismatch at parse time. A Signature parsed under ModeM192s cannot be cross-verified against a GroupKey parsed under ModeM256s --- VerifyBytesCtx returns false on mismatch.

3.5 Race detector

The Magnetar test suite passes under go test -race. SLH-DSA-heavy tests self-skip via the raceEnabled build tag pattern (race-on overhead is 5-10x and the tests carry no inter-goroutine concurrency that would benefit from race coverage); race-on runs cover the cheap unit tests (transcript, types, wire codec).

4. Migration from Magnetar v0.x

The v0.x CombineWithSeedReconstruction and AggregateSignatures API surfaces have been removed. v0.x consumers migrate as follows:

v0.x v1.0
magnetar.GenerateValidatorKey magnetar.PerValidatorKeypair
magnetar.AggregateSignatures + SignedBundle magnetar.BuildAggregateCert + ValidatorAggregateCert
magnetar.VerifyAggregated magnetar.VerifyAggregateCert
magnetar.CombineWithSeedReconstruction magnetar.Combine (THBS-SE, different semantics --- see THBS-SPEC.md)
pkg/thbs (legacy true-HBS) DELETED. THBS-SE in pkg/magnetar is the v1.0 threshold construction.

The signature payload bytes are byte-equal across primitives: a v0.x AggregateSignatures output and a v1.0 BuildAggregateCert output carry identical FIPS 205 signature bytes per validator. The only difference is the envelope shape.