TALUS threshold ML-DSA built: dealerless nonce DKG + CEF + REAL CSCP CarryCompare secure-comparison closes PULSAR-V13-W-LEAK (semi-honest, simulation-proven) — no node forms w0/w even transiently. FindHint + ReleaseGate bound malicious deviation to liveness (never forge/leak). Open items narrowed to Residual A (malicious-secure CSCP + networked non-simulation MPC) and Residual B (dealerless byte-FIPS-204 key DKG proven unreachable via S_eta bound -> trusted-dealer keygen; Corona carries permissionless). BLOCKERS reconciled, README/LLM/CHANGELOG/PROOF-CLAIMS refreshed; tag refs -> v1.2.0.
16 KiB
Pulsar -- Agent Knowledge Base (formerly Pulsar-M)
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-M → Pulsar
Per the Lux family rebrand, the three threshold libraries are:
| Name | Lattice | Class | Source path going forward |
|---|---|---|---|
| Pulsar (this repo, was Pulsar-M) | 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-M 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 Pulsar-MPC (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-M verifier).
Cross-repo dependencies
- Depends on:
golang.org/x/crypto/sha3(cSHAKE / KMAC primitives)luxfi/crypto/pq/mldsa/mldsa65(FIPS 204 verifier — Pulsar-M 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.