Commit Graph
31 Commits
Author SHA1 Message Date
zeekay 847e5ddee9 proofs: write EC theories (Corona_N1, N4, refinement chain) -- admit budget 0/13
13 EasyCrypt theories mirroring Pulsar's Tier A layout:

  Corona_N1.ec                       master byte-equality theorem
  Corona_N4.ec                       reshare public-key preservation
  Corona_N1_Memory.ec                byte-memory model + frame laws
  Corona_N1_Signature_Codec.ec       signature codec
  Corona_N1_{Combine,Sign}_Layout.ec input/output layouts
  Corona_N1_{Combine,Sign}_Refinement.ec  byte-walk + sep + frame axioms
  Corona_N1_{Combine,Sign}_Wrapper.ec     wrapper bridges
  Corona_N1_Extracted.ec             IMPLEMENTATION-BACKED theorem
  lemmas/RLWE_Functional.ec          in-house Boschini Sign mechanization
  lemmas/Corona_CT.ec                CT obligations

Admit budget: 0/0 across the 13-file set. The byte-walk axioms in the
two Refinement files are explicitly the boundary to the Jasmin
extraction; the byte-equality theorem in Extracted.ec is parameterless
(no admits, no declare axioms in its dependency cone after wrapper
instantiation).

Refines: ~/work/lux/corona/sign/sign.go + threshold/threshold.go.
Cites: Boschini et al. ePrint 2024/1113 §3-§5; ~/work/lux/proofs/lean.
Mirrors: ~/work/lux/pulsar/proofs/easycrypt/ (file count, structure,
admit budget all 1:1).
2026-05-19 08:37:57 -07:00
zeekay 7c5b3414ce submission: write AXIOM-INVENTORY + FIPS-TRACEABILITY + CRYPTOGRAPHER-SIGN-OFF (Tier A doc-shape closure)
Three Tier-A-required submission docs that were honestly omitted in
the v0.5.0 scaffold per the cryptographer agent's directive ("don't
fabricate proof claims that don't exist"):

- AXIOM-INVENTORY.md: enumerates construction-level + implementation-level
  axioms with explicit closure plans. EC theory shells are roadmap v0.7.0;
  this doc establishes the inventory the eventual proofs will discharge.
- FIPS-TRACEABILITY.md: Boschini ePrint 2024/1113 + IEEE S&P 2025
  section → code mapping. R-LWE has no FIPS standard; Boschini paper
  is the construction-level normative reference.
- CRYPTOGRAPHER-SIGN-OFF.md: APPROVED WITH GATES. Verdict mirrors
  Pulsar's v1.0.7 sign-off structure. Gates: GATE-1 EC theory shells,
  GATE-2 Lean ↔ EC bridge, GATE-3 dudect 10⁹ samples, GATE-4 external
  audit. All on v0.7.0 / v0.8.0 roadmap.

Tier label honest assessment: **Tier A documentation shape complete**;
the algorithmic-soundness gates inherit from Boschini paper, the
formal-methods gates are explicitly roadmap-tracked, not fabricated.
This positions Corona for NIST MPTC v0.2 submission window with full
review-ready doc package.
2026-05-19 06:53:34 -07:00
zeekay 21314bb643 Merge origin/main into submission scaffold (resolve LICENSING: take patent-protected tier; merge patent posture pointer from scaffold) 2026-05-18 23:12:37 -07:00
zeekay fbe2bc5a88 submission: scaffold NIST MPTC v0.2 submission package mirroring Pulsar template
Adds the NIST MPTC Class N1 + N4 submission package for Corona (R-LWE
threshold signing). Pattern mirrors luxfi/pulsar (M-LWE byte-equal
FIPS 204 path), adapted HONESTLY to Corona's lighter proof tier:

