LPsLux Proposals
Consensus Systems
LP-120

Quasar mainnet defaults, strict-PQ profile, and L1 onboarding

Draft

Concrete defaults for Quasar consensus on Lux primary network; the strict-PQ profile chain configuration; the L1 onboarding path for chains that want end-to-end post-quantum security with bidirectional warp messaging.

Category
Core
Created
2026-05-15

Implementation status (code-audited 2026-07-03): PARTIAL SigSchemeID 0x52 Pulsar-M-65 (consensus/config/pq_mode.go:288), BLS+Pulsar finality (config/profiles.go), PQ mode + scheme-pin confirmed; RefuseUnderStrictPQ lives at precompile-dex/contract/strict_pq.go.

Abstract

Defines the canonical Quasar mainnet defaults for the Lux primary network and the strict-PQ profile that L1s opt into when they want every cryptographic primitive on the chain (consensus, signatures, bridge) to be post-quantum. Specifies the precompile registry, the wire format, the light-client storage model, and the bidirectional warp messaging contract that lets a strict-PQ L1 launch on Lux, evolve to full-PQ-native, and continue to exchange warp messages with the primary network without dropping to a classical primitive at any point on the wire.

Motivation

Three operational questions need a single canonical answer:

  1. What does the Lux mainnet ship as the default consensus configuration?
  2. How does a chain launching on Lux declare itself strict-PQ — and what does that constrain?
  3. Can a strict-PQ L1 warp-message the primary network without breaking its own PQ guarantee?

This LP collapses those three questions into one configuration matrix.

Specification

Cryptographic primitives in scope

FamilySchemePrecompileHardnessSig sizeVerify
Classical fast laneBLS12-381 aggregatestandard precompilesco-CDH48 B714 µs
Module-LWE thresholdPulsar (FIPS 204 byte-equal ML-DSA-65)0x012204MLWE + MSIS3,309 B181 µs (3 µs cached)
Module-LWE thresholdCorona0x012206MLWE33,052 B1.6 ms
Hash-based threshold (proposed)Magnetar (public-DKG MPC threshold SLH-DSA)0x012207hash collision resistance~35,664 B~1.92 ms
Code-based KEM (family-disjoint)HQC (NIST PQC4 backup KEM)0x012208Syndrome DecodingCT 4,481 B (HQC-128)~150 µs (backend-bound)
Hash-based signatureSLH-DSA-192f (FIPS 205)0x012203hash collision resistance35,664 B1.92 ms (131 µs cached)
Module-LWE KEMML-KEM-768 (FIPS 203)0x012201MLWE25 µs
Strict-PQ STARKSTARK-FRI verifier (placeholder, pending dedicated LP)0x012220hash (cSHAKE256 / Goldilocks)~30 KB~5-10 ms
PQ unified verifier familyP3Q (kind-byte dispatch — see LP-218 / LP-220)0x012205hash + lattice (per-kind)variesvaries
Classical SNARKGroth160x0901KZG / pairings192 B~1-3 ms

Pulsar is the canonical PQ floor on the signature side. ML-KEM-768 is the canonical PQ floor on the KEM side. The other PQ schemes are profile-selectable add-ons. HQC closes the family-disjoint gap on the KEM side — its hardness rests on Syndrome Decoding rather than Module-LWE, so a structural break against MLWE does not compromise HQC and vice-versa. Magnetar is the analogue closer on the signature side (public-DKG MPC threshold SLH-DSA at 0x012207 with Pedersen-style VSS for auditable distributed key generation).

Slot history — 0x012205 reassignment

0x012205 was previously allocated for Strict-PQ STARK (Plonky3 fork) in this LP. Per LP-218 §"Slot history: STARK-FRI rename" (2026-06-03), the STARK-FRI verifier moved to placeholder slot 0x012220 pending its own dedicated LP. Slot 0x012205 is now owned by LP-218 / LP-220 for the P3Q unified verifier family (kind-byte dispatch). LP-0120 retains ownership of raw-primitive verifier slots 0x012206 (Corona) and 0x012207 (Magnetar); LP-220 wraps these under the unified verifier family but does not displace the raw slots. LP-300 records this reassignment in §"Existing conflicts resolved".

