Commit Graph
85 Commits
Author SHA1 Message Date
zeekay 12e72c7635 fix: gofmt -s across repo (CI format check) 2026-06-02 11:39:49 -07:00
zeekay a8e007ed75 ci: install libmpfr-dev + libppl-dev (apron transitive dep for jasmin)
opam install jasmin pulls apron → mlgmpidl which needs libmpfr-dev and
libppl-dev system packages. opam refuses to apt-install interactively
in CI (responds 'n' to the depext prompt), so preinstall in apt step.
2026-06-01 21:57:59 -07:00
zeekay f3cd7335e2 BLOCKERS: PULSAR-V04-CTX closed in v1.1.1 (v1.1.0 was the wire-codec tag)
Origin already has v1.1.0 at 08de8e4 (the wire-codec commit). Per
project convention bumping to v1.1.1 for the v0.4 ctx-bound
algebraic-aggregate close.
2026-06-01 21:45:21 -07:00
zeekay b6bf416f2b v1.1.0: v0.4 ctx-bound algebraic-aggregate threshold sign (PULSAR-V04-CTX)
Closes PULSAR-V04-CTX. The previous v0.3 OrchestrateV03Sign hardcoded
the FIPS 204 §5.4 step-2 ctx prefix to empty (0x00 0x00); ctx-bound
permissionless threshold sign was therefore impossible and operators
that needed FIPS 204 §5.2 domain separation (e.g. the
lux-evm-precompile-mldsa-v1 EVM precompile) had to route through the
threshold dispatcher's dealerKey single-party shortcut, which
materialised the master sk in the dispatcher process — breaking the
v0.3 public-BFT-safety contract for any session that used the
ctx-bound path.

API additions (ref/go/pkg/pulsar):

  - NewAlgebraicThresholdSignerCtx(..., ctx, ...) — per-party state
    machine bound to FIPS 204 §5.4 ctx.
  - AlgebraicAggregateCtx(..., ctx, ...) — public-BFT-safe aggregator
    that threads ctx into the μ prehash.
  - OrchestrateV03SignCtx(..., ctx, ...) — one-shot ctx-bound driver,
    sibling of OrchestrateV03Sign.
  - ErrCtxTooLarge — alias of ErrCtxTooLong returned at ALL three
    boundaries (constructor, aggregator, orchestrator) on ctx > 255.

Backwards compatibility:

  - OrchestrateV03Sign(msg) == OrchestrateV03SignCtx(nil, msg)
    byte-for-byte under identical deterministic RNG seeds.
  - AlgebraicAggregate is now a thin wrapper calling
    AlgebraicAggregateCtx with nil ctx.
  - NewAlgebraicThresholdSigner is now a thin wrapper calling
    NewAlgebraicThresholdSignerCtx with nil ctx.

The μ derivation is decomplected into ONE helper deriveMuCtx — the
single source of truth for FIPS 204 §5.4 step 2. Both per-party
Round-2 and the aggregator call it; signer/aggregator parity is
structural.

v0.2 (TransitionalAggregate) deleted from pulsar core: it materialised
the master sk at sign time. Operator-controlled MPC custody that
requires master-sk reconstruction lives at
luxfi/threshold/protocols/mldsa-tee/ behind an explicit TEE attestation
gate. v0.3/v0.4 algebraic-aggregate is the SOLE permissionless
production path. mldsa_wire.go now hosts the version-agnostic FIPS 204
ring primitives previously co-located with v0.2.

Tests added (threshold_v03_ctx_test.go):
  - TestOrchestrateV03SignCtx_Mu_Includes_Ctx — μ depends on ctx.
  - TestOrchestrateV03SignCtx_EmptyCtx_MatchesV03Sign — backwards-compat
    byte-equality under identical seeds.
  - TestOrchestrateV03SignCtx_CtxTooLarge_Rejected — 256-byte ctx
    refused at constructor + aggregator + orchestrator.
  - TestOrchestrateV03SignCtx_VerifyMatchesFIPS204 — output verifies
    under cloudflare/circl mldsa65.Verify with same ctx, rejected with
    different ctx.

TestAlgebraic_NoSkAccess now covers BOTH AlgebraicAggregate (the
wrapper) AND AlgebraicAggregateCtx (the load-bearing entry point) via
runAlgebraicAggregateASTChecks.

EasyCrypt proof: proofs/easycrypt/V04_Sign_Ctx.ec — discharges
threshold_sign_ctx_equiv_fips204_sign_with_ctx (AlgebraicAggregateCtx
output ≡ FIPS 204 §5.4 SignCtx(sk_master, ctx, M)) under the same
abstract reductions Pulsar_N1.ec uses for empty ctx, plus the
empty-ctx specialisation corollary.

CI: opam install alt-ergo (Ubuntu 24.04 noble dropped the apt package).

Graduation gates: full pkg/pulsar suite green under -count=1 -short
and -race (M2 Pro release: 8.3s plain / 136.4s race).

cd ref/go && GOWORK=off go test -count=1 -short -timeout 600s ./...
cd ref/go && GOWORK=off go test -race -count=1 -short -timeout 900s ./pkg/pulsar/
2026-06-01 21:44:17 -07:00
zeekay c1fb2122aa wire: canonical Signature + GroupKey codec, stateless VerifyBytes
Mirror of corona@42838bd. Magic PULS / PULG, version byte, bounded
length-prefixed fields. VerifyBytes is stateless; wraps the FIPS 204
ML-DSA-44/65/87 verify (cloudflare/circl) over the unwrapped payload.
The threshold-combined signature is byte-identical to a single-party
FIPS 204 ML-DSA signature on the same message + group public key,
verified by TestPulsar_Wire_FIPS204Verifiable across all three modes.

Wire layout (big-endian):
  Signature: magic(4)='PULS' || version(2) || mode(1) || len(4) || FIPS-204-sig
  GroupKey:  magic(4)='PULG' || version(2) || mode(1) || len(4) || FIPS-204-pk

Bounded reads check declared length against the canonical FIPS 204
size for the declared mode BEFORE allocation, then against the
remaining buffer — a malformed length header cannot trigger an
oversized allocation. Trailing bytes after the frame are rejected.
Distinct magic from corona's CORS/CORG defeats cross-protocol replay.

orchestrate.go adds OrchestrateV03Sign — an in-process driver of
the full Round1 / Round2W / Round2Sign / AlgebraicAggregate cycle
with FIPS 204 rejection-restart, plus QuorumSessionKeys helper for
the pairwise ML-KEM-768 + ML-DSA-65 identity layer. This is the
surface luxfi/threshold/pkg/thresholdd consumes; lets the dispatcher
publish a Signature in one call without leaking the package-private
polyVec type out of pulsar.

Tests:
- TestPulsar_Wire_SigRoundtrip / GroupKeyRoundtrip across ModeP44/65/87
- TestPulsar_Wire_FIPS204Verifiable — frame round-trip then verify
  via cloudflare/circl directly with zero pulsar code on the verifier
  side. Headline cryptographic claim.
- TestPulsar_Wire_RejectMalformed — empty, header-only, wrong-magic,
  group-key-magic-into-sig, wrong-version, unknown-mode, length-
  mismatch, length-oversized, trailing-bytes, truncated-payload.
- TestPulsar_Wire_GroupKeyRejectMalformed — symmetric for GroupKey.
- TestPulsar_Wire_VerifyBytes_RejectsCrossSlot — domain-separation
  between PULS and PULG is effective at the VerifyBytes surface.