- SUBMISSION.md / NIST-SUBMISSION.md — cover sheet + 1-page exec
  summary. Cite Boschini-Kaviani-Lai-Malavolta-Takahashi-Tibouchi
  ePrint 2024/1113 (IEEE S&P 2025) as the underlying construction.
  Construction-level N1 claim (no FIPS standard target for R-LWE
  threshold — Boschini et al. IS the spec). N4 = (A, bTilde)
  preserved across reshare within a key era.
- SPEC.md — standalone construction specification consolidating
  existing material (papers/lp-073-pulsar/, DESIGN.md). Full
  single-doc spec/corona.tex is roadmap v0.6.0.
- PATENTS.md — royalty-free patent grant + defensive termination.
  Claim scope EXCLUDES the published Boschini et al. construction;
  claims limited to Corona's production lifecycle additions
  (Pedersen DKG over R_q, proactive resharing, activation cert
  circuit-breaker, constant-time Pedersen slot equality, hash-suite
  injection).
- PROOF-CLAIMS.md — HONEST framing. Corona ships NO mechanized
  refinement (no EasyCrypt, no Lean, no Jasmin) — unlike Pulsar.
  Correctness reduces to code review + KAT cross-runtime byte-equality
  + academic construction analysis + per-path constant-time static
  audit. Mechanized refinement is roadmap v0.7.0.
- TRUSTED-COMPUTING-BASE.md — implementation TCB. Structurally
  simpler than Pulsar's; no EC/Lean/Jasmin tools in scope.
- DEPLOYMENT-RUNBOOK.md — operator-facing trust-model disclosure.
- LICENSING.md / CONTRIBUTING.md / SECURITY.md — standard NIST-MPTC
  artifacts.
- docs/mptc/ — submission-package docs subdir (kept separate from
  docs/ Next.js docs site):
  - evaluation.md, ietf-draft-skeleton.md, nist-mptc-category.md,
    patent-claims.md, design-decisions.md, family-architecture.md,
    threat-model.md
- scripts/{build,test,bench,gen_vectors,check-high-assurance,
  cut-submission}.sh — submission gates mirroring Pulsar's
  orchestrator pattern, adapted to Corona's reality (no EC/Lean/
  Jasmin checks because the artifacts do not exist).
- LLM.md + CHANGELOG.md — updated with submission scaffolding
  context and v0.5.0 entry. NO fabricated prior history; CHANGELOG
  v0.5.0 entry covers only the actual submission documentation.

DOES NOT FABRICATE: no CRYPTOGRAPHER-SIGN-OFF (Pulsar has one;
Corona's lighter proof tier does not yet warrant it — roadmap
v0.7.0+v0.8.0). No AXIOM-INVENTORY or FIPS-TRACEABILITY (Corona is
not anchored to a FIPS standard). No proof claims Corona does not
actually have.

