references.bib gave ePrint 2024/1113 the title "Corona: Practical Two-Round Threshold Signatures from Learning with Errors". The paper is "Ringtail: Practical Two-Round Threshold Signatures from Learning with Errors", by the six authors the entry already named correctly. A title is the authors' words. The file's own header asks for exactly this — "verified against https://eprint.iacr.org... Do not paraphrase or guess". Ringtail is their scheme. Corona is Lux's implementation over Ring-LWE; Pulsar retargets the same two-round structure to Module-LWE for FIPS 204. The prose and the citation key now say so, and this spec is the NIST MPTC submission, so it is the last place to get it wrong. patent-notes.tex stated "Corona's open-source repo is Apache-2.0 with no asserted patent claims". Corona is under the Lux Ecosystem License v1.2, which reserves commercial use — no Apache grant and no Apache §3 patent grant. The surrounding paragraph had been flattened by a rename into "Pulsar ... is derivative of Pulsar" and "Pulsar (and therefore Pulsar) is a fork"; it now names Corona and Ringtail where each is meant. Dropped the residual Pulsar-M spelling, including the naming rule that forbade writing "Pulsar" and required writing "Pulsar". Co-authored-by: Hanzo Dev <[email protected]>
16 KiB
Pulsar -- Agent Knowledge Base (formerly Pulsar)
Repository (current): github.com/luxfi/pulsar
Repository (target): github.com/luxfi/pulsar
Latest Tag: v1.2.0
Status: TALUS threshold ML-DSA BUILT; PULSAR-V13-W-LEAK CLOSED (semi-honest, simulation-proven). Not yet FIPS-validated; open residuals = the malicious-secure CSCP layer + a networked MPC deployment (Residual A) and dealerless-key impossibility ⇒ trusted-dealer keygen + Corona-carries-permissionless (Residual B). EasyCrypt + Lean machine-check on host (gate ec-machine-check.sh, 14/14); TALUS / no-leak BCC threshold path interop-verified byte-equal under CIRCL + pq-crystals.
Rename in progress: Pulsar → Pulsar
Per the Lux family rebrand, the three threshold libraries are:
| Name | Lattice | Class | Source path going forward |
|---|---|---|---|
| Pulsar (this repo, was Pulsar) | Module-LWE | NIST MPTC N1+N4 | ~/work/lux/pulsar |
| Corona (was the prior R-LWE Pulsar) | Ring-LWE | NIST MPTC S1+S4 | ~/work/lux/corona |
| Corona (unchanged) | Ring-LWE | academic upstream + Lux lifecycle DKG expansions | ~/work/lux/corona |
Until the cross-repo moves land, this repo continues at luxfi/pulsar-m
and the existing luxfi/pulsar v0.1.5 (R-LWE) keeps shipping. The
rename is a naming change, not a behaviour change — wire formats,
KAT vectors, and FIPS 204 byte-equality guarantees are unchanged.
Family migration plan
| Going-forward name | Lattice | Class | Where it lives now | Where it lives after |
|---|---|---|---|---|
| Pulsar | Module-LWE / FIPS 204 | NIST MPTC N1 + N4 | github.com/luxfi/pulsar |
github.com/luxfi/pulsar |
| Corona | Ring-LWE | NIST MPTC S1 + S4 | github.com/luxfi/pulsar (current R-LWE production fork) |
github.com/luxfi/corona |
| Corona | Ring-LWE | academic upstream + Lux lifecycle DKG expansions | github.com/luxfi/corona |
github.com/luxfi/corona (unchanged) |
| Quasar | composition layer | -- | consensus/protocol/quasar/ (sub-protocol) |
optional standalone github.com/luxfi/quasar as the PQ event horizon |
Quasar — PQ event horizon
Quasar is proposed as the top-level meta-package that consumes every
PQ primitive (Pulsar threshold ML-DSA, Corona threshold R-LWE, P3Q
STARK rollup, BLS aggregate, ML-DSA single-party) and exposes a
unified Verify(cert) interface. Consensus's existing
consensus/protocol/quasar/ already implements this as a sub-protocol;
promoting it to a standalone repo would let EVM precompiles
(precompile/quasar/ at 0x0604 per the LP-4200 table) and external
relying parties consume the same verification surface without
depending on the full consensus stack.
Migration order (when push authorised)
- Push pre-existing work first to avoid entangling pre-migration commits
with the rename:
luxfi/coronapush commits aheadluxfi/pulsarcommit + push LLM.md editluxfi/p3qcommit + push LLM.md editluxfi/pulsar-mcommitLarge*,luxround,largeshamir, spec, proofs and push asv0.2.0luxfi/precompilecommit + push the newpulsar/precompile
- Stand up
luxfi/coronaby mirroring currentluxfi/pulsarcontents. Preserve all tags. Cut rename commit asv0.2.0onluxfi/corona. Leaveluxfi/pulsaras redirect/archive marker for downstream go.mod consumers. - Move pulsar-m contents to
luxfi/pulsar: delete R-LWE content (preserved in corona), copy M-LWE content from pulsar-m, bump module path. Cut asv0.2.0. Archiveluxfi/pulsar-mwith README redirect. - Update consumers' go.mod (
luxfi/consensus,luxfi/precompile): replacegithub.com/luxfi/pulsar v0.1.0withgithub.com/luxfi/pulsar v0.2.0. Update imports +go mod tidy. - Optional: stand up
luxfi/quasaras the PQ event horizon meta-repo. Importsluxfi/pulsar,luxfi/corona,luxfi/p3q,luxfi/crypto/bls,luxfi/crypto/mldsa. Wireprecompile/quasar/(0x0604) to consume it.
Destructive-action checklist (push phase)
Operations modify shared / production systems and need explicit user confirmation per auto-mode safety policy:
git pushto any of the four reposgh repo rename luxfi/pulsar luxfi/coronagh repo create luxfi/coronagh repo archive luxfi/pulsar-m- Updating
luxfi/consensus/go.modandgo.sumto switch frompulsar-mtopulsar(busts go.sum hashes) - Cutting new tags (
v0.2.0on renamed repos)
Cleanliness audit (local snapshot)
| Repo | Status | Action |
|---|---|---|
luxfi/pulsar-m |
modified + untracked (GF(q) Large*, luxround helpers, spec, proofs) |
Commit cleanly; archive when contents move |
luxfi/pulsar |
LLM.md rename note modified | Commit; hosts M-LWE post-migration |
luxfi/corona |
commits ahead + modified + untracked | Push commits first; merge/discard locally |
luxfi/p3q |
LLM.md modified | Commit; v0.0.1 pushed |
luxfi/consensus |
Clean | go.mod bump after migration |
luxfi/precompile |
New precompile/pulsar/ (LP-4200 0x012204) |
Commit + run CI |
luxfi/corona |
Does not exist | Create from current luxfi/pulsar R-LWE contents |
luxfi/quasar |
Does not exist | Optional standalone repo |
Module-pin reconciliation (pre-rename gate)
Silent-swap hazard: threshold/go.mod and warp/go.mod both pin
github.com/luxfi/pulsar v0.1.0-rc1-pq-consensus-freeze with
replace github.com/luxfi/pulsar => ../pulsar. After the rename
../pulsar will contain M-LWE code (was R-LWE), so existing
R-LWE-API call sites in threshold/warp will fail to compile. The
go.mod surgery list below MUST land before any directory rename:
threshold/go.mod:require github.com/luxfi/corona v0.2.0(was:github.com/luxfi/pulsar v0.1.0-rc1-pq-consensus-freeze)replace github.com/luxfi/corona => ../corona(was:=> ../pulsar)- UPDATE all imports
github.com/luxfi/pulsar/...→github.com/luxfi/corona/...in source.
warp/go.mod: same pattern asthreshold/go.mod.consensus/go.mod:require github.com/luxfi/pulsar v0.2.0(was:github.com/luxfi/pulsar v0.1.0)require github.com/luxfi/corona v0.2.0(was:github.com/luxfi/pulsar v0.1.5)- UPDATE imports
github.com/luxfi/pulsar/...→github.com/luxfi/pulsar/...in source. - UPDATE imports
github.com/luxfi/pulsar/...(R-LWE) →github.com/luxfi/corona/...in source.
node/go.mod: same asconsensus/go.mod(indirect deps follow).precompile/go.mod:- add
require github.com/luxfi/pulsar v0.2.0(currently has no pulsar dep — Blue's commit didn't add it because the precompile usescrypto/mldsadirectly). - no R-LWE Pulsar / Corona dep needed (
precompile/coronacovers that path).
- add
Migration sequence
Exact commit order (each step gated by Verification below):
- Stand up
luxfi/coronarepo (mirror currentluxfi/pulsarcontents, all tags preserved). - Tag
luxfi/corona v0.2.0. - In
threshold/warp/consensus/node: updatego.mod+ imports to point atluxfi/coronafor R-LWE. - Tag each consumer (
threshold,warp,consensus,node). - Bump
pulsar-m→ cut asluxfi/pulsar v0.2.0(M-LWE code moves intoluxfi/pulsar; preserve pre-v0.2.0tags as historical R-LWE). - In
consensus/node/precompile: updatego.modimports fromluxfi/pulsar-m→luxfi/pulsar. - Tag each.
- Archive
luxfi/pulsar-mwith README redirect.
Verification gate
After each step in the Migration sequence, the affected consumer repos MUST compile + test green before the next step proceeds:
go build ./...exits 0go test ./...exits 0go mod tidyproduces no diff- CI green on the tagged commit
A red gate blocks the next step. No silent skips; document the failure and resolve before advancing.
Purpose (one-liner)
Threshold ML-DSA: a two-round lattice kernel + one-round online signing (TALUS) and DKG whose generated signatures are verifiable by unmodified FIPS 204 ML-DSA verification. Targeting NIST MPTC Class N1 (signing) + N4 (ML keygen / DKG).
Pulsar is the Module-LWE sibling of luxfi/pulsar (Ring-LWE). Pulsar's
two-round kernel is transplanted onto ML-DSA-65's polynomial-vector-over-R_q
algebra so the aggregated signature is bit-identical to a single-party
FIPS 204 signature on the same message + public key; TALUS (v1.2.0) adds
one-round online signing on top.
TALUS — threshold ML-DSA (v1.2.0)
TALUS is the threshold ML-DSA scheme on Pulsar's two-round lattice kernel,
adding one-round online signing. Source: ref/go/pkg/pulsar/talus*.go.
- Three pillars. Dealerless Shamir nonce DKG (
talus_nonce_dkg.go), CEF = Carry Elimination Framework / distributedw1(talus_cef.go), CSCP = the CarryCompare secure-comparison protocol (talus_cscp.go). BCC = Boundary Clearance Condition. These route around the impossibility of FROST-style additive-nonce threshold ML-DSA (HighBits/r0/carry is non-linear). - W-LEAK closed (semi-honest, simulation-proven). Commit
530c24e: the REAL CSCP secure-comparison circuit (bit-decompose + carry-save bitAdd + prefix bitLT over BGW multiplication, coefficient-exact vs FIPS Decompose) drivesCEFComputeW1→cscpSecureHighBitsVec, so NO node formsw0or the full commitmentweven transiently (only masked openings {valid, maskC, w1}). Proven leak-free byTestCSCP_MultiNode_LeakFree/TestCSCP_LeakFree_Structural/TestCSCP_MaskOpen_HidesW— but in an in-process N-party SIMULATION (NOT a networked/deployed MPC, NOT malicious-secure). Always describe as semi-honest, simulation-proven. - Two profiles. Pulsar-TEE (TEE-backed
w1) and PulsarPC (honest-majority N ≥ 2T−1, enforced byTalusMinPartiesMPC/newCSCPCtx/cscpSecureHighBitsVec/bgwMulShares). Signature byte-identical across both. - Stock FIPS-204. A TALUS signature verifies byte-equal under UNMODIFIED
cloudflare/circlmldsa65.Verify/mldsa87.Verify(TestTalus_MPC_EndToEnd_StockVerify,TestTalus_MPC_Mode87). - Malicious deviation = liveness-only.
FindHint(recovers the FIPS hint from publicw' = A·z − c·t1·2^d) +TalusReleaseGate(mandatory stock FIPS-204 verify, never releases a failed sig) bound any malicious CSCP deviation to abort/retry — never forge or leak (TestCSCP_WrongW1_CaughtByFindHint). This is Residual A (the malicious-secure CSCP layer + a networked MPC deployment, un-built). - KEYGEN is trusted-dealer (Residual B). Dealerless byte-FIPS-204 KEY DKG
is proven unreachable: FIPS-204 KeyGen samples s1,s2 from S_η = {‖p‖∞ ≤ η};
a dealerless sum of N ≥ 2 contributions has ℓ∞-support up to N·η > η, breaking
BCC byte-validity (‖c·s2‖∞ ≤ N·β > β) and the FIPS-204 security-equivalence
(
distributed_bcc_dkg.go→ErrDealerlessByteFIPSUnreachable). KEYGEN stays trusted-dealer; the permissionless guarantee is carried by Corona (corona v0.8.0, natively dealerless via Pedersen DKG over R_q) in the Quasar AND-mode cert.
Canonical profile + scheme constants
- Hash family: SHAKE / cSHAKE / KMAC256 / TupleHash256 (FIPS 202 + SP 800-185).
- Sharing: byte-wise Shamir, two regimes:
- GF(257) for small committees (n ≤ 256), 64-byte wire share.
- GF(q) for large committees (n ≤ q-1 = 8,380,416), 128-byte wire
share. Canonical extreme committee target:
TargetCommitteeSize = 1_111_111(seven 1s).
- Curve / lattice: same Module-LWE parameters as ML-DSA-65.
- Round count: two-round kernel (commit + reveal); TALUS adds one-round online signing.
- Abort model: identifiable.
- Arithmetic width: uint32 lanes with uint64 accumulators. uint128 / uint256 not required (reserved for the Z-Chain SNARK side).
Recent significant changes
| commit-like SHA | Impact |
|---|---|
170a705 |
NIST MPTC submission readiness — benchmarks + CI gates |
ced8779 |
KAT vectors for keygen / sign / verify / threshold / dkg |
cff8813 |
Proactive resharing with beacon-randomized quorum |
ddef135 |
Threshold sign (2-round commit + reveal) |
d0ae91e |
Epoch DKG with identifiable abort |
14481d6 |
Byte-wise Shamir secret sharing over GF(257) |
4d0ff1f |
Keygen + sign + verify (single-party) |
6cf9e5b |
Bootstrap NIST MPTC submission package |
| (pending) | GF(q) Shamir + N=1,111,111 target + spec system-model + parameters complete |
Active versions
- Repo:
v1.2.0(current; TALUS threshold ML-DSA + PULSAR-V13-W-LEAK closed semi-honest). - Pinned by:
luxfi/consensus v1.23.5+(finality verify path replaces the placeholder Pulsar verifier).
Cross-repo dependencies
- Depends on:
golang.org/x/crypto/sha3(cSHAKE / KMAC primitives)luxfi/crypto/pq/mldsa/mldsa65(FIPS 204 verifier — Pulsar outputs must round-trip through it byte-equal)
- Consumed by:
luxfi/consensus/protocol/quasar(finality path) — F107/F109 closure.- NIST MPTC submission package (
spec/LaTeX).
Where to look for X
- Keygen / sign / verify (single-party):
ref/go/pkg/pulsar/keygen.go,sign.go,verify.go. - 2-round threshold sign:
ref/go/pkg/pulsar/threshold.go - Epoch DKG (identifiable abort):
ref/go/pkg/pulsar/dkg.go - Proactive reshare (beacon randomization):
ref/go/pkg/pulsar/reshare.go - Small-committee Shamir (GF(257)):
ref/go/pkg/pulsar/shamir.go - Large-committee Shamir (GF(q)):
ref/go/pkg/pulsar/shamir_gfq.go,largeshamir.go - Field auto-selection logic:
ref/go/pkg/pulsar/types.go:resolveField - KAT vectors:
vectors/ - LaTeX submission spec:
spec/pulsar-m.tex(full; not a stub),spec/parameters.tex,spec/system-model.tex,spec/security-games.tex - Benchmarks (MPTC requirement):
bench/ - CT (constant-time) guards:
ct/
Where to find proofs
- LaTeX theorem statements + proofs:
~/work/lux/proofs/pulsar-m/unforgeability.tex-- TS-UF reduction to MLWE+MSIS+ML-DSA EUF-CMAscaling.tex-- Concrete claims at N* = 1,111,111output-interchangeability.tex-- Class N1 manifestodkg-soundness.tex-- DKG soundness + share privacyreshare-preservation.tex-- Reshare preserves pk + soundness + privacy
- Lean 4 mechanization skeletons:
~/work/lux/proofs/lean/Crypto/Pulsar_M/Unforgeability.lean,Shamir.lean,OutputInterchange.lean
Submission notes
- Submission package deadline (NIST MPTC first call): 2026-Nov-16.
- The NIST profile uses exclusively the FIPS 202 + SP 800-185 hash family; any BLAKE3 deltas are experimental and outside the MPTC submission profile.
- Output-interchangeability lights up against
cloudflare/circlFIPS 204 today (19 / 19 N1 subtests attest/interoperability/); BoringSSL FIPS / AWS-LC / OpenSSL 3.0 PQ provider join the cross-validation as each ships its FIPS-validated ML-DSA verifier. - Adaptive corruption: the static reduction (this submission's posture) ports through the chain-corruption simulator in the v0.2 audit cycle.
- Cross-message restart hybrid: the v0.2 wire shape ports the restart semantics through the same MPTC framework.
Rules
- Patch-bump only (
v0.1.0→v0.1.1); never minor/major without explicit approval. - Any deviation from the SHAKE / cSHAKE / KMAC profile is a forking decision — it breaks output-interchangeability with FIPS 204.
- KAT vectors are CI-pinned; never edit without rerunning the generator and committing the new vectors in the same commit.
TargetCommitteeSize = 1_111_111is the canonical extreme committee target. Change requires updating the constant inparams.go, the proofs in~/work/lux/proofs/pulsar-m/scaling.tex, and the spec inspec/pulsar-m.texsection "Large committees".- Default to
FieldDefaultwhen constructing a session; only pinFieldGF257orFieldGFqfor KAT replay where wire-format determinism is required.