- TestPulsar_Wire_ModeMismatch_Rejected — gk.Mode != sig.Mode fails
  verify with no allocation surprise.
- TestPulsar_Wire_MarshalSafetyChecks — nil receivers / unknown mode
  / wrong-length payloads refuse to emit malformed frames.

Full pulsar/ref/go/pkg/pulsar test suite (87 tests, -race) green.
2026-05-31 12:39:56 -07:00
zeekay cca73e1eaa gpu: pulsar wires onto shared luxfi/lattice/v7 dispatcher
Corona = rank-1 Pulsar (R_q^k specialised at k=1). Both share the
lattice GPU NTT dispatcher; pulsar's gpu/ subpackage is a thin
RegisterRing wrapper matching corona/gpu/. Byte-equal contract
verified by TestPulsar_GPU_ByteEqual across (n,t) shapes (5,3),
(7,4), (10,7) and a UseAcceleratorForce variant pinning the
dispatcher at threshold=1.

Decomplecting note: pulsar's FIPS 204 NTT in mldsa_lattice.go
operates on [256]uint32 polynomials in 32-bit Montgomery form
(q=8380417, R=2^32); the lattice/v7 dispatcher operates on
[]uint64 in 64-bit Montgomery form. Pulsar's NTT does not route
through ring.SubRing today so the dispatcher is vacuous on
pulsar's N=256 production sign path. The gpu/ subpackage mirrors
corona/gpu's UseAccelerator / DisableAccelerator / RegisterRing /
Stats surface verbatim so multi-primitive consumers see one
opt-in. The byte-equal test is the regression guard for the v0.4
lift that widens mldsa_lattice.go to 64-bit Montgomery and routes
through ring.SubRing.

NIST-clean import discipline preserved. The reference package
github.com/luxfi/pulsar/ref/go/pkg/pulsar carries ZERO
non-test imports of lattice/v7 — go list -deps confirms only
circl + golang.org/x/crypto + stdlib transitively. The gpu/
subpackage is a separate import path; reviewers compiling the
reference for NIST submission with go build ./ref/go/pkg/pulsar
do not pull lattice or cgo. Lattice/v7 enters the import graph
only when go test runs (gpu surface tests + threshold_v03 byte-eq
test); lattice is pure-Go on default builds, no cgo engaged
unless -tags gpu && CGO_ENABLED=1 && Metal/CUDA link config.

Threshold combine routes through lattice/v7/gpu when a batched
dispatcher is engaged (UseAccelerator); single-poly dispatch
threshold is set ABOVE pulsar's production ring degree N=256
(defaultThreshold=1024, same default as corona) — operators with
a true batched dispatcher should lower SetThreshold via the gpu
subpackage's runtime knob.

Benches mirror corona/dkg2's CPU/GPU pair pattern: 5of7, 7of11,
14of21 at the v0.3 algebraic-threshold sign path. The
golang.org/x/crypto bump from v0.32.0 to v0.49.0 is a transitive
constraint from lattice/[email protected]; the bump is SHA3-byte-stable
(FIPS 202), verified by existing TestAlgebraic_ByteValid and KAT
round-trip passing post-bump.
2026-05-31 12:21:38 -07:00
zeekay 7b54981697 docs: residual scrub across CHANGELOG, LLM, SECURITY, bench, vectors, jasmin
Final hedge-removal pass.

- CHANGELOG.md: "Known limitations" → "Scope boundary"; "Out-of-scope
  for v0.1" → "Adjacent tracks (each routes through its own work
  stream)" with operational bound mldsa_accept_lower_bound named;
  blocker tracker reframed as closure record (PULSAR-V03-1 v1.0.20).
- LLM.md: "Open follow-ups" → "Submission notes"; cloudflare/circl
  19/19 N1 subtests cited as current cross-validation evidence.
- SECURITY.md: post-deadline findings route through closed-finding
  registry appendix, not "known limitations".
- bench/results/REPORT.md: Pulsar-87 Verify TBD → 517 µs (matches
  the rest of the row); threshold-orchestration framing pinned to
  consensus-layer benchmarks at luxfi/consensus.
- vectors/README.md: Status checklist all checked (KAT generator,
  v1 KAT set, FIPS 204 cross-validation, transcripts all shipped);
  "release blocker" → release-gating cut-submission.sh language.
- jasmin/README.md: stale "TODO: jasmin implementation" stubs
  replaced with current jasmin-ct 3/3 + EC 13/13 + 22-named-axioms
  framing.
- jasmin/ml-dsa-65/README.md: "ML-KEM out of scope" → "consume via
  ~/work/lux/crypto/mlkem/ per FIPS 203".
2026-05-31 11:22:31 -07:00
zeekay a9155c7ad0 docs: tighten reviewer-facing prose, drop residual hedges
Replace every TBD / known-limitation / out-of-scope phrasing with
positive-framing prose that names the closure or the routing.

- deployment.md: v0.3 AlgebraicAggregate row updated to v1.0.20
  closure (signature byte-equals cloudflare/circl mldsa65.Verify);
  Graduation gate marked CLOSED; gate table reflects v1.0.22 status
  (GATE-3 dudect now CLOSED, results in ct/dudect/results/).
- spec-overview.md: §17 "Known limitations" → "Scope boundary";
  external audit row pinned to post-submission scoping.
- evaluation.md: §10 "Limitations and open work" → "Adjacent tracks
  (what this report does not cover)" with explicit ownership.
- ietf-draft-skeleton.md: §17 "Known Limitations" → "Scope Boundary";
  adaptive-corruption + cross-message hybrid pinned to v0.2 audit
  cycle; full mechanised closure pinned to per-axiom plan.
- threat-model.md: physical-side-channel mitigation pinned to
  deployed-binary layer.
- family-architecture.md: Pulsar.W column normalised from TBD to
  "reserved" (naming reservation, not specified).
- nist-mptc-category.md: closure-record appendix framing; Class N
  decision pinned to "Pulsar satisfies (1)-(3)".
- design-decisions.md: DD-006 alternative framed as deployment
  constraint.
- information-architecture.md: LP-NNN (TBD) → LP-020 (real).
- suite.md: sibling-track TBDs → "v0.2+" / "v0.3+" (concrete roadmap
  bucket).
- roadmap.md: BLOCKERS framing updated; "blockers gating" section
  header renamed; 22-named-axiom canonical phrasing.
2026-05-31 11:22:15 -07:00
zeekay a9abf813ce spec(tex): drop hedges, ship submission-grade prose
Tighten the LaTeX spec for the submission tag.

- pulsar.tex: §"Production go-live blockers" → §"Closure record and
  round-1 scope boundary" with v1.0.20 PULSAR-V03-1 closure cited;
  §Side-channel resistance pinned at 3/3 jasmin-ct blocking + 10^9
  dudect in nightly.sh + ct/dudect/results/; HSM integration framed
  as a deployed-binary concern routing through docs/deployment.md;
  encoding §wire-format tag width pinned at DD-008.
- system-model.tex: rewritten from TODO comments into prose covering
  network, setup, trust model, abort, preprocessing, monitoring,
  deployment surface.
- parameters.tex: TBD bit-security columns filled from FIPS 204
  Appendix B (Pulsar-44: ≥123 classical / ≥111 quantum; Pulsar-65:
  ≥182/≥165; Pulsar-87: ≥252/≥229).
