Files
zeekay 10b2d9ae01 accel: implement lux_lattice_ntt_mldsa_batch + lux_mldsa_verify_batch (was ErrNotSupported stub)
Pulsar audit (commit 2dd1383) identified these as the missing wiring blocking
GPU acceleration for ML-DSA threshold signing. This change ships the C ABI
plumbing end-to-end:

  1. internal/capi/include/lux/accel/c_api.h
     - declares lux_mldsa_sign_batch, lux_mldsa_verify_batch (FIPS 204; modes
       2/3/5 = ML-DSA-44/65/87)
     - declares lux_lattice_ntt_mldsa_batch (in-place forward/inverse NTT
       over Z_q[X]/(X^256+1), q=8380417)

  2. internal/capi/stub.go — adds weak-symbol stubs returning LUX_NO_BACKEND
     so the build succeeds without libluxaccel.

  3. internal/capi/capi.go — replaces the placeholder _ = stubs that returned
     ErrNotSupported with real cgo calls. Reorders the header search path so
     the vendored c_api.h takes precedence over older installed snapshots
     (single source of truth: ${SRCDIR}/include/lux/accel/c_api.h).

  4. ops_lattice.go — adds LatticeNTTMLDSABatch to the LatticeOps interface,
     consumed by both cgoLatticeOps (ops_c.go) and stubLatticeOps (ops.go).

  5. accel_c.go — top-level Go API:
       MLDSAVerifyBatch(mode, msgs, sigs, pks, msgWidth)
       MLDSASignBatch(mode, msgs, sks, msgWidth)
       LatticeNTTMLDSABatch(polys, inverse)
     Below MLDSABatchThreshold=8 each returns ErrNotSupported so callers
     route to their per-element CPU oracle (pulsar's existing fallback).

  6. errors.go — adds MLDSAMode{44,65,87}, per-mode pk/sk/sig widths,
     MLDSANTTPolyLen=256, MLDSABatchThreshold=8.

  7. ops/lattice/mldsa_ntt.go — Go CPU oracle byte-equal to
     PQCLEAN_MLDSA65_CLEAN_ntt and PQCLEAN_MLDSA65_CLEAN_invntt_tomont.
     Same 256-entry zeta table the lux-private/gpu-kernels/ops/lattice/
     ntt_mldsa kernels embed across every backend (CUDA/HIP/Metal/WGSL).

Tests:
  - ops/lattice/mldsa_ntt_test.go: round-trip identity, zero-input, constant-
    poly evaluation, zeta-table endpoint pins, Montgomery-reduce edge case,
    batch=22 (Pulsar Round-2 shape) byte-equality to per-poly oracle.
  - accel_test.go: MLDSAVerifyBatch/MLDSASignBatch/LatticeNTTMLDSABatch
    surface checks, FIPS 204 width constants.

Verified:
  - go test ./... PASS on cgo + CGO_ENABLED=0 + -tags=accel.
  - pulsar TestPulsar_GPU_ByteEqual PASS (~/work/lux/pulsar regression).
  - go vet clean, gofmt clean.
2026-06-03 12:23:15 -07:00
..