Mainnet defaults (Lux primary network)

FinalitySchemeID:     BLSPlusPulsar (the production default)
FastLane:             BLS12-381 aggregate (48 B + bitmap, 714 µs verify)
                      Used for speculative block building + 2-block tail
                      confirmation. Anchored at Pulsar — speculative
                      BLS confirms can be revoked by Pulsar rejection.
Finality:             Pulsar threshold (Module-LWE, FIPS 204 byte-equal)
                      3,309 B per cert at P65, 3 µs cached verify.
                      Threshold (t, k) sampled per Lux round via VRF
                      sortition from the validator registry.
Rollup:               Optional. Off by default. Enable per L1 if
                      per-validator identity sigs need to be compressed
                      onto chain — pick Groth16 (192 B, classical) or
                      STARK-FRI (~30 KB, strict-PQ, placeholder slot
                      `0x012220` pending a dedicated LP).
Light-client surface: Z-Chain rollup proofs only. ~30 KB per epoch.
PQ profile gate:      contract.RefuseUnderStrictPQ (single chokepoint
                      at every classical precompile's Run()).

Signature-scheme registry and the scheme-agnostic certificate (Normative)

Quasar is scheme-agnostic: the consensus engine defines only the quorum rule (a stake-weighted strict-⅔ predicate — LP-0110 §3), and the node injects the per-signer signature scheme as a one-byte wire tag SigSchemeID. This is why the classical→PQ migration is a profile flip, not a protocol change; it is proved invariant under the scheme substitution in proofs/pq-finality-no-bls.tex §"Scheme-agnostic certificate and the signature registry" (Proposition PQ migration is a profile flip).

SigSchemeID (config/pq_mode.go) is block-structured and open-ended. New entries claim the next free integer in their block, are pinned in pq_mode_test.go before any code references them, and a retired id is never reused:

Wire byteSchemeFamily / hardnessNotes
0x00noneBLS-only certs commit to no scheme
0x10BLS12-381 aggregateco-CDH (classical)day-1 cert, live
0x20Nasua (academic R-LWE)R-LWE, BLAKE3 profiletrusted-dealer; federation/bridge only; not an open-chain stance
0x30Pulsar.RR-LWE threshold (SHA-3 profile)production R-LWE
0x41 / 0x42 / 0x43ML-DSA-44 / -65 / -87M-LWE (FIPS 204, single-party)raw per-validator sig
0x51 / 0x52 / 0x53Pulsar-M-44 / -65 / -87M-LWE threshold (FIPS 204-compatible)0x52 = production PQ default

The 0x40 (raw single-party) and 0x50 (Pulsar-M threshold) blocks are kept distinct on purpose: both verify under the unmodified FIPS 204 ML-DSA.Verify relation, but the producing protocol differs (single-party vs. threshold), and the receiver needs to know which kernel emitted the bytes.

Naming note (wire byte is canonical). In config/pq_mode.go the 0x20 constant is SigSchemeNasua (String()"nasua"); the block comment and some external references still call this academic R-LWE finality scheme "Corona-academic". That is distinct from the Corona Module-LWE threshold precompile at 0x012206 (LP-4440). The human name is being reconciled toward Nasua; the wire byte 0x20 is stable regardless and MUST NOT be renumbered.

Transcript binding (cross-suite confusion resistance). SigSchemeID and HashSuiteID are covered inputs to the signed cert transcript ("LUX/chain/vote/v2" ‖ chainID ‖ height ‖ round ‖ canonicalID ‖ parentCanonical ‖ setRoot ‖ SigSchemeID ‖ HashSuiteID, hashed with SHAKE256). Flipping the scheme byte post-signing changes the digest the signatures cover, so a cross-suite confusion attack fails on signature verification, not on a byte-equality check (proof: pq-finality-no-bls.tex Lemma Cross-suite confusion resistance).

Orthogonal axes. SigSchemeID is one of six independent wire axes, each with its own numbering and its own 0x90+ forbidden-marker block so audit tooling can name a classical leakage explicitly: PolicyID (witness-set shape), HashSuiteID (0x01 SHA3-NIST normative / 0x02 BLAKE3-legacy), SigSchemeID (this table), ProofPolicyID (proof security class — STARK/FRI PQ vs. classical-forbidden), ProofBackendID (0x30 direct weighted-quorum full- node verify, 0x22 P3Q, …), and IdentitySchemeID (validator identity, FIPS 204 ML-DSA). The end-to-end axes (WalletSchemeID, TxSchemeID, ContractAuthID, KeyExchangeID, RecoverySchemeID) pin the wallet/tx/contract/KEM/recovery layers respectively.

Profile-flip activation. PQ finality is enabled by pinning the validator finality/identity scheme, not by swapping the engine:

  • Default mainnet: SigSchemeID = 0x52 (Pulsar-M-65) as the finality default; 0x10 BLS runs the speculative fast lane.
  • Strict-PQ: pin ValidatorSchemeID/finality to ML-DSA-65 (0x42) or -87 (0x43), or Pulsar-M-65/-87 (0x52/0x53); classical schemes are refused. PQSigner/PQVerifier enforce the pin and reject a mismatch with ErrPQSchemeMismatch. The quorum rule and the no-double-finalization argument are unchanged across the flip; only the per-signer forgery bound improves from the Shor-breakable BLS bound to the lattice MLWE/MSIS bound.

Worked example (BLS → Pulsar-M-65). A chain running the classical default finalizes with SigSchemeID = 0x10: each cert carries a 48-byte BLS aggregate, and the safety proof (LP-0110 §2.7; quasar-cert-soundness.tex) rests on the co-CDH forgery bound. To go post-quantum, the operator flips the finality scheme to 0x52 (Pulsar-M-65). Nothing in the rule changes: the same committee is sampled, the same strict-⅔ stake threshold is required, the same set-root is cross-checked, and the same decided-height sign gate applies — so the No double-finalization theorem holds verbatim with Verify_{0x10} replaced by Verify_{0x52}. The only differences are the cert bytes (a ~3.3 KB M-LWE threshold signature instead of 48 B) and the forgery bound (MLWE/MSIS instead of co-CDH), which is precisely why an adversary with a quantum computer gains nothing. Because 0x52 is a value the assembler reads — not a code path — the migration ships as a config/profile change, gated by contract.RefuseUnderStrictPQ so classical precompiles refuse to execute once the flip is live.

Assumption diversity (honest). Pulsar (R-/M-LWE) and ML-DSA (M-LWE) both rest on lattice hardness — two lattice legs buy defense-in-depth against implementation faults, not independent hardness. The genuine cross-family diversifier is the hash-based SLH-DSA (FIPS 205) reserved for recovery and high-value roots (RecoverySchemeID 0x05–0x07), which survives a total break of lattice assumptions.

Q-Chain. The PQ proof root and omni-chain consensus coordinator is the Q-Chain (QuantumVM under Quasar) — the chain that anchors validator PQ identity, carries the strict-PQ finality certificates, and coordinates cross-chain ordering. Q-Chain finality blocks are specified in LP-170; the quantum-secure consensus family is LP-4099 (superseded into LP-0110 + this LP).

Strict-PQ profile

A chain declares itself strict-PQ at genesis by setting:

{
  "chainConfig": {
    "networkUpgradeOverrides": {
      "strictPQTimestamp": 0   // active from genesis
    },
    "isStrictPQ": true,
    "finalitySchemeID": "Pulsar"  // OR "Aurora" OR "Magnetar"
  }
}

When IsStrictPQ(time) == true, every classical-primitive precompile refuses to execute. The single chokepoint is precompile/contract/strict_pq.go#RefuseUnderStrictPQ — called from the top of Run() in each classical module (BLS12-381, BN254, KZG, secp256k1, secp256r1, Ed25519, Ristretto, Pedersen, Baby Jubjub, Pasta, Pulsar's own Groth16 wrap, etc.).

What's forbidden under strict-PQ

ForbiddenWhy
BLS12-381 G1/G2/PairingDiscrete log under Shor's
BN254 (Add, ScalarMul, Pairing)Same
KZG (0x0900)Uses BN254 pairings
Groth16 / PLONK / fflonk / Halo2Curve-based SNARKs
secp256k1 / ECDSADiscrete log
secp256r1 / P-256Same
Ed25519, sr25519, RistrettoDiscrete log on Edwards
Pedersen over BN254Curve-based
Baby Jubjub, Pasta (Pallas/Vesta)Curve-based
RIPEMD160, Blake2FPre-PQ hash families with caveats
C-Chain / EVM with classical-only precompilesUse a Lux EVM with PQ-precompile registry instead

What's allowed under strict-PQ

AllowedNotes
Pulsar (0x012204)Module-LWE FIPS 204 threshold
Corona (0x012206)Module-LWE threshold
Magnetar (0x012207, proposed)Public-DKG MPC threshold SLH-DSA (FIPS 205 byte-equal)
ML-DSA single-party (0x012202)FIPS 204
SLH-DSA (0x012203)FIPS 205 hash-based
ML-KEM (0x012201)FIPS 203 KEM (Module-LWE)
HQC (0x012208)NIST PQC4 KEM (code-based, family-disjoint from ML-KEM)
STARK-FRI (0x012220, placeholder)Strict-PQ rollup (pending dedicated LP — see LP-218 §"Slot history: STARK-FRI rename")
P3Q unified verifier (0x012205)Unified verifier family with kind-byte dispatch (LP-218 / LP-220)
cSHAKE256, BLAKE3, SHA-3Hash primitives
Pulsar bridge messagesE2E PQ warp
X-Wing+ (0x2222, proposed)X25519 ∥ ML-KEM-768 ∥ HQC hybrid envelope (extends X-Wing with code-family KEM)

Wire format minimums

Per-block on-the-wire (1.1M-signer registry, k=128 sampled committee):

Z-Chain header
  parent_hash         32 B
  state_root          32 B
  validators_root     32 B   (Merkle root of the 1.1M-validator registry)
  rollup_proof_root   32 B
  epoch + slot         8 B
                    ─────
                    136 B   header

Pulsar threshold sig over header
                  3,309 B

Sortition proof (k=128 from N=1.1M, Merkle path)
                ~3.8 KB  (128 × 30 B path + payload)

────────────────────────────
Total per Z-Chain block  ~7.3 KB

STARK-FRI proof transmitted once per epoch (~30 KB), not per block. For 1 ms block time, batch into 1-second super-rollups so light clients verify ~30 KB per second of chain progress instead of per millisecond. (STARK-FRI verifier currently parked at placeholder slot 0x012220 per LP-218 §"Slot history: STARK-FRI rename"; awaits a dedicated LP.)

Light-client storage budget

Persistent state (constant in time):
  Pulsar group public key            1,952 B
  Validator-set Merkle root             32 B  (refreshed per epoch from P-Chain)
  Z-Chain head pointer                  32 B
  Latest STARK-FRI checkpoint       ~30 KB  (verifier at placeholder 0x012220)
                                  ─────────
                                  ~32 KB persistent

Per-tx-of-interest (ephemeral):
  Tx Merkle inclusion proof        ~1 KB
  (STARK-FRI header amortised across the epoch)

A subscribed-to-100-addresses light client: ~32 KB + ~100 KB = ~132 KB total state. Drops proofs once rolled into the next STARK-FRI checkpoint.

Pruned full node ("forget mode")

Keep forever:
  Z-Chain proof chain (STARK-FRI per epoch)   ~30 KB × 52K/yr ≈ 1.5 GB/yr
  Validator-set history Merkle                ~10 MB/yr
  P-Chain state diffs                         ~100 MB/yr

Drop after rollup:
  Full block bodies / tx data older than 2 epochs

Pruned-node total disk: ~1.6 GB/year vs archival ~10 TB/year for full chain history at 1 ms block time. ~6,000× compression.

L1 onboarding — strict-PQ launch checklist

1.  Genesis config:
      strictPQTimestamp = 0
      finalitySchemeID  = "Pulsar" (or "Aurora" / "Magnetar")
      classicalCompatUnsafe = false

2.  Validator key material:
      pubkey scheme   = ML-DSA-65 (Pulsar pk)
      NodeIDScheme byte = 0x42 (SigSchemeMLDSA65)

3.  Precompile registry (in evm/main.go blank-imports):
      _ "github.com/luxfi/precompile/mlkem"    // 0x012201
      _ "github.com/luxfi/precompile/mldsa"    // 0x012202
      _ "github.com/luxfi/precompile/slhdsa"   // 0x012203
      _ "github.com/luxfi/precompile/pulsar"   // 0x012204
      _ "github.com/luxfi/precompile/p3q"      // 0x012205 (unified verifier family — LP-218 / LP-220)
      _ "github.com/luxfi/precompile/corona"   // 0x012206
      _ "github.com/luxfi/precompile/magnetar" // 0x012207 (proposed)
      _ "github.com/luxfi/precompile/hqc"      // 0x012208 (family-disjoint KEM)
      // _ "github.com/luxfi/precompile/starkfri" // 0x012220 (placeholder, pending dedicated LP — see LP-218 §"Slot history: STARK-FRI rename")
      _ "github.com/luxfi/precompile/xwing"    // 0x2221 (X25519 ∥ ML-KEM-768)
      // _ "github.com/luxfi/precompile/xwingplus" // 0x2222 (proposed: X-Wing+, X25519 ∥ ML-KEM ∥ HQC)
      // ABSENT under strict-PQ:
      // _ "github.com/luxfi/precompile/kzg4844"
      // _ "github.com/luxfi/precompile/bls12381"
      // (any other classical-curve module)

4.  Warp:
      SchemeCorona Scheme = "corona"  (warp/crypto/signature/interface.go)
      OR
      Pulsar threshold over warp messages (default)
      Classical SchemeBLS still available but profile-gated.

5.  Bridge (B-Chain) custody:
      MPC key scheme = Pulsar (or Corona)
      Cross-chain messages signed by source-chain Pulsar threshold
      Re-signed by B-Chain Pulsar MPC for destination

6.  Light-client RPC endpoints:
      GET /v1/zchain/head
      GET /v1/zchain/proof/{epoch}
      GET /v1/zchain/inclusion/{tx_hash}
      (returns: STARK-FRI proof over a Pulsar-finalised batch + Merkle path)

Warp messaging — strict-PQ L1 ↔ Lux primary network

Bidirectional, end-to-end PQ:

                          STRICT-PQ L1                     LUX PRIMARY NETWORK
                          ────────────                     ───────────────────
Outbound from L1:
  L1 produces tx          → Pulsar finality on L1 block ← (one Pulsar sig per block)
  Bridge module on L1     → wraps message + L1 Pulsar proof + Z-Chain rollup ref
                          → emits warp event
  Validator gossip        → carries the wrapped message
  Lux primary B-Chain     → ingests, verifies L1's Pulsar proof
                            via precompile 0x012204 — strict-PQ verify
                          → re-signs for destination chain via B-Chain MPC
                          → emits warp event on Lux primary
  Destination Lux chain   ← verifies B-Chain re-signature (Pulsar)
                          ← message executes

Inbound to L1:
  Same path, mirrored. Lux-primary-Pulsar proof → L1 B-Chain → L1 destination

Every signature on every leg is one of: Pulsar (M-LWE) or Corona (M-LWE) or SLH-DSA (hash) or STARK-FRI. No BLS, no ECDSA, no KZG, no Groth16 anywhere on the warp wire when both ends are strict-PQ.

If one end is strict-PQ and the other is mixed (e.g., Lux mainnet C-Chain running BLS-fast-lane + Pulsar-finality), the strict-PQ end MUST verify only the Pulsar portion of the proof; the BLS aggregate is dropped at the strict-PQ boundary. This is enforced by the precompile-level RefuseUnderStrictPQ gate on the strict-PQ side and by Pulsar's own self-sufficient finality on both sides.

Can an L1 run only EVM (no other VMs)?

Yes. An L1 launched on Lux can ship with the EVM as its sole VM. Strict-PQ does not require running M-Chain (MPC), F-Chain (FHE), or any other Lux-primary chain locally — those are services exposed by the Lux primary network that the L1 can opt into via warp messaging. Strict-PQ requirements on a single-EVM L1:

Required:                                Optional:
  EVM + PQ precompile registry             M-Chain MPC custody (use Lux primary's)
  P-Chain validator follower               F-Chain FHE compute (use Lux primary's)
  Z-Chain follower                         B-Chain teleport ingress
  Pulsar threshold ceremony                Per-validator identity sig rollup
  Strict-PQ chain config

At a minimum: one EVM + Pulsar threshold + Z-Chain follower. ~32 KB persistent state for light clients, ~1.6 GB/yr for pruned nodes, ~10 TB/yr for archival.

Rationale

Why Pulsar as the PQ floor (not Aurora or Magnetar)

Pulsar is byte-equal to FIPS 204 ML-DSA-65 — the only NIST-validated PQ signature standard. Module-LWE and Module-SIS are stress-tested through the NIST PQC competition. There's no operational benefit to stacking more PQ schemes by default. Defense-in-depth additions (Corona for intra-lattice diversity in the Aurora profile, plus Magnetar for cross-family hash diversity in the Polaris profile) are profile-selectable, not the floor.

Certificate profile naming

Strict-PQ chains pick one finality scheme. Names are astronomical so they stay distinct from the Wing-prefixed transport/KEM hybrids (X-Wing, Z-Wing) and the Z-Chain rollup surface:

finalitySchemeIDConstructionStory
Pulsarthreshold ML-DSA (FIPS 204)the PQ floor — fast, regular pulse
AuroraPulsar ∥ Coronacombined glow from intra-lattice diversity
PolarisPulsar ∥ Corona ∥ Magnetarmaximum-assurance, adds the hash-only tail

Pulsar / Corona / Magnetar are the primitive names; Aurora / Polaris are the certificate profile names that bundle them. The Wing prefix is reserved for hybrid constructions on the transport lane (Z-Wing channel, LP-9702 — legacy, do not overload) and the KEM lane (X-Wing, IETF; X-Wing+, the code-family extension at 0x2222). No Wing names on the cert lane, no new Wing letters introduced — X-Wing+ is a notation extension of the IETF name, not a new Lux Wing brand.

Why MLWE ⊃ RLWE rules out "2× lattice safety"

Module-LWE with module rank k=1 is Ring-LWE. Polynomial-time reductions between them exist (with parameter shifts in modulus and error width). Stacking Pulsar and Corona (both Module-LWE, different parameter sets and codebases) gives implementation-level defense-in-depth but not family-disjoint hardness. For true family-disjoint PQ defense, cross to hash (SLH-DSA / Magnetar on signatures) or codes (HQC on KEM). HQC at 0x012208 and Magnetar at 0x012207 close those two gaps: a structural break in lattice cryptography would not compromise HQC (its hardness is Syndrome Decoding on random quasi-cyclic codes) or Magnetar (its hardness is collision/preimage resistance of the underlying hash family).

Why HQC on the KEM side and Magnetar on the signature side

The Lux PQCrypto block aims for two-axis coverage: by-default lattice (Pulsar + ML-KEM) for speed, profile-selectable code (HQC) and hash (Magnetar, SLH-DSA) for cross-family hedge. A chain that wants belt-and-suspenders KEM can chain X25519 ∥ ML-KEM-768 ∥ HQC at 0x2222X-Wing+, the code-family extension of the IETF X-Wing KEM combiner. Breaking the X-Wing+ shared secret requires solving ECDLP, MLWE, AND Syndrome Decoding simultaneously. The cost is one additional KEM operation (~150 µs for HQC-128 encapsulate) and ~4.5 KB of ciphertext per envelope on top of the X-Wing baseline.

Why Z-Chain is the light-client surface

Following the Z-Chain rollup gives a light client "this state was finalized by these validators" for any other chain in the topology, with a constant-size proof per epoch. Pulsar's threshold output is constant in n (the registry size), so the Z-Chain proof chain is constant-rate even as the validator set grows to 1.1M signers.

Why strict-PQ is profile-gated, not chain-default

The Lux primary network ships BLS as a fast lane because the bandwidth and verify cost are negligible (48 B, 714 µs) compared to Pulsar (3.3 KB, 181 µs single / 3 µs cached). Speculative 2-block confirmation under BLS, with canonical finality at Pulsar, gives the operational profile most chains want. Strict-PQ chains pay the cost of dropping BLS in exchange for a wire that no quantum adversary can attack at any point.

Backwards compatibility

This LP changes no existing wire format. Strict-PQ is an opt-in chain configuration. Existing chains continue under their current profile until they reconfigure at a genesis upgrade.

Security considerations

  • Post-quantum everywhere is one gate, not per-precompile policy. The chain-wide posture is a single value — Mode (pq/mode.go:47): classical ignores PQ material, hybrid validates it when present, strict-pq refuses every classical authentication root. At the EVM-precompile layer, ModeStrictPQ installs the one enforcement function: RefuseUnderStrictPQ (precompile/contract/strict_pq.go:33), called at the top of Run() by every classical precompile before it does any work — across 18 modules (BLS12-381, BN254/KZG, secp256r1, Ed25519/sr25519, Curve25519/X25519, Pedersen, BabyJubjub, Pasta, Poseidon, BLAKE3, FROST, CGGMP21, Ring, VRF, HPKE, the ZK SNARK verifiers; the BLS12-381 module alone guards 7 operations). Decomplecting the gate from each precompile's verification logic is the whole design: profile enforcement lives in one function, primitive math stays in its own lane. Bypassing the gate means modifying that one function — a chain compiled with the strict-PQ profile cannot route around it, because there is no second place the policy is expressed.
  • Cross-profile warp messaging (strict-PQ end ↔ mixed end) requires the strict-PQ end to verify only the Pulsar portion of the proof. The BLS portion is opaque to it; the security boundary is Pulsar.
  • Sortition VRF for the per-cert k-of-N committee uses a PQ-safe VRF (cSHAKE256-based). No discrete-log VRF in the sortition path.
  • B-Chain bridge custody key shares are Pulsar MPC by default in strict-PQ mode; Corona MPC available as a profile-selectable alternative.

Test cases

TestStrictPQ_ClassicalRefused       — every classical precompile returns
                                       ErrClassicalForbiddenInPQ when the
                                       chain reports strict-PQ
TestStrictPQ_PulsarAccepted         — Pulsar verify succeeds under strict-PQ
TestZChain_LightClientFollowsOnly   — light client constructs state from
                                       Z-Chain proofs alone (no full blocks)
TestWarp_E2E_PQ_Roundtrip            — strict-PQ L1 ↔ Lux primary warp
                                       message verifies on both ends with
                                       only PQ primitives on the wire

References

  • LP-110: Quasar Consensus
  • LP-118: Warp Signature Aggregation Protocol
  • FIPS 204: Module-Lattice-Based Digital Signature Standard (ML-DSA)
  • FIPS 205: Stateless Hash-Based Digital Signature Standard (SLH-DSA)
  • FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM)
  • Boschini-Kaviani-Lai-Malavolta-Takahashi-Tibouchi, IACR ePrint 2024/1113 (Ringtail — the academic two-round lattice threshold; Lux's Corona is the production Module-LWE scheme that follows this construction. Distinct artifacts — do not relabel the paper as "Corona".)
  • NIST IR 8528: Status Report on the Fourth Round of the NIST Post-Quantum Cryptography Standardization Process (HQC + Falcon backups)
  • proofs/lean/Crypto/Pulsar/ (machine-checked threshold correctness)
  • proofs/lean/Crypto/Threshold_Lagrange.lean (shared algebraic core)
  • proofs/lean/Crypto/Corona.lean (Module-LWE threshold)
  • proofs/lean/Crypto/MLKEM.lean (Module-LWE KEM)
  • proofs/lean/Crypto/HQC.lean (code-based KEM, family-disjoint from MLKEM)