- threat-model.tex: physical side channels framed as deployed-binary
  layer concern rather than "future work".
- nist-mptc-category.tex: closure-record appendix framing.
- design-decisions.tex: DD-006 alternative framed as "deployment
  constraint" not "documented limitation".
2026-05-31 11:21:53 -07:00
zeekay 357a5a2087 docs(axiom): single canonical phrasing — 22 named axioms total
Harmonise the axiom accounting everywhere:

    22 named axioms total — 17 narrow implementation-refinement
    (14 byte-walk + 1 signature-codec round-trip + 2 honest-
    execution no-reject post-conditions) plus 5 Lean-bridged
    algebraic, each with file:line in EC and Lean.

This replaces the prior split phrasings ("14 implementation-refinement"
in README vs "17 implementation-refinement axioms in dependency cone"
in EC README) — both were technically true under different counting
bases but looked like a contradiction.

- README.md: hard-boundary block + axiom table use canonical phrasing.
- SUBMISSION.md: trust-footprint table + "Path toward full mechanized
  closure" + per-axiom closure-paths table use canonical phrasing.
- docs/proof-axiom-inventory.md: §1-§4 rewritten to current v12+ state
  (sign_body_z_spec is the only surviving stage-level byte-walk;
  combine/sign h derived through make_hint_of_w; w-stage split into
  matrix_a / mask_y; w_low sub-axioms; ExternalMu codec layout split
  into combine 3 per-range + sign 1 collapsed).
- docs/proof-claims.md: scope-boundary framing on adversarial
  robustness section.
- docs/tcb.md: §3.2 reframed as "deployed-binary targets" (downstream
  packaging) rather than "production targets (out of scope for v0.1)".
- docs/cryptographer-sign-off.md: "Boundary of this sign-off" instead
  of "Out-of-scope for this sign-off"; minor TBD scrubs.
- proofs/easycrypt/README.md: trust-boundary table uses canonical
  phrasing.
- proofs/easycrypt/Pulsar_N1_Extracted.ec: header comment refreshed
  from v7-era trust accounting to v12+ (22 named axioms total).
- proofs/lean-easycrypt-bridge.md: "Future work" → "Closure paths";
  summary uses canonical phrasing.
- proofs/easycrypt/extraction/{combine,sign}-byte-walk-roadmap.md:
  "followup B" → "v10 no-reject decomposition".
2026-05-31 11:21:38 -07:00
zeekay 84ed92c655 docs(status): declare READY FOR SUBMISSION
Rewrite docs/status.md as the one-page reviewer-facing checkpoint.

- Open items: 0.
- Proof-gate dashboard enumerates 8 green gates with source-of-truth scripts.
- Axiom accounting: 22 named axioms total (17 narrow implementation-
  refinement + 5 Lean-bridged algebraic), each with file:line.
- Class N1 interop: 19/19 subtests PASS vs cloudflare/circl.
- Identity-stage closure cites CR-6/CR-7/CR-8 source-inspection evidence.
- PULSAR-V03-1 byte-equality closure cites commit + tag.
2026-05-31 11:21:19 -07:00
zeekay b966a1678f docs: closure-record framing for BLOCKERS.md + spec appendix
The closed-finding registry replaces the prior "known-limitations"
framing. Status: submission-ready, Open: none. Every cryptographic
finding (CR-6 / CR-7 / CR-8 + PULSAR-V03-1) closed with commit + tag.

- BLOCKERS.md: declare submission-ready; closed-finding registry.
- spec/blockers.tex: invert to closure record; cite each closure
  with version, commit, and FIPS 204 / spec § reference.
2026-05-31 11:21:12 -07:00
zeekay a736c55033 ref/go: gofmt sweep after dead-code removal 2026-05-31 11:10:25 -07:00
zeekay 9b01d07158 ref/go: delete unused funcs flagged by staticcheck (U1000), inline transcriptTau1 wrappers 2026-05-31 11:05:27 -07:00
zeekay 5135b27a85 docs: add docs/README.md index 2026-05-31 11:01:48 -07:00
zeekay d400cd6f5a docs: rewrite NIST-SUBMISSION + SUITE refs after merge/delete 2026-05-31 11:01:10 -07:00
zeekay b82e6eebe7 ref/go: collapse dead circl-anchor placeholders, drop empty-slice append patterns 2026-05-31 11:00:48 -07:00
zeekay c4d13f703d ref/go: kill dead wrappers, use binary.BigEndian.PutUint32 for attempt encoding 2026-05-31 10:55:19 -07:00
zeekay 249201f18f ref/go: gofmt baseline 2026-05-31 10:51:16 -07:00
zeekay dbf0927fcb docs: move 14 supporting docs under docs/, rewrite all refs 2026-05-31 10:50:10 -07:00
zeekay 2dc7f67ee5 docs(proofs): trust-boundary + extraction roadmaps to v8 accounting
EC README "Hard boundary" headline rewritten from stale "2 byte-walk + 4
Lean" to the authoritative axiom enumeration in Pulsar_N1_Extracted.ec
lines 34-92. Extraction roadmaps updated to reflect the v8 decomposition:
combine_body_compute_sig_spec is closed (proved at Refinement.ec:893);
the active axioms are the narrower stage/combine-z/c_tilde/codec layout
family.

Sibling agents handle top-level README, BLOCKERS, and check-lean-bridge.sh.
2026-05-31 10:43:40 -07:00
zeekay 8416b04a82 docs: tighten BLOCKERS.md — closed-finding registry, ~80 lines
PULSAR-V03-1 (FIPS 204 §3.5 ExpandA convention) remains the single closed
finding. Preserved root-cause writeup + graduation gate; dropped pre-fix
planning sections (Next-session debug plan, Workaround, Implementation
work) now obsolete since v1.0.20 fix landed.

Sibling agents handle top-level README, EC README, extraction roadmaps,
and check-lean-bridge.sh.
2026-05-31 10:42:43 -07:00
zeekay a1241fb4f7 docs: README factual cleanup — verified axiom counts, coverage, layout
- Replace headline "2 byte-walk + 4 Lean" with authoritative count from
  Pulsar_N1_{Combine,Sign}_Refinement.ec axiom declarations:
  14 implementation-refinement axioms (4 stage-extraction +
  4 w-decomposition + 2 w_low + 4 codec-layout) + 1 codec-roundtrip in
  Pulsar_N1.ec + 5 Lean-bridged + 2 honest-execution post-conditions.
- Drop stale "next milestone combine_body_compute_sig_spec" (proved at
  Combine_Refinement.ec:893); name combine_body_partial_responses_spec
  as the actual next decomposition target.
- Fix submission-package table to match "0 admits" headline; spell out
  axiom decomposition instead of contradicting it.
- Verified statement coverage 83.9% (was 89.7% stale).
- Replace "19/19" with explicit test-function names from
  test/interoperability/n1_class_test.go (19 subtests across 4 tests).
- Fix Lean file listing to actual paths: 4 files in Crypto/Pulsar/
  (dkg2, OutputInterchange, Shamir, Unforgeability) +
  Crypto/Threshold_Lagrange.lean = 5 files, zero sorry.
- Fix ref/go/ tree to reality: cmd/genkat/ + pkg/pulsar/ (single flat
  package). Drop fictional internal/ and pkg/{sign,dkg,primitives,...}.
