Files
zeekay 166f23d951 pulsar: TALUS docs to v1.2.0 — PULSAR-V13-W-LEAK closed (semi-honest), residuals scoped
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.
2026-06-27 14:14:46 -07:00

16 KiB
Raw Permalink Blame History

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)

  1. Push pre-existing work first to avoid entangling pre-migration commits with the rename:
    • luxfi/corona push commits ahead
    • luxfi/pulsar commit + push LLM.md edit
    • luxfi/p3q commit + push LLM.md edit
    • luxfi/pulsar-m commit Large*, luxround, largeshamir, spec, proofs and push as v0.2.0
    • luxfi/precompile commit + push the new pulsar/ precompile
  2. Stand up luxfi/corona by mirroring current luxfi/pulsar contents. Preserve all tags. Cut rename commit as v0.2.0 on luxfi/corona. Leave luxfi/pulsar as redirect/archive marker for downstream go.mod consumers.
  3. 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 as v0.2.0. Archive luxfi/pulsar-m with README redirect.
  4. Update consumers' go.mod (luxfi/consensus, luxfi/precompile): replace github.com/luxfi/pulsar v0.1.0 with github.com/luxfi/pulsar v0.2.0. Update imports + go mod tidy.
  5. Optional: stand up luxfi/quasar as the PQ event horizon meta-repo. Imports luxfi/pulsar, luxfi/corona, luxfi/p3q, luxfi/crypto/bls, luxfi/crypto/mldsa. Wire precompile/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 push to any of the four repos
  • gh repo rename luxfi/pulsar luxfi/corona
  • gh repo create luxfi/corona
  • gh repo archive luxfi/pulsar-m
  • Updating luxfi/consensus/go.mod and go.sum to switch from pulsar-m to pulsar (busts go.sum hashes)
  • Cutting new tags (v0.2.0 on 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 as threshold/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 as consensus/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 uses crypto/mldsa directly).
    • no R-LWE Pulsar / Corona dep needed (precompile/corona covers that path).

Migration sequence

Exact commit order (each step gated by Verification below):

  1. Stand up luxfi/corona repo (mirror current luxfi/pulsar contents, all tags preserved).
  2. Tag luxfi/corona v0.2.0.
  3. In threshold / warp / consensus / node: update go.mod + imports to point at luxfi/corona for R-LWE.
  4. Tag each consumer (threshold, warp, consensus, node).
  5. Bump pulsar-m → cut as luxfi/pulsar v0.2.0 (M-LWE code moves into luxfi/pulsar; preserve pre-v0.2.0 tags as historical R-LWE).
  6. In consensus / node / precompile: update go.mod imports from luxfi/pulsar-mluxfi/pulsar.
  7. Tag each.
  8. Archive luxfi/pulsar-m with 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 0
  • go test ./... exits 0
  • go mod tidy produces 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 / distributed w1 (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) drives CEFComputeW1cscpSecureHighBitsVec, so NO node forms w0 or the full commitment w even transiently (only masked openings {valid, maskC, w1}). Proven leak-free by TestCSCP_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 ≥ 2T1, enforced by TalusMinPartiesMPC / newCSCPCtx / cscpSecureHighBitsVec / bgwMulShares). Signature byte-identical across both.
  • Stock FIPS-204. A TALUS signature verifies byte-equal under UNMODIFIED cloudflare/circl mldsa65.Verify / mldsa87.Verify (TestTalus_MPC_EndToEnd_StockVerify, TestTalus_MPC_Mode87).
  • Malicious deviation = liveness-only. FindHint (recovers the FIPS hint from public w' = 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.goErrDealerlessByteFIPSUnreachable). 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-CMA
    • scaling.tex -- Concrete claims at N* = 1,111,111
    • output-interchangeability.tex -- Class N1 manifesto
    • dkg-soundness.tex -- DKG soundness + share privacy
    • reshare-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/circl FIPS 204 today (19 / 19 N1 subtests at test/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

  1. Patch-bump only (v0.1.0v0.1.1); never minor/major without explicit approval.
  2. Any deviation from the SHAKE / cSHAKE / KMAC profile is a forking decision — it breaks output-interchangeability with FIPS 204.
  3. KAT vectors are CI-pinned; never edit without rerunning the generator and committing the new vectors in the same commit.
  4. TargetCommitteeSize = 1_111_111 is the canonical extreme committee target. Change requires updating the constant in params.go, the proofs in ~/work/lux/proofs/pulsar-m/scaling.tex, and the spec in spec/pulsar-m.tex section "Large committees".
  5. Default to FieldDefault when constructing a session; only pin FieldGF257 or FieldGFq for KAT replay where wire-format determinism is required.