Build/test verification: GOWORK=off go build ./... clean; sign/,
primitives/, hash/ unit tests pass; scripts/build.sh + scripts/
check-high-assurance.sh exit 0.
2026-05-18 23:10:13 -07:00
zeekayandGitHub b0e8c0e94e chore: bump Go toolchain to 1.26.3 (#2)
Pin Go version to 1.26.3 across go.mod, CI workflows, and Dockerfiles
for canonical alignment with the rest of the luxfi/* stack.
2026-05-16 16:42:40 -07:00
zeekayandGitHub b8019e9479 Merge pull request #1 from luxfi/licensing/canonical-pointer
docs: add LICENSING.md pointer to canonical Lux IP strategy
2026-05-15 16:40:43 -07:00
zeekay f22502937f docs: add LICENSING.md pointing at canonical Lux IP strategy
Single LICENSING.md file referencing the canonical three-tier IP and
licensing strategy at github.com/luxfi/.github/blob/main/profile/README.md.

LICENSE file is unchanged; this only adds a navigational pointer.
2026-05-15 16:40:36 -07:00
zeekay 27692894fe threshold: add parallel VerifyBatch — N-signature throughput for consensus
Corona signatures are Ring-LWE (C, Z, Delta) ring-polynomial triples,
not FIPS 204 byte-equal (that's Pulsar's Module-LWE sibling). Single
Verify is the only place this package touches the sign.Verify
predicate; VerifyBatch composes it across N (groupKey, message,
signature) tuples in parallel via a GOMAXPROCS-bounded worker pool.

Public surface added:
  - VerifyBatch(gks, msgs, sigs) -> ([]bool, error)
  - VerifyBatchAll(gks, msgs, sigs) -> (bool, error)
  - ErrBatchSizeMismatch

Pure Go: NO CGO / accel dep. A future Metal/CUDA NTT-batch kernel
over the polynomial-arithmetic hotspot would live in luxfi/accel
behind the same byte interface; consumers wanting GPU dispatch call
accel directly against the wire bytes. This file is the portable
fallback everyone gets for free.

Tests (GOWORK=off go test ./threshold/ -run TestVerifyBatch):
  TestVerifyBatch_AllValid            (n=4, all valid)      PASS
  TestVerifyBatch_OneCorrupt          (message swap @1)     PASS
  TestVerifyBatch_StructuralMismatch  (slice len mismatch)  PASS
  TestVerifyBatch_Empty                                     PASS
Full ./threshold suite: ok 2.068s.
2026-05-15 01:42:48 -07:00
zeekay 080dfe207e corona: don't mix — QUASAR-PULSAR-* prefixes -> QUASAR-CORONA-* in Corona's table
Per user directive: don't mix Pulsar and Corona naming. Corona's design
doc was documenting Pulsar tag prefixes for what are actually Corona's
own rows in the Quasar consensus tag scheme. Fixed:

  QUASAR-PULSAR-BUNDLE-v1   -> QUASAR-CORONA-BUNDLE-v1
  QUASAR-PULSAR-SIGN1-v1    -> QUASAR-CORONA-SIGN1-v1
  QUASAR-PULSAR-SIGN2-v1    -> QUASAR-CORONA-SIGN2-v1
  QUASAR-PULSAR-COMBINE-v1  -> QUASAR-CORONA-COMBINE-v1
  QUASAR-PULSAR-REFRESH-v1  -> QUASAR-CORONA-REFRESH-v1
  QUASAR-PULSAR-RESHARE-v1  -> QUASAR-CORONA-RESHARE-v1
  QUASAR-PULSAR-REANCHOR-v1 -> QUASAR-CORONA-REANCHOR-v1

Plus Lane column for these rows: Pulsar -> Corona.

Preserved legitimate Pulsar cross-references: sister-kernel comparison,
fork lineage (Corona forked from Pulsar), shared LSS lifecycle concepts.
Those documentation references aren't mixing — they're describing
Corona's relationship to Pulsar.
2026-05-13 15:39:32 -07:00
zeekay 1b0ad93f2a corona: doc drift cleanup — CHANGELOG references match renamed Go code
Scientist audit flagged stale Pulsar references in CHANGELOG.md (e.g.
'Pulsar-SHA3' production default name, 'pulsar/primitives/hash.go' paths).
The Go code was already renamed in commit e0fdfe4; this aligns the docs.

DESIGN.md's QUASAR-PULSAR-*-v1 prefix table is preserved — those are
Quasar consensus lane prefixes describing Pulsar pulse messages, NOT
Corona-internal tags. Different scope.
2026-05-13 14:28:54 -07:00
zeekay e0fdfe475b corona: symmetric domain separation — PULSAR-* tags -> CORONA-*
Leftover from Corona's "Pulsar-R" lineage. Pulsar (M-LWE) and Corona
(R-LWE) are independent constructions with separate hardness assumptions,
so their cSHAKE personalisation strings must be distinct.

Changes (Go, non-luxcpp):
  - hash tags: PULSAR-HC-v1 -> CORONA-HC-v1, etc. (HU, TRANSCRIPT, PRF, MAC, PAIRWISE)
  - profile IDs: "Pulsar-SHA3" -> "Corona-SHA3", "Pulsar-BLAKE3" -> "Corona-BLAKE3"
  - context strings: pulsar.dkg2.A.v1 -> corona.dkg2.A.v1, etc.
  - env vars: PULSAR_RESHARE_KAT_PATH -> CORONA_RESHARE_KAT_PATH, etc.
  - struct names: pulsarSHA3 -> coronaSHA3
  - KAT derive roots: sign_e2e_pulsar -> sign_e2e_corona

What's preserved (different scope):
  - luxcpp/crypto/pulsar/* path references in comments (separate repo,
    out of scope; the C++ side will rename in its own commit)
  - Cross-runtime KAT files on disk (will regenerate next CI run)

All 11 packages test green: dkg, dkg2, hash, keyera, networking,
primitives, reshare, sign, threshold, utils, wire.
2026-05-13 14:19:13 -07:00
zeekay 185d0c1ddc go.mod: bump go directive to 1.26.3 (security advisory) 2026-05-12 21:29:02 -07:00
zeekay 06bcfaf5b3 ci: Fresh-Clone CI default to bash shell (fixes 'set -o pipefail' on sh) 2026-05-12 14:54:45 -07:00
zeekay bf272721b0 gofmt: fix formatting in cmd/{corona_oracle_v2,dkg_oracle,shamir_general_oracle,sign_oracle}/main.go 2026-05-12 12:24:22 -07:00
zeekay 804ea28a1a corona/papers: corona2025 cite → boschini2024corona; coronaThreshold → coronaThreshold in TeX 2026-05-12 10:04:47 -07:00
zeekay 6d9e1192a3 corona: kill all remaining Corona identifiers in code + docs
After this commit zero 'corona' / 'Corona' / 'CORONA' references
remain in any Go file, Markdown doc, or TeX source in the corona
repository. The library is referenced by its production name (Corona)
everywhere; the upstream R-LWE construction is cited by author
(Boschini et al, ePrint 2024/1113) where attribution is required.

Renames:
  cmd/corona_oracle_v2/ → cmd/corona_oracle_v2/
  doc paths to luxcpp/crypto/corona → luxcpp/crypto/corona
  coronaThreshold (import alias in INTEGRATION.md) → coronaThreshold
  wrapAsCoronaShares                                → wrapAsCoronaShares
  CONSTANT-TIME-REVIEW.md, INTEGRATION.md, oracle cmd comments — all
  prose references swept Corona → Corona.
2026-05-12 10:04:40 -07:00
zeekayandGitHub 4d346173ef Update README.md 2026-05-12 09:21:34 -07:00
zeekay 27eaa39198 README: drop 'academic' framing, replace nasua hyperlink with ePrint citation 2026-05-12 09:12:25 -07:00
zeekay 8b65ae5c32 README: independent library + Double-Lattice composition with pulsar
Corona (Ring-LWE) and Pulsar (Module-LWE) are independently usable
threshold ML-DSA libraries — no shared types, no import line between
them. Each can be selected as a chain's sole PQ threshold layer.

The academic Corona upstream (Boschini et al, ePrint 2024/1113) is
referenced as luxfi/nasua (historical reference fork, trusted-dealer
DKG, not for public-chain use). Corona is the production track that
adds the lifecycle the academic fork lacks (Pedersen DKG over R_q +
proactive resharing + identifiable abort).

Lux primary-network QuasarCert layers both lattice families as a
Double-Lattice PQ defence with optional BLS classical fast-path and
per-validator ML-DSA-65 rolled up via STARK/FRI through P3Q.
2026-05-12 09:09:42 -07:00
zeekay f28c574360 corona: docs reference luxfi/nasua (academic upstream), not luxfi/corona
The academic 2-round R-LWE threshold construction was renamed Corona
→ Nasua at the family taxonomy level. Update Corona's documentation
references to point at the new name. Corona itself imports nothing
from luxfi/nasua — the dependency line is on luxfi/lattice/v7 for the
ring/sampling primitives — these comment refs only name the conceptual
upstream for design provenance.
2026-05-12 09:00:59 -07:00
zeekay 56d6c32ef1 corona: README — Ring-LWE identity; v0.1.x history inherited from luxfi/pulsar
This repository owns the former luxfi/pulsar v0.1.x Ring-LWE code line.
v0.2.0 is the first post-split Corona release. The Module-LWE sibling
library moved to luxfi/pulsar and starts at v1.0.0.

The 'Pulsar' brand name retained in the Quasar consensus protocol
refers to the Module-LWE library; this repository's brand is Corona —
the luminous ring around the central Pulsar/Quasar light.
2026-05-11 19:37:10 -07:00
zeekay 8c010dd8ef corona: rename module path github.com/luxfi/pulsar → github.com/luxfi/corona
Repo forks from luxfi/pulsar (R-LWE production threshold for Lux
consensus) to luxfi/corona under the family rename. Same Ring-LWE
code, same hash family (Pulsar-SHA3 / Pulsar-BLAKE3 -- wire-format
customization tags stay stable per MED-2). Only the Go module path
and internal imports change.

Lux family alignment:
  - Pulsar  = M-LWE / FIPS 204 / NIST MPTC N1 (was luxfi/pulsar-m)
  - Corona  = R-LWE / NIST MPTC S1            (this repo)
  - Corona = academic upstream + Lux DKG expansions
2026-05-11 14:55:26 -07:00
zeekay e1e7539c70 pulsar: LLM.md — corona rename note + post-E2E-PQ state
Records the Pulsar/Corona rename context: this repo (R-LWE,
production fork) becomes luxfi/corona; luxfi/pulsar-m (M-LWE, FIPS
204) becomes the canonical luxfi/pulsar. No code change here — wire
formats and consensus paths are unchanged until the cross-repo moves
land. v0.1.x tags continue to point at R-LWE code; new consumers
should pin v0.2.0+ on the renamed repo.
2026-05-11 11:47:07 -07:00
zeekay e4d8614e8c ci: bump Go toolchain 1.26.2 → 1.26.3 (fix remaining govulncheck CVE)
First post-bump CI run still failed with one stdlib vuln:

  GO-2026-4971  net.Dial / net.LookupPort NUL-byte panic on Windows
                Fixed in: [email protected].3

The previous bump to 1.26.2 cleared 4 of 5 reported CVEs but missed
this one (referenced via networking.DialTCP / networking.ListenTCP).
Bumping to the latest 1.26.x patch closes it. Still patch-bump only;
no minor / major change.
2026-05-10 17:45:35 -07:00
zeekay ea0dec9e10 ci: bump Go toolchain 1.26.1 → 1.26.2 (fix govulncheck CVEs)
govulncheck reported the following stdlib CVEs against Go 1.26.1 in the
Security Scan job:

  GO-2026-4866  crypto/x509  excludedSubtrees case-sensitivity auth bypass
  GO-2026-4870  crypto/tls   TLS 1.3 KeyUpdate DoS
  GO-2026-4946  crypto/x509  inefficient policy validation
  GO-2026-4947  crypto/x509  unexpected chain-building work

All fixed in go1.26.2. Bumped:

  go.mod                                go 1.26.1 → 1.26.2
  .github/workflows/ci.yml              GO_VERSION 1.25.7 → 1.26.2
  .github/workflows/fresh-clone-ci.yml  GO_VERSION 1.25.7 → 1.26.2

Matrix test-matrix entry also bumped 1.25.7 → 1.26.2.
2026-05-10 17:41:12 -07:00
zeekay 666e6b8950 style: gofmt -s across cmd/ + reshare/ + dkg2/ + keyera/ + threshold/
Whitespace-only struct-tag alignment changes. Closes the CI Lint gate
that was failing across multiple recent commits on otherwise-green
build+test runs.
2026-05-10 17:23:40 -07:00
zeekay b70f60dc31 pulsar: plumb HashSuite through every Sign-path primitive (F22)
primitives/hash.go: PRNGKey / GenerateMAC / GaussianHash / PRF / Hash /
LowNormHash all take HashSuite as first param. suite == nil resolves to
the production default Pulsar-SHA3 (cSHAKE256 / KMAC256 / TupleHash256
per FIPS 202 + NIST SP 800-185).

sign/sign.go: Party gains Suite field; NewParty defaults to
hash.Default(); NewPartyWithSuite for operator-explicit construction.
sign.Verify keeps its signature for callers and resolves the default
internally; the suite-explicit form is sign.VerifyWithSuite.

reshare/commit.go: suite-aware commit derivation aligned with the new
hash.HashSuite contract used by the rest of pulsar/reshare/dkg2/keyera.

Closes the gap where the HIP-0077 claim that Pulsar uses SHA-3
cSHAKE256/KMAC256/TupleHash256 in production was structurally false at
the Sign layer (only pulsar/reshare/, pulsar/dkg2/, pulsar/keyera/ were
consuming pulsar/hash/HashSuite previously). Pulsar-BLAKE3 retained as
legacy/non-normative only for cross-port byte checks.

go.mod: luxfi/math v1.3.0 -> v1.4.0 (consumes the codec for the new
hash-suite tag).

CHANGELOG.md added. sign_roundtrip_test.go pins the new contract.
Tests: primitives + sign + reshare PASS. Patch-bump.
2026-05-10 17:19:13 -07:00
zeekay 49630bb398 LP-107 Phase 4: pulsar consumes luxfi/math/codec
wire/wire.go — pulsar's wire-format hardening boundary. Untrusted
lattice Vector[Poly] frames now flow through luxfi/math/codec.Reader
so the bounded-decode contract is centralized: no recursion, no
hidden growth, no unbounded allocation.

Replaces the test-only validateVectorPolyFrameInline walker that
lived at threshold/fuzz_round_test.go with a production-grade
equivalent on the canonical luxfi/math/codec substrate.

Tests:
* TestValidateVectorPolyFrame_RejectsHugeLength — regression for
  lattice issue #4 (70-trillion-element attack input). Same input
  the original fuzz finding produced, now rejected with
  codec.ErrLimitExceeded via the shared math substrate.
* TestValidateVectorPolyFrame_HappyPath — 3-element accept.
* TestValidateVectorPolyFrame_AtCap — exactly MaxLatticeUintSliceLen
  accepted.
* TestValidateVectorPolyFrame_OverCap — MaxLatticeUintSliceLen+1
  rejected.

go.mod bumps luxfi/math v1.2.4 -> v1.3.0 (the LP-107 substrate
release with codec/ + params/ + backend/ + modarith/ + ntt/ + poly/
+ rns/ + sample/).

This is the first downstream consumer of the math substrate. Lens,
FHE, and lattice consumers follow.
2026-05-04 09:47:05 -07:00
zeekay 4d7b048aa9 pulsar: cross-runtime oracles + sign KAT generator (v0.1.2 follow-on)
cmd/sign_oracle/  — emits the canonical Pulsar sign+verify KAT JSON
(Gen + SignRound1 + SignRound2{Preprocess,} + SignFinalize + Verify) for
(t, n) ∈ {2/3, 3/5, 5/7, 7/11}. The C++ port at
luxcpp/crypto/pulsar/cpp/sign/ replays these entries byte-equal.

cmd/cross_runtime_oracle/  — Go writer for the cross-runtime release
gate. Emits a SHA-256 manifest tying together the three canonical
Pulsar KATs (sign, reshare, dkg2). C++ side at
luxcpp/crypto/pulsar/test/cross_runtime_test.cpp replays each KAT and
checks byte-equality (forward direction: 30/30 PASS).

cmd/cross_runtime_verify/  — Go reader for the reverse direction
(C++ writes, Go verifies). Currently 3/3 PASS against the SHA-256s
emitted by luxcpp/crypto/pulsar/cmd/cross_runtime_oracle/.

threshold/testdata/fuzz/FuzzPulsarSign1Round1Data/  — corpus seed for
the in-tree fuzz harness; mitigates the second lattice DoS (issue #4)
where Vector[T].ReadFrom calls make([]T, size) with no bound.

23 fuzz harnesses × 30s = 10.9M execs, 0 panics.
2026-05-04 03:32:05 -07:00
zeekay 4cff733804 threshold: validate Vector[Poly] frame before lattigo ReadFrom
FuzzPulsarSign1Round1Data found a 9-byte input that crashes the
goroutine with `fatal error: out of memory: cannot allocate
105589698985984-byte block` in `lattice/v7/utils/structs.Vector[T].
ReadFrom`. Recovery cannot catch the fatal OOM — the only safe path
is to reject malformed frames before `make([]T, size)` runs.

This is a SECOND DoS surface in lattice/v7, distinct from the
ReadUintNSlice recursion fixed by luxfi/lattice#3 (still open):
ReadFrom calls `make([]T, size)` with `size` read from the wire
before any bound check. PR #3 fixes the inner slice readers but the
outer Vector wrapper allocation remains exploitable.

Filed upstream as luxfi/lattice#4 with reproduction. The new
validateVectorPolyFrameInline walker mirrors the existing
warp/pulsar.validateVectorPolyFrame: walks the wire frame
end-to-end, asserts every length field is <= MaxLatticeUintSliceLen
(4096), and rejects truncated / over-large frames before the
lattigo decoder runs.

Result: FuzzPulsarSign1Round1Data passes 30s with the new walker
in place (28577 execs, 0 panics). Failing input
testdata/fuzz/FuzzPulsarSign1Round1Data/a80b8d313b40fa55 is now
rejected cleanly with "vector length 70368955777453 exceeds 4096".

Refs: luxfi/lattice#2 (open), luxfi/lattice#3 (open),
      luxfi/lattice#4 (filed 2026-05-04)
2026-05-04 03:15:49 -07:00
zeekay 261ad9d290 pulsar: lattice threshold kernel with key-era lifecycle + Pulsar-SHA3 + Nebula binding
Forked from github.com/luxfi/corona @ d09b2c2. Pulsar inherits the
2-round signing math byte-equal but adds blockchain-grade key
lifecycle and a SHA3-based domain-separated hash profile for
permissionless validator-set rotation.

Inherits from upstream Corona (byte-equal):
  - Sign1/Sign2/Combine 2-round signing math
  - Lattice ring R_q = Z_q[X]/(X^256+1), q = 0x1000000004A01
  - Module-LWE / Module-SIS hardness
  - NTT, Discrete-Gaussian Ziggurat, MAC layer

Replaces from upstream:
  - Broken Feldman-style DKG (pseudoinverse-recoverable). Replaced
    with: (a) one-time foundation MPC ceremony / trusted-dealer
    Bootstrap; (b) Pedersen DKG over R_q (research, dkg2/) hiding
    under MLWE on B / binding under MSIS on [A | B].
  - Trusted-dealer-per-epoch lifecycle (wrong shape for permissionless
    rotation). Replaced with Verifiable Secret Resharing (VSR) every
    epoch under the persistent group public key.

Key-era lifecycle (KeyEraID / Generation / RollbackFrom):
  - KeyEraID bumps only at Reanchor (rare governance event)
  - Generation bumps every Refresh / Reshare under the same GroupKey
  - RollbackFrom records prior generation reverted from (0 = forward)
  - Activation cert (QUASAR-PULSAR-ACTIVATE-v1) gates new generations
    under the unchanged GroupKey

Pulsar-SHA3 hash profile (NIST FIPS 202 / SP 800-185):
  - Hc:        cSHAKE256("PULSAR-HC-v1", transcript) → challenge
  - Hu:        cSHAKE256("PULSAR-HU-v1", transcript) → XOF stream
  - TranscriptHash: TupleHash256("PULSAR-TRANSCRIPT-v1", parts...)
  - PRF:       KMAC256(key, msg, "PULSAR-PRF-v1")
  - MAC:       KMAC256(key, msg, "PULSAR-MAC-v1")
  - Pairwise:  KMAC256(kex, encode(...), "PULSAR-PAIRWISE-v1")
  - Default suite is Pulsar-SHA3; Pulsar-BLAKE3 retained as optional
    non-normative fast profile. HashSuiteID is bound into transcripts.
  - Implementation at pulsar/hash/ with HashSuite interface.
  - All KATs regenerated under SHA3 profile; vectors in
    luxcpp/crypto/pulsar/test/kat/.

Nebula root binding (TranscriptInputs + ActivationMessage canonical
bytes, all bound under TupleHash256):
    chain_id, network_id, group_id,
    key_era_id, old_generation, new_generation,
    old_epoch_id, new_epoch_id,
    old_set_hash, new_set_hash,
    threshold_old, threshold_new,
    group_public_key_hash,
    nebula_root,
    hash_suite_id,
    implementation_version,
    variant.

Packages:
  primitives/   Shamir over R_q, Lagrange, hash helpers
  sign/         2-round sign math (byte-equal upstream)
  threshold/    GroupKey, KeyShare, Signer types
  reshare/      VSR kernel — Refresh (HJKY97 zero-poly), Reshare
                (Desmedt-Jajodia), commit (Pedersen R_q), complaint,
                transcript, pairwise KEX, activation cert
  hash/         HashSuite interface; PulsarSHA3 (default), PulsarBLAKE3
  dkg2/         Pedersen DKG over R_q (research, reference only)
  keyera/       Lifecycle wrapper: Bootstrap → Reshare → Reanchor
  papers/       LP-073-pulsar paper (sections + bibliography)
  cmd/*_oracle/ KAT generators (Go ↔ C++ byte-equal validation)

DESIGN.md is the single source of truth:
  - The Pulsar metaphor (rotating beam over persistent body)
  - Vocabulary stack per LP-105: Nebula / Photon / Lumen / Beam /
    Pulsar / Pulse / Prism / Horizon / Quasar
  - Pulsar ≠ Lumen (PQ stream is separate, planned)
  - Pulsar / Lens / LSS three-layer architecture
  - Bootstrap Dealer vs Signature Coordinator
  - No-slashing failure ladder (timeout → retry → rollback → reanchor)
  - MVP VSR vs Robust VSR phasing
  - Borrowed-brand terms ("X-Wing" used casually) replaced with
    "hybrid KEM" / "Hybrid Lumen Handshake"; X-Wing cited only as
    the IETF combiner primitive name where exact reference matters.

Tests: full suite green
  hash 5+/5+, keyera 5/5, reshare 45+/45+, threshold, sign, dkg,
  dkg2, primitives, networking, utils, corona_oracle_v2 KAT —
  all pass.

Honest claim: the crypto primitives are not new (HJKY97,
Desmedt-Jajodia97, Wong-Wang-Wing02, Corona, Hermine, Threshold
Raccoon all exist). The novel contribution is the systems
composition: a permissionless-consensus deployment architecture that
turns static two-round PQ threshold signatures into a dynamic,
leaderless, validator-rotation-tolerant finality layer.

Companion docs: papers/lp-073-pulsar/ (academic paper); LP-073 +
LP-103 + LP-105 in github.com/luxfi/lps; threshold/protocols/lss/
lss_pulsar.go (LSS adapter wrapping this kernel).
2026-03-03 12:00:00 -08:00