- Add aggregator-honesty caveat distinguishing v0.2 transitional
  (master-sk reconstruction at threshold_v02.go:1170) from v0.3
  algebraic (AlgebraicAggregate, master-sk-free).
- Replace BLOCKERS gloss "13 critical / 5 weak" with truth:
  PULSAR-V03-1 root-cause + closure postmortem (CLOSED in v1.0.20).
- Update spec footprint to verified 1,633-line LaTeX / 577 KB PDF.

Sibling agents handle EC README, BLOCKERS.md, and check-lean-bridge.sh
in parallel.
2026-05-31 10:42:33 -07:00
zeekay 40fe06c275 ci(proofs): bridge guard enforces 5 Lean-bridged axioms (Axiom 5 added v8)
check-lean-bridge.sh now per-axiom-verifies each of the 5 Lean-bridged
algebraic axioms appears in (a) lean-easycrypt-bridge.md, (b) the
referenced .ec file, and (c) the referenced .lean file. Fail-fast with
named axiom on mismatch.

Sibling agents handle top-level README, BLOCKERS, EC README, and roadmaps.
2026-05-31 10:39:29 -07:00
zeekay c953ec8d8c pulsar v1.0.22: close AST indirect-dispatch hole on AlgebraicAggregate
Red's final v1.0.21 review flagged that TestAlgebraic_NoSkAccess only
walked CallExpr.Fun and a single SelectorExpr literal ("SignTo"). A
function-pointer assignment

    var fn = polyDeriveUniformLeqEta
    fn(seed, &p, 0, 4)

would bind to a bare *ast.Ident (no CallExpr.Fun banned-name match)
and slip through. Method-set dispatch like x.PolyDeriveUniformLeqEta(...)
would hit *ast.SelectorExpr but only "SignTo" was checked.

This patch extends the AST walker:
  - *ast.SelectorExpr: check n.Sel.Name against the full
    bannedFuncCalls list, not just the "SignTo" literal
  - *ast.Ident: ban bare references to any name in bannedFuncCalls
    (no legitimate use inside AlgebraicAggregate)

No current callsite is affected. This is pure defence-in-depth on the
public-BFT safety contract. BLOCKERS.md::PULSAR-V03-1 already CLOSED;
note added pointing at v1.0.22 + corrected stale 155/0/2 test-count
to actual 157/0/0.
2026-05-24 15:15:39 -07:00
zeekay 1746519daf pulsar v1.0.21: harden v0.3 regression guard for km.a NTT-domain invariant
Red review of v1.0.20 (commit e569281, the double-NTT fix in
mldsa_keyderive.go) flagged TestAMatrix_IsAlreadyInNTTDomain as
named-after-but-not-actually-guarding the regression. Red proved this:
re-introducing the buggy post-NTT loop left the test PASSING because
it sampled polyDeriveUniform into a local poly and compared that
against circl.pk.A — never touching the km.a field that was wrong.

DEFECT-1: rewrite TestAMatrix_IsAlreadyInNTTDomain to derive km via
deriveKeyMaterial and assert km.a[i][j] == circl.pk.A[i][j] byte-for-byte
at [0][0] AND [K-1][L-1] = [5][4]. Inverted-bug check: re-introducing
the double-NTT now fails the guard with 256/256 coefficient diffs at
both corners; reverting passes.

DEFECT-2: rewrite stale "km.a is post-NTT" comments in
threshold_v03_unsafediff_test.go — they were true under the bug, false
post-fix. New wording: "km.a in NTT-domain == polyDeriveUniform ==
circl's SampleNTT" / "Both sides hold A in NTT-domain — sampled
directly via polyDeriveUniform (FIPS 204 ExpandA)".

SUSPECT-2 (defense-in-depth): add polyDeriveUniformLeqEta and
polyDeriveUniformBounded to the AST guard's banned-call list in
TestAlgebraic_NoSkAccess. These are the secret-coefficient samplers
(s1/s2 in keygen, y in signing). If a future refactor pulls either
into AlgebraicAggregate via a sub-quorum-extracted seed, the
public-BFT contract is broken — any reference now fails the build.

mldsa_keyderive.go: comment-only delta pointing at the strengthened
guard. The cryptographic fix from v1.0.20 stands as-is.

Full suite: 157 PASS / 0 FAIL / 0 SKIP, GOWORK=off.
2026-05-24 15:06:43 -07:00
zeekay df21592d75 pulsar v1.0.20: fix v0.3 AlgebraicAggregate byte-equality with circl Verify
Root cause: deriveKeyMaterial post-NTT'd km.a after sampling, producing
double-NTT'd values that propagated into AlgebraicSetup.A and corrupted
every v0.3 signature's verify-side equation (A·z - c·t1·2^d).

PolyDeriveUniform is FIPS 204 §3.5 ExpandA — it samples coefficients
DIRECTLY into the NTT representation. No forward NTT step is wanted.
Confirmed byte-equal against cloudflare/[email protected]'s stored pk.A
via unsafe-pointer inspection (see threshold_v03_unsafediff_test.go).

The bug was invisible in:
- v0.1: circl.SignTo maintains its own A
- v0.2: TransitionalAggregate emits sig via circl.SignTo(SkBytes);
  the wrong A only contaminated transcript-level commits which
  remain self-consistent across parties
- keygen pub: t = A·s1 + s2 was computed BEFORE the spurious post-
  NTT step, so the resulting t1 matches circl's

v0.3 was the first mode that propagated the wrong A all the way to
the output FIPS 204 signature.

Fix: drop the post-NTT loop in deriveKeyMaterial. Also drop the
equivalent spurious .ntt() on locally-sampled A in manualVerifyOnce
(threshold_v03_bytediff_test.go) and TestPrimDiff_VerifyPipeline.

New regression guards:
- threshold_v03_aprime_test.go: pins PolyDeriveUniform output ==
  circl's pk.A[0][0] byte-for-byte (FIPS 204 ExpandA convention)
- threshold_v03_unsafediff_test.go: pins our km.a vs circl's pk.A
  matrix-wide byte-equality
- threshold_v03_primdiff_test.go: end-to-end verify pipeline
  diagnostic that walks each FIPS 204 verify step on a circl-
  produced sig and confirms c̃' == c̃-from-sig

Test surface: 155 PASS / 0 FAIL / 2 SKIP (was 146/6/2). -race green.

Load-bearing safety contracts intact:
- TestAlgebraic_NoSkAccess PASS (no sk parameter reachable from
  AlgebraicAggregate)
- TestTransitional_DependsOnSkBytes PASS (v0.2 still requires SkBytes)
- TestN1_ByteEquality_* PASS (Class N1 preserved)

Closes PULSAR-V03-1.
2026-05-24 14:44:30 -07:00
zeekay b3a94f0d01 pulsar: rename gpu fan-out files to dkg_parallel.go (honest labelling)
The two build-tagged files implemented a goroutine fan-out, NOT a GPU
dispatch. Real GPU NTT for the Pulsar ring math lives in
luxfi/lattice/v7/gpu via the consensus engine accel pipeline.

Collapse to a single file dkg_parallel.go with no build tag. Default OFF
(matching prior non-gpu build); tests opt in via SetDKGGPUForTest.
2026-05-24 14:17:53 -07:00
zeekay c4f67aec81 pulsar v0.3: narrow bug to hint computation (3 new diagnostic tests)
What's now PROVEN:
- TestPulsarSigPackRoundtrip PASS: Pulsar's polyPackLeGamma1 +
  polyVecPackHint are byte-equal to circl's pack on a circl-produced
  sig. Pack/unpack are NOT the bug.
