Draft. Amends LP-017. The v1 codenames (Pulsar / Aurora / Polaris)
become INTERNAL identifiers; operator-facing configuration uses the
4-mode ladder defined here.
Activated at the genesis of the new final Lux network: **2025-12-25
16:20 Pacific (unix 1766708400)**. The pre-Quasar Edition Lux network
(2020–2025) is a separate network and is out of scope.
LP-017 v1 named cert profiles after astronomical phenomena (Pulsar,
Aurora, Polaris). Those names describe internals, not posture: an
operator cannot read "Aurora" and know whether their cert is
PQ-protected or how much latency it costs. This LP replaces the
operator-facing surface with a 4-mode additive ladder whose name
declares posture and whose composition is monotone.
PQ-off ⊂ PQ-fast ⊂ PQ-strict ⊂ PQ-heavy
BLS BLS+Corona BLS+Corona BLS+Corona
+Pulsar +Pulsar+Magnetar
Each step adds exactly one independent security property. The pure-PQ
variants (drop BLS) are identical leg compositions minus the classical
fast-path:
strict-PQ-fast = Corona
strict-PQ-strict = Corona + Pulsar
strict-PQ-heavy = Corona + Pulsar + Magnetar
Seven valid configurations total. The QuasarCert wire format (LP-182)
is unchanged; the cert struct shape is unchanged; the LP-017 v1
composition predicates (IsPolaris, IsDoubleLattice, HasHashBased)
are unchanged. The new mode name is a single header byte on the
operator config knob — quasar.cert_mode.
Three concrete failures of the v1 codename surface:
1. Posture is opaque. "Aurora" does not announce that BLS is the
fast-path leg or that lattice diversity is present. Operators ask
"is Aurora PQ?" — the answer requires reading LP-017 §Specification.
2. Ordering is non-monotone. Pulsar → Aurora → Polaris is the v1
security ordering, but the names give no hint that Polaris is a
superset of Aurora. A new operator reading the codenames in
alphabetical order builds the wrong mental model.
3. No room for the pure-PQ variant. A chain that does not need a
classical fast-path (post-PQ-transition L1, sovereign network not
anchored to a BLS bridge) has no v1 name; the v1 spec assumes BLS is
always present.
The 4-mode ladder fixes all three: names declare posture, ordering is
monotone (each step is a superset), and pure-PQ variants are first-class
(prefix strict-).
Each mode defines a REQUIRED leg set. A cert is at mode M if and only
if every leg in M's required set is present and verified. Modes are
totally ordered by subset inclusion within their family (classical or
pure-PQ).
Latency numbers below are measured wall-clock per signing round
on Spark (GB10 ARM, 20-core) at N=64 from the Quasar 4-scheme matrix
bench (2026-06-04, /tmp/quasar-matrix-bench). Columns: M1 Max,
Spark — CPU-only paths (GPU dispatch unplumbed at bench time;
projections in §"GPU dispatch — measured gaps"). Cert size is the
LP-022 wire form at N=64.
The pure-PQ variants drop BLS; otherwise the leg composition is
identical:
Per-primitive single-validator timings (measured, same bench, 192s
for Magnetar — production-target parameter set):
Corona ceremony scales O(N^1.5–1.7) between N=32 and N=64 (Spark:
370 ms → 585 ms = 1.58×; M1: 231 ms → 391 ms = 1.69×). This is
consistent with a 2-round threshold protocol whose Round1 / Round2
messages cross-multiply. Corona rejection-exhausted at N=128 under
the default coronaMaxRetries=8 setting; production at N=128 requires
parameter retuning. PQ-strict at N≤64 stays inside the 1-s budget on
both M1 Max and Spark.
The bench measures Magnetar SLH-DSA-192s (small-signature variant)
because that is what ~/work/lux/threshold/protocols/magnetar/ ships
today. At 795 ms/sign on Spark, **no Magnetar-bearing profile is
sub-second at any measured N. Switching to 192f** (fast variant,
larger signatures) drops per-validator sign to 36 ms on Spark and
restores the sub-1-s budget for pq-heavy at N≤64.
Decision: pq-heavy MUST use Magnetar-192f for production. Operators
choosing pq-heavy with -192s opt into a multi-second finality cost.
(LP-220 follow-up: gate the parameter-set choice at threshold init.)
Background nvidia-smi dmon -s pucvmet across the 2-hour bench run
captured 4,595 samples; mean SM% = 11.9% — idle / background
only. GPU was not exercised by any path in this bench. Two
real boundary gaps prevent the GPU dispatch:
1. No lux-lattice.pc on spark. The Go-side
github.com/luxfi/lattice/v7/gpu package uses `#cgo pkg-config:
lux-lattice; the CMake build hits find_package(MLX REQUIRED)`
on the dependency chain even for CUDA targets, so `-tags
"cgo gpu"` doesn't build on Spark today. Local Mac builds succeed
(lux-lattice.pc + libluxlattice.dylib at `/Users/z/work/luxcpp/
install/lib/`). The CUDA NTT kernels themselves are present and
pass KAT tests; the bench just couldn't reach them.
2. Magnetar SLH-DSA CUDA boundary unplumbed.
luxcpp/crypto/slhdsa/gpu/cuda/slhdsa.cu exists and
test_slhdsa_kat_cuda passes on Spark (WOTS+ / FORS / XMSS
subtree KATs PASS), but lux_slhdsa_* entry points are NOT
exposed in luxcpp/lux-accel/include/lux/accel/c_api.h, so
magnetar.ValidatorSign falls back to pure-Go via
cloudflare/circl.
When both gaps close, the GPU column will reflect actual measured
numbers. Until then, GPU numbers in this LP and downstream LPs are
explicitly tagged "projected, not measured."
1. Required-set semantics. A cert is at mode M iff every leg in
M's required set has been aggregated and verified at the round
digest. A cert with extra legs is still at mode M — extra legs are
allowed but not required.
2. LP-202 tier degradation. If a required leg fails to aggregate
by the round deadline, the cert is published with that leg empty.
Relying parties whose policy requires mode M wait for the next
height or fall back to the previous height; relying parties at the
highest mode whose required set is satisfied finalize normally.
Consensus liveness is preserved by the surviving legs.
3. Monotone observability. The cert is observable at progressively
higher modes as legs arrive. A single cert struct serves all
relying-party policies; the relying party applies its mode policy
against the cert's observed leg set.
4. Pure-PQ variants drop BLS. strict-PQ-* modes do not require
BLS. A cert with BLS present and the required PQ legs satisfies
both the classical mode (PQ-*) and the pure-PQ variant
(strict-PQ-*). Operators pick the mode their relying-party policy
enforces; the cert is the same.
5. ZK leg is profile-orthogonal. The optional zero-knowledge leg
(execution-side certification, LP-017 v1) is not part of the mode
ladder. It is attached or absent independently per chain; modes
describe consensus-cert posture only.
The v1 codenames remain in the codebase as INTERNAL identifiers (struct
names, package paths, EasyCrypt artifact filenames). The mode-to-internal
map for operator config translation:
The v1 "Pulsar" profile (BLS + Pulsar + ZK) named Pulsar as the
cheapest PQ leg. The v2 PQ-fast mode names Corona as the cheapest PQ
leg. The choice is governed by the Corona/Pulsar parity audit
(scheduled, not yet completed). Best-evidence as of activation:
is structurally cheaper per-aggregate-op than Pulsar's Module-LWE
rank-k (k≥4 for ML-DSA-65). On the GPU NTT paths in LP-203, Corona
aggregate at N=64 measures ~50 ms (M4 Max) / ~15 ms (H100); Pulsar
threshold aggregate at the same N is in the same order-of-magnitude
but with constant-factor overhead from the rank-k matrix ops.
latency for both primitives at N ∈ {16, 32, 64, 128, 256}, GPU class
∈ {M4 Max, H100, Blackwell}, signed by an external benchmark
authority. The deliverable lands as an addendum to LP-203.
Spec posture. This LP specs the ladder STRUCTURE (4 modes +
3 variants, additive composition, LP-202 degradation) AND the leg
ORDER. The parity audit (2026-06-03, lux/threshold/protocols/parity/)
measured Corona at 141× the cost of Pulsar at N=64 — algorithmic
not optimization. PQ-fast = BLS + Pulsar (LOCKED). PQ-strict adds
Corona on top for the never-trust-aggregator security property — the
~100× latency cost buys an architectural security upgrade, not a
redundant lane.
One struct — CertPolicy — declares the full cert posture for a chain
at genesis. Three previously-scattered knobs (cert_mode,
cert_timeout_ms, and LP-204's per-L1 mode picker) collapse to four
fields of one record. LP-202 references CertPolicy.TimeoutMs. LP-204
attaches a CertPolicy per chain-VM (default: inherit from parent L1).
LP-218 reuses CertPolicy.Mode as the rollup's inherited cert mode.
The operator-facing enum is CertMode (not PQMode). PQMode is
already taken in pq_mode.go for the v1 internal codenames
(PQModePulsar, PQModeQuasar, PQModeMLDSA, ...) which name
cryptographic building blocks; CertMode is the v2 operator-facing
ladder defined here.
// CertPolicy is the single configuration record that declares a
// chain's cert posture. One CertPolicy per chain at genesis;
// validated at chain launch (see Validation rules below); refused if
// invalid.
type CertPolicy struct {
Mode CertMode // PQ-off | PQ-fast | PQ-strict | PQ-heavy
Variant CertVariant // Hybrid (BLS + PQ legs) | Strict (pure PQ, no BLS)
TimeoutMs uint32 // max wait for full-mode cert; past TimeoutMs
// LP-202 tier degradation kicks in
Fallback CertMode // tier to settle at if Mode's legs don't
// arrive in TimeoutMs; MUST satisfy Fallback <= Mode
}
// CertMode is the additive cert-mode ladder. Subset-ordered:
// CertModeOff < CertModeFast < CertModeStrict < CertModeHeavy
type CertMode uint8
const (
CertModeOff CertMode = 0 // Hybrid: BLS only. Strict: (invalid; refused)
CertModeFast CertMode = 1 // Hybrid: BLS + Pulsar. Strict: Pulsar only
CertModeStrict CertMode = 2 // Hybrid: BLS + Pulsar + Corona. Strict: Pulsar + Corona
CertModeHeavy CertMode = 3 // Hybrid: BLS + Pulsar + Corona + Magnetar.
// Strict: Pulsar + Corona + Magnetar
)
// CertVariant picks whether BLS is part of the required leg set.
type CertVariant uint8
const (
CertVariantHybrid CertVariant = 0 // include BLS as classical leg
CertVariantStrict CertVariant = 1 // drop BLS; pure PQ legs only
)
quasar:
cert_policy:
mode: PQ-strict # PQ-off | PQ-fast | PQ-strict | PQ-heavy
variant: hybrid # hybrid | strict
timeout_ms: 1000 # max wait for full-mode cert
fallback: PQ-fast # tier to settle at if Mode's legs miss
# the timeout; MUST be <= mode
A chain configured mode=PQ-strict, variant=hybrid produces a
QuasarCert with BLS + Pulsar + Corona legs. The same chain at
mode=PQ-strict, variant=strict drops BLS. The seven valid
configurations from §"The 4 modes" are enumerated by
(Mode, Variant) pairs (table below).
Mode | Variant | Required legs | Wire name |PQ-off | hybrid | BLS | PQ-off |PQ-fast | hybrid | BLS + Pulsar | PQ-fast |PQ-strict | hybrid | BLS + Pulsar + Corona | PQ-strict |PQ-heavy | hybrid | BLS + Pulsar + Corona + Magnetar | PQ-heavy |PQ-fast | strict | Pulsar | strict-PQ-fast |PQ-strict | strict | Pulsar + Corona | strict-PQ-strict |PQ-heavy | strict | Pulsar + Corona + Magnetar | strict-PQ-heavy |Seven configurations; the eighth slot (PQ-off, strict) is invalid
(no legs at all) and refused by Validate.
CertPolicy is validated at chain genesis. A chain MUST refuse to
launch with an invalid CertPolicy. The rules are:
1. Fallback <= Mode. The fallback tier cannot be stronger than
the target mode. A fallback tier means "the relying party
finalises at this lower posture if Mode's legs do not arrive
within TimeoutMs"; finalising at a stronger tier would require
more legs, not fewer, so a stronger fallback is incoherent. The
four modes are subset-ordered (`PQ-off < PQ-fast < PQ-strict <
PQ-heavy); the comparison is integer-ordering on PQMode`.
2. Variant == Strict requires Mode >= PQ-fast. Pure-PQ at
PQ-off is the empty leg set (no BLS, no PQ legs). A cert with no
legs is not a cert; this configuration is refused.
3. **TimeoutMs >= 2 * expected_floor_latency(Mode).** Per the
footgun warning previously in this section: a chain configured at
a high Mode with a TimeoutMs shorter than the floor latency
for that mode will routinely publish certs at a lower tier (per
LP-202 tier degradation). The validator MUST reject such a
configuration at genesis — there is no operationally-useful chain
that wants to declare PQ-heavy and then never satisfy it. The
expected floor latencies are pinned in §"The 4 modes" Table 1
(Blackwell N=64):
Mode | Floor latency | Min TimeoutMs |PQ-off | ~1 ms (final) | 2 ms |PQ-fast | ~5 ms (GPU) | 10 ms |PQ-strict | ~50 ms (GPU) | 100 ms |PQ-heavy | ~80 ms (final) | 160 ms |Validators with non-Blackwell hardware multiply through the
CPU/M4-Max floors in Table 1. The 2× factor is the minimum;
production deployments typically set TimeoutMs to 4–10× the
floor to absorb jitter without dropping to Fallback.
4. Fallback must itself be a valid (Mode, Variant) under the
chain's Variant. A chain at Variant=Strict cannot fall back to
PQ-off because (PQ-off, strict) is invalid (rule 2).
None. Previous knobs (cert_mode standalone, cert_timeout_ms
standalone) do not exist on this network. There is no migration; the
new final Lux network starts at genesis with CertPolicy.
in the critical path of an order-matching engine; non-financial L2s
whose threat model does not include store-now-decrypt-later
adversaries; legacy bridge endpoints that consume only classical
BLS-verifiable certs.
/ card-rail end-to-end latency); gaming chains where PQ insurance is
desired but ~5 ms is the upper budget; DEX matching layers settling
to a PQ-strict L1.
L1s where the cert is the audit anchor; store-of-value chains. The
intra-lattice diversity (two Module-LWE parameter sets — Pulsar +
Corona) hedges against a parameter- or implementation-specific break.
chain consumes); sovereign-network anchors; long-archival
commitments (cert verified 30+ years out, where the hash-based
Magnetar leg provides defense against any future lattice break).
operator-facing names; remain as INTERNAL identifiers in code
(struct names, file paths, EasyCrypt artifacts). v1 composition
predicates (IsPolaris, IsDoubleLattice, HasHashBased) unchanged
and continue to serve the relying-party-policy surface in v1
consumers.
PQ-heavy / strict-PQ-heavy; its threshold ceremony and wire codec
are not affected by this LP.
the same struct shape across all modes; the operator's mode choice
is a header byte on the runtime config, NOT a wire format change.
Relying parties parse the cert and apply mode policy locally.
unchanged. LP-202 references CertPolicy.TimeoutMs and
CertPolicy.Fallback from this LP rather than defining its own
cert_timeout_ms knob. LP-202 §"Cert leg degradation tiers"
describes the temporal behavior; this LP defines the static
posture surface that triggers it.
parallel CUDA-stream dispatch in LP-203 §Specification is per-leg;
CertPolicy.RequiredLegs() is the leg-set the verifier dispatches
kernels for. Bench numbers in this LP are derived from LP-203's
measured + estimated rows.
CertPolicy at genesis. Each Tier-2 chain-VM in chains: defaults
to inheriting the parent L1's CertPolicy; it MAY override with
its own cert_policy: block, subject to the parent L1 actually
operating at that policy's Mode (a Tier-2 chain-VM cannot
synthesise legs the parent L1 never produces). CertPolicy is
upgrade-able via the chain's governance path (P-chain
SetChainValidatorWeightTx analog; spec'd per-chain). Downgrade
is mechanically possible but a safety-equivalence audit is
required before any chain at Mode=PQ-strict or higher downgrades.
CertPolicy.Mode at genesis (LP-218 calls this the rollup's CertModeFloor); the
rollup cannot enforce a stronger Mode than its parent L1
operates at. LP-218 §"Inherited cert mode" cites CertPolicy.Mode
as the policy-axis name. A rollup MAY pin a lower Mode than the
parent L1 and finalise earlier in the LP-202 tier-degradation
timeline; this is the explicit operator declaration that the
rollup is comfortable with a lower posture than the parent
provides.
activates: 2025-12-25T16:20:00-08:00
activates-unix: 1766708400
The 4-mode ladder is the operator-facing surface from activation
forward. v1 codenames remain valid internal identifiers and are not
ripped from the codebase.
Each mode adds exactly one security property over the previous mode.
This makes the operator's decision linear: pick the lowest mode whose
posture floor exceeds your threat model. The codename ladder
(Pulsar → Aurora → Polaris) is additive in legs but not in name; the
mode ladder is additive in both.
The Corona/Pulsar parity audit (lux/threshold/protocols/parity/) measured
the two schemes apples-to-apples on Apple M1 Max + DGX Spark GB10 and
found Corona is 141× slower than Pulsar at N=64 validators (3.2-4.0 s
vs 23-28 ms total signing round-trip). This is not an optimization gap —
it is algorithmic:
1. Pulsar is a "reconstruct-on-aggregator" Shamir scheme. The
aggregator briefly materialises the 32-byte master sk via Shamir
reconstruction over GF(257), runs unmodified FIPS 204 ML-DSA sign
once on that host, zeroises. Output is byte-equal to vanilla
ML-DSA — verifiable by any FIPS 204 verifier (circl, BoringSSL,
RustCrypto).
2. Corona is a genuine 2-round threshold lattice scheme (Corona
family, eprint 2024/1113). Each party performs 392 NTT polynomial
multiplies in Round 1 plus 256 independent Gaussian eliminations
in Round 2 plus 2t PRF expansions. No party ever materialises the
master sk. Different security property; different cost class.
3. At N=64 on the same hardware: Pulsar 28.5 ms total; Corona
4031 ms total. The 141× gap is the price of "never trust the
aggregator." Worth it for high-value chains; not worth it for the
minimum-PQ tier.
4. Pulsar has committed KAT vectors (lux/pulsar/vectors/*.json)
and cross-impl validation against circl. Corona's KAT vectors are
pending; the audit harness produced the seed for the first set.
The audit recommends: PQ-fast = BLS + Pulsar (cheap, FIPS 204
interoperable). PQ-strict adds Corona on top for chains that need
the never-trust-aggregator property — the latency cost (~100×) buys
a real security upgrade (threshold lattice without aggregator trust),
not a redundant lane.
A chain that does not need a classical fast-path (post-PQ-transition
L1, sovereign anchor chain) should not be forced to operate BLS
infrastructure. The strict-PQ-* prefix is the explicit operator
declaration that this chain does not consume BLS-verifiable certs.
LP-017 v1 implicitly required BLS in every profile; this LP relaxes
that.
This matches the sig-pack matrix bench dimensions (LP-203 §Bench):
each row of the bench is one of the 7 valid leg-sets. Specs and
benches share the same enumeration, so any new leg added later expands
both surfaces identically.
None. New final Lux network; no legacy cert_mode / cert_timeout_ms
standalone knobs to migrate from. The seven (Mode, Variant) wire
names are the only operator-facing surface.
LP-017 v1 codenames remain as INTERNAL identifiers — code that
references polaris.go's PolarisLegs struct or IsPolaris /
HasHashBased predicates is unaffected: those are internal-API
surfaces, not operator-facing. CertPolicy.ToV1Predicate() is the
single bridge.
A chain genesis published before activation cannot use the v2
CertPolicy field. Pre-activation chains are on the pre-Quasar
Edition Lux network and are out of scope for this LP entirely (per
LP-202 §Status).
A conformant implementation MUST:
1. Parse all 7 wire names (PQ-off, PQ-fast, PQ-strict, PQ-heavy,
strict-PQ-fast, strict-PQ-strict, strict-PQ-heavy) from
quasar.cert_policy YAML into a CertPolicy value; reject any
other string.
2. Refuse to launch the chain when CertPolicy.Validate() returns
an error — specifically when any of the four validation rules
(Fallback <= Mode, Variant=Strict requires Mode>=PQ-fast,
TimeoutMs >= 2 * expected_floor_latency(Mode), Fallback
itself valid under the same Variant) fails.
3. Produce a cert whose observed leg set is a superset of the
policy's Mode required-leg set (or report tier degradation per
LP-202 with the cert observable at Fallback).
4. Return ErrCertPolicyLegMissing when the operator's Mode
required set cannot be satisfied within TimeoutMs AND no
Fallback tier is acceptable.
5. Map the v2 CertPolicy to the internal v1 codename predicate
(IsDoubleLattice for Mode=PQ-strict; IsPolaris for
Mode=PQ-heavy) when interoperating with v1 relying parties.
6. Verify the leg verify pipeline (LP-203 §Specification) only
dispatches kernels for legs present in the policy's required set —
no wasted GPU compute on legs the operator did not request.
Tests live in ~/work/lux/consensus/config/cert_policy_test.go (new —
parse, Validate(), RequiredLegs() table tests across all seven
configurations) and `~/work/lux/consensus/protocol/quasar/
cert_roundtrip_test.go` (extended to cover the 7 configurations).
The operator-facing CertPolicy lives alongside the existing v1
internal codename enums (pq_mode.go's PQModePulsar, PQModeQuasar,
etc.). One file, one decision record:
~/work/lux/consensus/config/cert_policy.go (new) — CertPolicy struct, PQMode + PQVariant enums, Parse(s string) (CertPolicy, error),
(cp CertPolicy) Validate() error, `(cp CertPolicy) RequiredLegs()
[]LegName, (cp CertPolicy) WireName() string` (the seven-name table
above), (cp CertPolicy) ToV1Predicate() func(*QuasarCert) bool
(maps to polaris.go's IsPolaris / IsDoubleLattice / HasHashBased).
~/work/lux/consensus/config/cert_policy_test.go (new) —validation table tests for the four rules; round-trip parse of all
seven canonical wire names; the eighth-slot refusal.
~/work/lux/consensus/config/pq_mode.go — internal codenamepredicates remain unchanged; this file does NOT own the operator-
facing names.
~/work/lux/consensus/protocol/quasar/polaris.go:9-18 — internal codename predicates remain; CertPolicy.ToV1Predicate() dispatches
here.
~/work/lux/consensus/protocol/quasar/types.go — QuasarCert struct unchanged; the operator's CertPolicy is a runtime config,
not a wire-format change.
Genesis plumbing:
~/work/lux/node/genesis/cert_policy.go (new) — reads quasar.cert_policy from genesis YAML; calls Validate(); refuses
to start the chain on validation error.
chain.yaml — each Tier-1 L1 declares quasar.cert_policy in its genesis. Each Tier-2 chain-VM in chains: may declare its
own cert_policy: block (LP-204 inheritance — default is parent
L1's policy).
The mode ladder does not change the cryptographic guarantees of any
individual leg. Mode security is the floor of the strongest leg in the
required set — the same property LP-017 v1 stated for cert profiles.
The v2 mode names declare posture explicitly. An operator who picks
PQ-off is making an informed declaration that their threat model
excludes store-now-decrypt-later adversaries; the v1 codename "Pulsar"
did not make that declaration nearly as legibly. This is a security
property of the SPEC SURFACE, not the protocol — but operator-error
reduction is a real security concern at the human layer.
The pure-PQ variants drop BLS. A chain at strict-PQ-* cannot
interoperate with any relying party that requires BLS in the cert; the
relying party will see an empty BLS leg and degrade per LP-202. This
is intended — pure-PQ chains are explicit about not consuming BLS.
Copyright and related rights waived via CC0.