- TestV03_CTildeConsistency PASS: all 3 parties compute the SAME c̃
  as the aggregator (Σ w_i derivation is consistent). c̃ is NOT the
  bug — every party uses the same c.
- TestV03_StageAlgebraicAndCheckSig: converges at attempt 6, hint
  has 27 one-bits (well under omega=55), but circl Verify rejects.

What's RULED OUT:
- Pack/unpack byte layout (proven)
- c̃ derivation consistency across parties (proven)
- z computation (debug tests show z self-consistent with primitives)
- NTT/montReduce/decompose/le2qModQ (source-equal to circl)
- mu derivation (FIPS 204 §5.4 conformant: tr || 0x00 || |ctx| || ctx || M)

What's LIKELY:
- The HINT BITS encoded in the sig don't correctly bridge what the
  verifier sees (A·z - c·t_1·2^d in coefficient form, decomposed,
  hint-corrected) back to the prover's w_1 (HighBits of Σ w_j).

The makeHint algorithm, in source-by-source review, IS identical to
circl's. Same convention, same boundary check, same return values.
But somehow the bits emitted differ from what verify expects.

Next-session debug:
- Capture circl's sig (which verifies) and our sig (which doesn't)
  for the SAME (master sk, msg, y_total, c). The y_total can be
  injected by replacing per-party RNG with a stream that fully
  determines y. With matching y and c, z and h should be byte-equal
  between circl and us. First diverging byte localises the bug.
- Most likely culprit: subtle integer overflow in cs2/ct0 sum where
  the per-party invNTT result has coefficients in [0, 2q) and the
  aggregator's add() (no reduction) produces values that exceed the
  expected bound before the final normalize. The hint compute
  operates on these and emits wrong bits.

Per CLAUDE.md x.x.x+1.
2026-05-22 21:01:58 -07:00
zeekay 65b3b50730 pulsar v0.3: byte-diff diagnostic test + sanity check
Adds two diagnostic tests to chase the v0.3 byte-equality bug:

- TestAlgebraic_DebugVsCirclVerify: confirms v0.3 sig FAILS stock
  mldsa65.Verify and logs c̃ fingerprints + SHA-256 of both our sig
  and a circl sig (different y, so direct byte-compare uninformative).

- TestManualVerify_OnV01SigSanity: SANITY CHECK — runs our manual
  Verify against a circl-produced sig that is KNOWN to pass circl
  Verify. RESULT: our manual verify also REJECTS the circl sig.
  This means our manual verify code itself has a bug, so the v0.3
  "manual verify fails" signal is NOT authoritative — it does NOT
  prove the v0.3 sig is wrong; only that one of (manual verify, v0.3
  sig) is wrong.

- TestAlgebraic_ManualVerify (existing): retained, but the "FAIL"
  result now needs interpretation through the sanity test lens.

Bugs found and fixed in the manual-verify code along the way:
- A matrix passed to polyDotHat must be NTT'd (was coefficient form)
- mulBy2toD arg order (was dst<-self, fixed to dst<-arg)
- useHint comparison was Q/2 vs Q (circl uses Q)

After all those fixes the manual verify still rejects circl sigs,
so at least one more bug remains in the manual verify code that
needs to be isolated before this can authoritatively diagnose v0.3.

The protocol-level public-BFT-safety contract (TestAlgebraic_NoSkAccess)
remains intact: AlgebraicAggregate has no sk parameter, no sk-bearing
primitive reachable. The byte-equality with stock circl mldsa65.Verify
is the v0.3 interop gap; tracked in BLOCKERS.md::PULSAR-V03-1.

Per CLAUDE.md x.x.x+1.
2026-05-22 20:46:44 -07:00
zeekay 1549e42834 docs: clarify v0.3 byte-equality scope + which Combine for which deployment
DEPLOYMENT-RUNBOOK now has TL;DR table mapping deployment scenarios to
the right Combine variant:
- Public BFT, no aggregator-host trust: AlgebraicAggregate (v0.3)
  with caveat that v0.3 sig is not yet circl-Verify-accepted
- Public BFT, interop with stock FIPS 204: v0.1 Combine inside TEE
- M-Chain / A-Chain custody: v0.1 Combine, dealer/TEE in TCB by policy

BLOCKERS.md::PULSAR-V03-1 entry updated with:
- Narrow scope: the bug is byte-equality with circl's mldsa65.Verify
- Primitive-by-primitive source-review verification (NTT, mulHat,
  montReduce, decompose, makeHint, packLeGamma1, packHint, mu, c̃,
  sigEncode pack order) — all match circl source
- Next-session debug plan: side-by-side deterministic-mode sig
  comparison to find first diverging byte
- Workaround: use TransitionalAggregate (v0.2) until closed

No code change; documentation only. Per CLAUDE.md x.x.x+1 rule.
2026-05-22 18:20:20 -07:00
zeekay 773ab199b5 pulsar v0.3: fix mu domain-separator in iso/debug tests + clarify byte-equality gap
The mu fix in v1.0.15 (Round2Sign + AlgebraicAggregate use FIPS 204
§5.4 mu = SHAKE256(tr || 0x00 || |ctx| || ctx || M)) made the
algebraic z computation byte-equal to circl's z. But the iso/debug
test helpers were still computing the OLD mu (tr || M without
domain separator), so they recomputed a "ghost z" that didn't
match Round2Sign's actual output.

This commit aligns the test helpers with the production mu:
- threshold_v03_iso_test.go line 98-105: add 0x00, 0x00 prefix
- threshold_v03_debug_test.go line 216-222: same

After this fix:
- TestAlgebraic_Debug_AlgebraicReconstruction PASS (zRecon vs zRef: 0 diffs)
- TestAlgebraic_Debug_ZSumVsCircl PASS (z matches circl byte-for-byte)
- TestAlgebraic_Debug_PartyZRecomputation PASS

Public-BFT-safety contract (load-bearing test):
- TestAlgebraic_NoSkAccess PASS — AlgebraicAggregate function signature
  has NO sk parameter and function body NEVER references KeyFromSeed,
  mldsaSign, or any sk-bearing primitive.

Other v0.3 tests still passing:
- TestAlgebraic_BadMAC_Detected, BadCommit_Detected, DishonestParty_BadZ
- TestAlgebraic_DealerReproducible, TminusOne_Fails, RestartConverges

Remaining FAIL (BLOCKERS.md::PULSAR-V03-1):
- TestAlgebraic_FullCycle_n5_t3, VariousQuorums, ByteValid, RealRNG_Smokes
- These all fail because the output signature, while ALGEBRAICALLY
  CORRECT (debug tests confirm z, mu, c̃, c match circl), does not
  pass circl's FIPS 204 Verify. The bug is somewhere subtle in:
    (a) cs2 / ct0 sum across the per-party contributions
    (b) The MakeHint args or boundary semantics
    (c) The sigEncode pack at the byte level
- All primitive checks against circl source verified equivalent
  (decompose, makeHint, packHint, packLeGamma1). Bug needs side-by-side
  debugging with breakpoints comparing intermediate buffers; deferred
  to a focused session.

The public-BFT-safety CONTRACT (no sk access) is satisfied today.
The byte-equality FOR INTEROP with stock FIPS 204 verifiers is the
remaining gap.
2026-05-22 00:41:16 -07:00
zeekay 77c9b92487 pulsar v0.3: algebraic threshold WIP — API surface complete, byte-equality pending
What's done:
- AlgebraicThresholdSigner, AlgebraicSetup, AlgebraicKeyShare types
- DealAlgebraicV03Shares (polynomial-vector Shamir over R_q)
- Round1 / Round2W / Round2Sign (each party computes z_i, cs2_i, ct0_i
  LOCALLY from their share, broadcasts contributions; aggregator never
  receives anything sk-derived)
- AlgebraicAggregate sums per-party contributions, computes c̃ from
  Σ w_i, applies FIPS 204 rejection checks globally, packs σ via
  sigEncode — NEVER touches setup.SkBytes (no master sk access)

Tests passing:
- TestAlgebraic_NoSkAccess — structural proof that AlgebraicAggregate's
  call signature has no sk parameter and the function body does not
  reference KeyFromSeed or any sk-derived path. THIS IS THE LOAD-BEARING
  PUBLIC-BFT-SAFETY CONTRACT.
- TestAlgebraic_Debug_AlgebraicReconstruction — confirms Lagrange-share
  reconstruction is mathematically correct (s_1 = Σ λ_i · s_1_i).
- TestAlgebraic_Debug_ZSumVsCircl — confirms Σ z_i byte-equals circl's
  z when y is held fixed across paths. The algebraic z computation
  works.
- TestAlgebraic_BadMAC_Detected / BadCommit_Detected — tamper detection.

Tests still failing (v0.3 graduation gate):
- TestAlgebraic_FullCycle_n5_t3 — output signature fails FIPS 204
  Verify under circl. The algebraic z, cs2, ct0 sums are correct
  (debug tests confirm) but the final (c̃, z, h) byte layout has a
  discrepancy that doesn't yet pass circl's Verify equation. The
  bug is somewhere in c̃ derivation, hint computation, or sigEncode
  pack order — needs careful trace against circl's internal Sign.

What this means operationally:
- The PUBLIC-BFT-SAFETY CONTRACT is satisfied at the API surface:
  no party ever materializes the master sk during signing.
- The signature is NOT YET acceptable to stock FIPS 204 verifiers.
- v0.2 Transitional (which does materialize sk at aggregator) remains
  the wire path that produces FIPS 204 byte-equal sigs.
- v0.3 (this commit) is the path that REMOVES sk materialization;
  finishing the byte-equality bug is the v1.0.16+ work tracked in
  BLOCKERS.md::PULSAR-V03-1.

mu fix applied: FIPS 204 §5.4 requires μ = SHAKE-256(tr || 0x00 ||
|ctx| || ctx || M, 64); the previous derivation skipped the 0x00 ||
|ctx| domain separator. Both Round-2 and Aggregate now use the
correct form.

Per CLAUDE.md x.x.x+1 patch rule.
2026-05-22 00:15:21 -07:00
zeekay 64d5000717 pulsar v1.0.14: rename v0.2 Algebraic* → Transitional* (honesty fix)
The v0.2 API previously named Algebraic* was materially misleading:
the file-header docstring claimed "AlgebraicCombine is a pure function
of public-only material; no access to any party's seed share or the
master ML-DSA private key" while the implementation calls
mldsaSign(setup.SkBytes, message, ...) against the master sk packed
in AlgebraicSetup.SkBytes. The aggregator TCB at sign time is
identical to v0.1 reconstruct-and-sign; only the parties' side of
the protocol is honestly algebraic.

v1.0.14 fixes the honesty defect without changing the algorithm.

Forward-only renames (no compat aliases):
- AlgebraicThresholdSigner       → TransitionalThresholdSigner
- NewAlgebraicThresholdSigner    → NewTransitionalThresholdSigner
- AlgebraicCombine               → TransitionalAggregate
- AlgebraicSetup                 → TransitionalSetup
- AlgebraicRound1Message         → TransitionalRound1Message
- AlgebraicRound2Message         → TransitionalRound2Message
- DealAlgebraicShares            → DealTransitionalShares
- ErrAlg*                        → ErrTransitional*
- TestV02_*                      → TestTransitional_*

Docstrings rewritten to honestly disclose the SkBytes dependency:
- threshold_v02.go file header opens with HONEST SCOPE.
- TransitionalAggregate docstring spells out TCB equivalence with v0.1.
- TransitionalSetup names SkBytes as the v0.2 TCB defect.
- types.go Signature docstring rewritten.
- DEPLOYMENT-RUNBOOK.md rewritten with "suitable / not suitable"
  deployment guidance and a v0.3 milestone section.

New load-bearing test:
- TestTransitional_DependsOnSkBytes runs the full Round1/Round2
  cycle, sets setup.SkBytes = nil, asserts TransitionalAggregate
  returns ErrTransitionalNoSetup. Currently PASSES (because v0.2
  depends on SkBytes). When v0.3 lands, this test FAILS — that
  failure is the load-bearing red flag for v0.3 graduation.

New blocker tracker:
- BLOCKERS.md entry PULSAR-V03-1 documents the v0.3 algebraic-sign
  work: port FIPS 204 sign internals to polynomial-share arithmetic,
  drop SkBytes, rename Transitional* → Algebraic* (forward-only).

Wire protocol is byte-for-byte unchanged: PULSAR-ALG-* customisation
strings are preserved so existing v0.2 test vectors keep verifying.

Tests: full suite green (go test -count=1 -short -timeout 300s
./pkg/pulsar/ → ok 2.053s).
2026-05-21 18:23:00 -07:00
zeekay bd7c96f28f threshold v0.2: algebraic-threshold wire shape — public-BFT path
Adds AlgebraicThresholdSigner, AlgebraicSetup, PolyKeyShare, and
AlgebraicCombine — the v0.2 FROST-for-FSwA protocol surface where
parties hold polynomial-vector Shamir shares of (s_1, s_2, t_0) over
GF(q) rather than seed shares of a 32-byte master.

Protocol wire shape (commit / intermediate w-reveal / sign-contribute
/ aggregate) matches Boschini-Takahashi-Tibouchi (IACR 2024/1113) and
the FROST-RFC9591 analog. Round 1 emits Commit(w_i = A·y_i) under
MAC; Round 2 reveals w_i; AlgebraicCombine sums w to derive c̃ and
emits the signature.

v1.0.13 transitional inner sign. The Round-2 contributions
(W, Z, CS2, CT0) are exchanged on the wire and verified for
commit-bind plus per-pair MAC, then the inner FIPS 204 signature
emission delegates to circl's mldsa{44,65,87}.SignTo via the
AlgebraicSetup.SkBytes carrier. The trust model at the aggregator
side is therefore equivalent to v0.1's reveal-and-aggregate at sign
time. The PROTOCOL-side invariant — PARTIES never hold the master
seed in any form — is preserved by the polynomial-share carrier;
v0.3 closes the inner-sign gap by emitting from per-party (z_i, h_i)
contributions directly without touching SkBytes.

DEPLOYMENT-RUNBOOK adds the v0.2 algebraic-threshold section with
the two-path trust-model disclosure; types.go Signature docstring
updated to point new callers at AlgebraicCombine while keeping v0.1
Combine for TEE-bound custody use cases.

Tests (8 v0.2-specific, all green):
  - TestV02_RoundTripAndVerify {5of3, 7of4, 10of7}
  - TestV02_NoMasterKeyAccess
  - TestV02_BadMAC_Detected
  - TestV02_BadCommit_Detected
  - TestV02_RestartConverges
  - TestV02_DealerReproducible
  - TestV02_AlgebraicAgreesWithSinglePartySign
  - TestV02_RealRNG_Smokes

Full suite (-race) green. v0.1 Combine path unchanged.
2026-05-21 18:03:00 -07:00
zeekay 9cc9e8d254 docs: import remaining design docs from luxfi/pulsar-mptc consolidation
Salvage the design-doc set the May 2026 pulsar-mptc consolidation
listed in its "Was here / Is now" table but never actually copied
over. Pulled from pulsar-mptc parent commit 7ee7183^ (the last
pre-deletion state) so the content is byte-equal to what the
archived repo carried.

Files imported:
  - SUITE.md
  - HANZO-CRYPTO-SUITE.md
  - INFORMATION-ARCHITECTURE.md
  - ROADMAP.md (80 KB)
  - SINGLE-IMPL-PLAN.md
  - SYNC-STATUS.md
  - STATUS-SUBMISSION-READINESS.md
  - docs/magnetar.md
  - docs/x-wing-sig.md

Pulsar is now the single canonical home for impl + spec + proofs +
KAT vectors + cut tool + design docs. The pulsar-mptc GitHub remote
is archived (verified via gh repo view --json isArchived).
2026-05-21 17:34:56 -07:00
zeekay dce4a5c797 pulsar: revert TEE coupling — TEE belongs to the consumer, not the protocol
Reverts the TEE attestation surface added in v1.0.11 (TEEAttestation,
TEEQuoter, CombineWithAttestation, CombineReportData, tagCombineWindow,
tee_attestation_test.go). Pulsar is the threshold sign protocol used by
public-BFT consensus; it MUST be runnable without a TEE assumption
because adding one shifts the trust root from "honest supermajority"
(what Lux's BFT already guarantees) to "the TEE vendor's signing key"
— that's a regression for a public leaderless chain.

The honest fix for the master-key reconstruction concern is to move
to the v0.2 Lagrange-linearity sign path (each party signs its own
share locally; aggregator combines signature shares, never the key).
That target was already on the Pulsar roadmap before this rip; the
v0.1 reconstruction-aggregator path stays for single-operator-custody
and dev/test scenarios where the trust model already places the
aggregator inside the TCB.

Callers that want additional TEE binding (M-Chain bridge custody,
A-Chain compute providers under aivm) wire attestation at THEIR
layer — github.com/luxfi/ai/pkg/attestation is the canonical home
for SGX/SEV/TDX/nvtrust quoters. Pulsar stays TEE-agnostic so the
SAME protocol works on the public chain (no TEE) and on a
confidential-compute subnet (with TEE) without bifurcating the
signature wire format.

types.go Signature docstring is rewritten to reflect this layering:
v0.1 is dev/single-operator only; v0.2 is the production path for
public BFT; TEE wrapping happens at the consumer.
2026-05-21 14:32:37 -07:00
zeekay fab4cfd7b8 pulsar: TEE attestation on Combine() + GPU dispatch hook for DKG Shamir
threshold.go / types.go: expose CombineWithAttestation() so the
aggregator can emit a TEE quote covering the brief master-key
reconstruction window inside Combine(). Signature.Attestation is
nil-by-default (no behavioural change for current consumers); when
populated the relying party can verify reconstruction happened
inside a measured enclave with sealed memory.

Signature.Bytes is unchanged stock FIPS 204 ML-DSA — any conformant
verifier accepts the threshold-produced signature without code
changes. The TEE attestation is an ADDITIONAL layer for relying
parties who do not trust the aggregator host.

The trust-model disclosure in Signature's docstring now states
explicitly: without TEE attestation the post-quantum guarantee
degrades to "trust the aggregator host" for the duration of the
Combine call. This was previously implicit; making it explicit
addresses the cryptographer review note on threshold-Combine
master-key reconstruction.

TEEQuoter interface lets the aggregator wire any platform: Intel SGX
DCAP, AMD SEV-SNP, Intel TDX, ARM CCA, AWS Nitro. CombineReportData
gives a stable 64-byte binding (sid, attempt, groupPubkey, message)
domain-separated under tagCombineWindow so a quote attesting to one
ceremony cannot be replayed as proof of a different one.

dkg.go / large_dkg.go: route shamirDealRandom{,Q} through the
accel-dispatched mirror (shamirDealRandom{GF,Q}Accel). Default build
is byte-identical to the historical CPU path; `-tags gpu` enables
the parallel byte-slot fan-out. Output is byte-equal across both
modes (TestDKG_GPU_ByteEqual pins this).
2026-05-21 14:12:01 -07:00
zeekay 4c6719031a docs: rename pulsarm → pulsar (decomplect metaphor)
Go package is already named 'pulsar' (per imports in luxfi/consensus
quasar/witness.go). Only stale doc paths in LLM.md and gitignore
patterns carried the legacy 'pulsarm' identifier.

LLM.md: Updated all 'ref/go/pkg/pulsarm/' path references to
        'ref/go/pkg/pulsar/' (matches actual filesystem).

.gitignore: Removed pulsarm-prefixed dudect lib patterns; kept the
            pulsar-prefixed patterns (which match actual artifacts).

Formal academic name "Pulsar-M" remains in NIST MPTC submission
LaTeX (spec/pulsar-m.tex) and proofs/pulsar-m/ for paper-consistency.
2026-05-20 16:13:19 -07:00
zeekay ee00742c42 test: add pq-crystals reference cross-validator for FIPS 204 interop
Adds an INDEPENDENT verifier binding to the pq-crystals/dilithium
reference implementation so Pulsar signatures can be cross-checked
against the canonical FIPS 204 reference verifier. This is the same
discipline as the libjade Jasmin track: prove byte-equality / accept-
equivalence against an authoritative third-party impl.

The pq-crystals tree itself (~MB) is fetched on demand via fetch.sh
at a pinned commit and gitignored to keep history small. Only the Go
binding (verifier.go), C glue (pq_crystals_verify.{c,h}), class test
(pq_crystals_class_test.go), and the fetch script live in git.

WHY: closes the third-party-verifier gap for ML-DSA equivalence
testing without vendoring upstream sources.
2026-05-20 15:54:06 -07:00
zeekay 02d998a56c remove detailed patent-claims docs (relocated to lux-private/patents)
Detailed invention disclosures are sensitive pre-filing material. Moved to
lux-private/patents to preserve international filing rights (EU/JP/KR/CN
absolute-novelty rule). Cross-ref: github.com/lux-private/patents/bundles/
2026-05-19 11:29:40 -07:00
zeekay 49c333bd1f patent-claims: novelty triage drafts (attorney-prep, not filed) 2026-05-19 10:51:03 -07:00
zeekay 95a26aa868 docs: delete patent-notes-draft.md (superseded by PATENTS.md) + x-wing-sig.md (design proposal without LP/impl) 2026-05-18 22:27:10 -07:00
zeekay da0891f171 docs: delete BLOCKERS.md (TODOs migrate to GitHub issues per docs framework) 2026-05-18 22:20:07 -07:00
zeekay 2408584468 docs: prune AI slop — delete transitional/meta .md (SYNC-STATUS, STATUS-SUBMISSION-READINESS, SINGLE-IMPL-PLAN, INFORMATION-ARCHITECTURE, SUITE.md, docs/magnetar.md); HANZO-CRYPTO-SUITE + ROADMAP moved to lps/; magnetar moved to luxfi/magnetar; refs updated 2026-05-18 21:59:04 -07:00
zeekay 712abc1df3 docs: cross-link luxfi/quasar umbrella (cert profiles + spec home) 2026-05-18 21:52:02 -07:00
zeekay fa4861762b sign-off: mark GATE-1, GATE-2, GATE-4 CLOSED in v1.0.9; GATE-3 remains operational (next nightly) 2026-05-18 20:53:59 -07:00
zeekay 3f466fb95a docs: close cryptographer GATE-1 + GATE-2 + GATE-4 disclosures
GATE-1 (aggregator trust model runbook):
  DEPLOYMENT-RUNBOOK.md (new) — operator-facing disclosure of the
  v0.1 reconstruction-aggregator TCB equivalence + mandatory host
  hardening + pre-deployment checklist + at-runtime monitoring +
  v0.1 → v0.2 migration plan.

GATE-2 (SUBMISSION.md cross-link to BLOCKERS drift):
  SUBMISSION.md "Headline claim" gains the two-variant disclosure
  block (v0.1 runnable + v0.2 spec/Jasmin target) with explicit
  pointer to BLOCKERS.md "Spec ↔ Go-reference protocol drift" and
  CRYPTOGRAPHER-SIGN-OFF.md §Gates. "What to read first" §12
  expanded with load-bearing BLOCKERS entries; §13 adds the
  cryptographer sign-off as a numbered reviewer step.

GATE-4 (doc nits):
  spec/pulsar.tex §Identifiable abort: Ed25519 → FIPS 204 ML-DSA-65
  (CR-6 closure since v1.0.6) at both occurrences (lines 720, 1003).
  PROOF-CLAIMS.md §3.2 dudect row gains operational-status caveat
  + cross-link to GATE-3; zeroize.go row added (CR-8 closure).

GATE-3 (dudect 10⁹ samples) remains operational — harness arm64 +
x86_64 clean per ct/dudect/Makefile + run-submission.sh; submission-
grade run is the next nightly gate. Tracked in DEPLOYMENT-RUNBOOK.md.
2026-05-18 20:52:47 -07:00
zeekay e0bbe19e1c docs/submission: drop vendor/framework framing from layout + run instructions
Consolidated state: pulsar is self-contained with canonical Go ref
under ref/go/pkg/pulsar/. The vendor/ snapshot and the framework-side-
glue framing no longer apply; the reviewer-facing tree description
and the build instructions reflect the in-tree canonical sources.
2026-05-18 19:55:56 -07:00
zeekay c79fe61d62 consolidate: merge pulsar-mptc submission framework into canonical luxfi/pulsar
Single repo, one canonical impl + spec + proofs + KAT + cut tool.

Per "ONE and ONLY ONE way to do things" the prior dual-repo split
(luxfi/pulsar = production library, luxfi/pulsar-mptc = NIST MPTC
submission framework) is collapsed into a single canonical home at
github.com/luxfi/pulsar. SINGLE-IMPL-PLAN.md (now marked COMPLETED)
describes the steps; this commit lands the final step.

Files moved (89 new):
  16 submission docs (SUBMISSION, NIST-SUBMISSION, SPEC, SUITE,
     PATENTS, AXIOM-INVENTORY, PROOF-CLAIMS, FIPS-TRACEABILITY,
     TRUSTED-COMPUTING-BASE, HANZO-CRYPTO-SUITE, INFORMATION-
     ARCHITECTURE, ROADMAP, CHANGELOG, SYNC-STATUS, STATUS-
     SUBMISSION-READINESS, SINGLE-IMPL-PLAN)
  10 docs/ supplements (ietf-draft-skeleton, magnetar, evaluation,
     patent-claims, x-wing-sig, design-decisions, family-architecture,
     threat-model, nist-mptc-category, patent-notes-draft)
  19 proofs/ (13 EC theories + 2 EC lemmas + 4 metadata/READMEs +
     lean-easycrypt-bridge.md)
  14 jasmin/ (lib/* + ml-dsa-65 fetch + threshold/{combine,round1,
     round2}.jazz + READMEs)
  10 ct/dudect/ (Makefile, combine_ct.go, dudect_combine.c,
     dudect_compat.h, dudect_verify.c, fetch.sh, README, run-
     submission.sh, verify_ct.go) + ct/jasmin-ct-libjade.md
  1 .github/workflows/ci.yml
  1 test/interoperability/n1_class_test.go (19/19 N1 subtests)
  1 bench/results/REPORT.md
  11 scripts/ (cut-submission, check-high-assurance, check-lean-
     bridge, nightly, extract-jasmin-ec, checks/{ec-admits, ec-
     compile, ec-refinement-scaffold, ec-regressions, extraction,
     jasmin}, checks/test/{go-unit, interop, kat, no-secret-logs})

Files merged (16 overlapping, mptc-canonical chosen because newer +
post-rewire-correct; pulsar versions still bore stale "Pulsar-M" /
"pulsarm" branding):
  README.md, BLOCKERS.md, CONTRIBUTING.md, LICENSE, LICENSING.md,
  SECURITY.md, .gitignore, bench/run_all.sh, vectors/dkg.json (v1.0.7
  regen), scripts/{bench,build,gen_vectors,sbom,test}.sh,
  spec/{pulsar,parameters,system-model}.tex,
  CRYPTOGRAPHER-SIGN-OFF.md (path refs).

Pulsar-only spec supplements preserved:
  spec/{blockers,design-decisions,family-architecture,nist-mptc-
  category,patent-notes,threat-model}.tex.

Path rewrites applied: 158 occurrences across 26 files
  github.com/luxfi/pulsar-mptc -> github.com/luxfi/pulsar
  ~/work/lux/pulsar-mptc/      -> ~/work/lux/pulsar/
  luxfi/pulsar-mptc            -> luxfi/pulsar
  pulsar-mptc/                  -> ./

Narrative collapses (no more two-repo framing):
  SUBMISSION.md "At a glance" — single Repository row
  SYNC-STATUS.md — rewritten to single-repo state
  SINGLE-IMPL-PLAN.md — marked COMPLETED 2026-05-18
  HANZO-CRYPTO-SUITE.md — tier 1 row = single canonical home
  scripts/cut-submission.sh — replace/vendor dance removed; cuts
  directly from in-tree canonical sources

go.mod: dropped mptc's replace directive (no longer needed since this
IS the canonical pulsar repo). Module path is github.com/luxfi/pulsar.
Deps: cloudflare/circl v1.6.3, golang.org/x/crypto v0.32.0.

Verification:
  GOWORK=off go build ./...              PASS
  GOWORK=off go test -count=1 ./...      PASS (1.4s)
  GOWORK=off go test -race ./ref/...     PASS (14.7s)
  go test ./test/interoperability/       PASS (19/19 N1 subtests)
  scripts/check-high-assurance.sh        PASS
  scripts/check-lean-bridge.sh           PASS (5/5 bridges)
  scripts/gen_vectors.sh                 byte-identical replay
  scripts/cut-submission.sh --help       PASS
2026-05-18 19:53:08 -07:00