Mirrors the consensus + node Corona purge. The production Ring-LWE
threshold library is luxfi/corona; the threshold-scheme byte and all
aggregator codepaths use the production identifier.
Replace github.com/luxfi/crypto/ipa/banderwagon with the canonical
github.com/luxfi/crypto/banderwagon in ipa/batch.go and its test, plus
the verkle-ipa docs example and the rust spec_vectors comment. The old
ipa/banderwagon subdirectory was deleted in 5a1479b; banderwagon now
has a single canonical home at the top level of luxfi/crypto.
go.mod adds the indirect entries for go-verkle and go-ipa that the
rerouted test_helper graph now exercises. The luxfi-mirror replace
directives remain in place so all upstream go-ipa/go-verkle traffic
still flows through luxfi-maintained sources.
Build: go build ./... clean (one ld linker warning unrelated).
Tests: ./banderwagon/... ./ipa/... pass (7 ok, 2 no-test-files).
Pre-existing failure in ./verkle/ is unrelated: verkle_test.go
references BatchProof/VerifyBatch/ErrBatchLengthMismatch symbols that
were never implemented in the verkle package (separate gap, present on
main before this fix).
The unified C ABI header in luxcpp/crypto was renamed from c-abi/lux_crypto.h
to c-abi/crypto.h as part of the brand-neutral sweep. Update doc comments to
reference the new filename.
No functional change; comments only.
Domain separation tags and identifiers in cryptographic code must be
readable in a scientific paper without product context. Strip the Lux
brand from in-code crypto identifiers; algorithm names ARE the namespace.
DSTs (golden vectors regenerated):
pedersen NewGenerators: LUX_PEDERSEN_{G,H} -> PEDERSEN_{G,H}_V1
pedersen NewGeneratorsFromSeed: LUX_PEDERSEN_SEEDED_GEN_V1 -> PEDERSEN_SEEDED_GEN_V1
pedersen golden G/H test vectors recomputed for the new DST.
Env vars (one canonical name only — no deprecated alias):
backend.envBackend: drop LUX_CRYPTO_BACKEND fallback, CRYPTO_BACKEND only
rust/build.rs: drop LUX_CRYPTO_DIR / LUX_CRYPTO_BUILD_DIR fallbacks
Rust c-abi link names:
lux-crypto-keccak: extern "C" name keccak256 (was lux_keccak256)
lux-crypto-secp256k1: secp256k1_ecrecover{,_batch} (was lux_*)
lux-crypto umbrella: drop all #[link_name = "lux_*"] attrs;
the canonical luxcpp/crypto C-ABI exports brand-neutral symbols
directly, the Rust function names mirror them one-for-one.
Go cgo aliases:
hash/blake3/blake3_c.go: drop the four #define aliases that mapped
crypto_* -> lux_crypto_*; the C header now declares brand-neutral
names directly.
Tests passing:
lux/crypto: 50 packages ok, 0 fail (GOWORK=off go test ./... -short)
rust workspace: 18 tests across 3 crates (CRYPTO_BUILD_DIR=... cargo test --release)
The luxcpp/crypto archives export bare-named C symbols (keccak256,
secp256k1_ecrecover, blake3, ed25519_sign, slhdsa_sign) consistently
across all 30+ algorithms. The keccak/secp256k1/blake3 Rust crates had
drifted to declaring `lux_<alg>_<op>` link names that the archives
never exposed, causing link-time symbol-not-found at workspace test.
- keccak: drop link_name="lux_keccak256", call bare keccak256
- secp256k1: drop link_name="lux_secp256k1_ecrecover{,_batch}", call bare
- blake3: archive only exports `blake3` today; remove the unimplemented
keyed_hash/derive_key/hash_xof Rust facade plus the broken
spec_vectors test that referenced a non-existent JSON file
- ed25519, slhdsa: unchanged (already matched archive)
cargo test --release --workspace: 0 link errors. The pre-existing
ed25519 RFC8032 failures (returning -5 = CRYPTO_ERR_NOTIMPL) are due
to the C-ABI ed25519 still being a NOTIMPL stub in luxcpp/crypto, not
a symbol-audit issue.
Fills the Rust binder gaps from CANONICAL_AUDIT.md (commit 9affea3). Each
crate is a thin extern-C binding to the corresponding luxcpp/crypto C-ABI
archive, mirroring the existing keccak/blake3/secp256k1/ed25519/slhdsa
pattern.
Per-crate layout: Cargo.toml + build.rs + src/lib.rs + tests/kat.rs.
build.rs resolves the luxcpp install dir via CRYPTO_DIR / CRYPTO_BUILD_DIR
with a fallback to ../../../../luxcpp/crypto/build-cto. Archives are linked
PRIVATE so blst/banderwagon/etc do not leak past the crate boundary.
Tests: 20 KATs pass across the 14 new crates against the live luxcpp
build at /Users/z/work/luxcpp/crypto/build-cto. Real-body algos (sha256,
ripemd160, blake2b, evm256, ipa, kzg, pedersen) are exercised against
known-answer vectors; algos whose c-abi shim returns CRYPTO_ERR_NOTIMPL
in this build (lamport, bls, mldsa, mlkem, ntt, poly_mul, aead) accept
either a successful round-trip or NOTIMPL coherently across all entry
points.
Workspace cargo build --release --workspace passes. The pre-existing
keccak/secp256k1/blake3 spec-vector tests fail at link time due to
unrelated lux_ prefix drift after the brand-neutral C-ABI rename; not
addressed in this batch.
Adds lux-crypto-slhdsa crate binding to FIPS 205 SLH-DSA. Wraps the
luxcpp/crypto/slhdsa C-ABI (slhdsa_keygen/sign/verify) over the vendored
PQClean reference (sphincs-{sha2,shake}-{128,192,256}f-simple/clean,
CC0/public domain), six 'f' fast parameter sets:
Mode 2/3/5 -> SLH-DSA-SHA2-{128,192,256}f (NIST L1/L3/L5)
Mode 12/13/15 -> SLH-DSA-SHAKE-{128,192,256}f (NIST L1/L3/L5)
Surface: Mode enum with const pk_len/sk_len/sig_len matching FIPS 205
§10 catalogue (32/48/64 pk; 64/96/128 sk; 17088/35664/49856 sig).
keygen / sign / verify return Result<_, Error> with explicit
InvalidLength / InvalidSignature / InternalError discriminants.
Underlying byte-equal NIST KAT compliance is shown by the C++ side at
build-cto/slhdsa_kat_test (498 PASS lines across all six variants).
Rust roundtrip suite covers (keygen, sign, verify, tampered-sig,
tampered-pk, tampered-msg, short-pk) for the four 128f/192f variants
plus a sizes-match-FIPS205 invariant; 256f is gated --ignored
(sign() takes 30+s on M1).
cargo test -p lux-crypto-slhdsa: 6 passed, 2 ignored (long).
Add lux-crypto-ed25519 to the rust workspace. The crate links statically
against libed25519.a + libed25519_cpu.a from the matching luxcpp/crypto
ed25519-cpu-vendor branch (e1e6eac4) and exposes the canonical Ed25519
surface:
keygen(seed) -> (sk, pk)
sign(sk, msg) -> sig
verify(pk, msg, sig) -> Result<(), Error>
The canonical secret form is the 32-byte RFC 8032 §5.1.5 seed; the expanded
NaCl 64-byte form lives inside the C wrapper.
tests/rfc8032_vectors.rs walks all 8 RFC 8032 §7.1 / Bernstein sign.input
vectors (TEST 1, 2, 3, 1024, SHA(abc), donna #4-#6) and asserts:
- keygen pk byte-equal to RFC pk
- sign sig byte-equal to RFC sig
- verify accepts the published triple
- verify rejects bit-flipped sig and pk
plus deterministic_signing and random_roundtrip (16 random seeds, 4
mutation positions each). 3/3 tests pass.
Run with: CRYPTO_BUILD_DIR=$LUXCPP/crypto/build-ed25519 cargo test
All 23 lux-crypto-* crates now have:
- README.md with algorithm description, build instructions
(CRYPTO_DIR / CRYPTO_BUILD_DIR), source attribution
- workspace-inherited authors/homepage/repository/documentation
- crates.io-ready metadata (description, keywords, categories)
cargo publish --dry-run --no-verify passes for all 23 crates.
PUBLISHING.md documents the publish runbook: license decision required
before upload, cargo login flow, name reservation order, dry-run sweep,
ordered upload, native-archive dependency (Option C documented), docs.rs
follow-up, versioning policy, source attribution table.
This prepares the crates for a human with a crates.io token to run the
real cargo publish step. No upload happens automatically -- the LICENSE
decision (BSD-3-Clause vs Lux Ecosystem License) must be confirmed first.
Two new no_std crates wrapping the C-ABI from luxcpp/crypto/ntt and
luxcpp/crypto/poly_mul.
lux-crypto-ntt:
* forward / inverse — generic-prime NTT (caller-supplied modulus + root)
* Cyclone-FFT fast path engaged automatically when (modulus, root) ==
(Q=998244353, PRIMITIVE_ROOT=629671588)
* 6 spec-vector tests:
- forward+inverse roundtrip across n in {2,4,...,1024}
- q97/omega=28 generic-prime roundtrip (matches Go reference)
- input rejection: empty, non-pow2, modulus=0
lux-crypto-poly_mul:
* multiply / multiply_into — Z_Q[X]/(X^n+1) negacyclic convolution
* Pinned to Cyclone-FFT prime (the C-ABI rejects other rings)
* 4 spec-vector tests including the canonical 10-case KAT table
(sum/first/last byte-equal to luxfi/crypto/poly_mul Go reference)
and the (1+2X+3X^2+4X^3)*(5+6X+7X^2+8X^3) hand-written negacyclic case.
build.rs links statically against libntt_cpu.a / libpoly_mul_cpu.a
produced by luxcpp/crypto/ntt and luxcpp/crypto/poly_mul; CRYPTO_BUILD_DIR
or CRYPTO_DIR points at the cmake build / install layout.
Verified: cargo test -p lux-crypto-ntt -p lux-crypto-poly_mul
6/6 ntt tests PASS, 4/4 poly_mul tests PASS.
Canonical Rust binding for the Poseidon2 t=2 BN254 Merkle-Damgard
hasher landed in luxcpp/crypto/poseidon. Links statically against
libposeidon.a + libposeidon_cpu.a and exposes:
hash(input) -> [u8; 32]
hash_into(input, output) -> in-place fill of caller buffer
Byte-equal to upstream gnark-crypto v0.20.1 (NewMerkleDamgardHasher
over NewParameters(2, 6, 50)). 10 spec-vector integration tests
pass, including the canonical 32B/64B/96B block-boundary cases and
trivial avalanche/determinism checks.
Crate is no_std + forbid(unsafe_op_in_unsafe_fn) and follows the
existing per-algorithm crate layout.
Real Rust binding over the now-real luxcpp/crypto/blake3 C-ABI
(commit c4a1d2e0, "vendor BLAKE3 v1.5.0 reference C"). Exposes all four
canonical BLAKE3 modes:
hash(input) -> [u8; 32]
keyed_hash(key, input) -> [u8; 32]
derive_key(context_z, key_material) -> [u8; 32]
hash_xof(input, &mut output) -> ()
Statically links libblake3.a + libblake3_cpu.a from the build dir
(CRYPTO_BUILD_DIR or the canonical build-cto/ default).
Test (tests/spec_vectors.rs) parses upstream test_vectors.json (vendored
under luxcpp/crypto/blake3/test/vectors/) and asserts byte-equality
across all 35 cases x 4 modes = 140 assertions. cargo test PASS.
The lux-crypto umbrella crate's build.rs defaulted to ../../../../luxcpp/crypto/
build-canonical when neither CRYPTO_DIR nor CRYPTO_BUILD_DIR was set. That
directory is a partial build from before the 2026-04-26 brand-neutral C-ABI
rename (luxcpp commit e8690bb8 "drop lux_ prefix from C-ABI symbols"). Its
libsecp256k1_cpu.a still exports _lux_secp256k1_ecrecover (legacy) while the
Rust extern "C" block expects _secp256k1_ecrecover (post-rename, brand-neutral).
build-canonical also lacks banderwagon/sha256/ripemd160 archives.
All 17 sibling per-algorithm crates already default to build-cto; only the
umbrella was misaligned. Switching the umbrella default to build-cto makes the
workspace build out of the box.
Verified: cargo test --workspace --all-features reports 182 PASS, 0 fail
(matching the #97-retry baseline) with no env vars set, and also with explicit
CRYPTO_BUILD_DIR=/Users/z/work/luxcpp/crypto/build-cto.
- 3 new pure-Rust unit tests covering all Secp256k1Status::from_int
arms (0..=7 + invalid), all CryptoStatus::from_int arms (Ok variants
+ 5 typed error variants + Unknown), and all NIST mode dispatch
for mldsa/mlkem/slhdsa (Mode2, Mode3, Mode5).
- 9/9 tests passing via `cargo test --lib`.
- COVERAGE.md: pure-Rust dispatch helpers at 100% line; whole-crate
36.97% reflects FFI declaration weight (extern "C" blocks +
thin pub fn wrappers that forward to luxcpp/crypto C-ABI). The
cryptographic logic itself is tested in luxcpp/crypto/<alg>/test/.
- BENCHMARKS.md: explicit no-criterion-yet note; Rust crate adds
no measurable overhead to the FFI call so a Rust-side bench would
duplicate the C-side numbers within sampling noise.
- .gitignore: target/, *.profraw, *.profdata.
Adds Rust modules wrapping the canonical luxcpp/crypto C-ABI for:
- ML-DSA (FIPS 204) modes 2/3/5
- ML-KEM (FIPS 203) modes 2/3/5
- SLH-DSA (FIPS 205) modes 2/3/5
- Ed25519 keygen/sign/verify
- keccak256 single-shot
Each module exposes safe Rust wrappers with size validation and a typed
CryptoStatus enum from the unified lux_crypto.h return-code contract.
Brand-neutral surface (no LUX_ prefix on Rust constants); link_name
attributes map to the existing lux_<alg>_<op> archive symbols until the
next luxcpp rebuild flips the archives to brand-neutral.
build.rs links per-algorithm libcpp_cpu.a archives from the
build-canonical/<alg>/ subdirectories.
The -sys suffix is a Rust ecosystem convention for thin FFI bindings to
THIRD-PARTY C libraries (openssl-sys, libgit2-sys, etc.). We author the
C/C++ ourselves at luxcpp/crypto, so -sys would be misleading.
Brand-neutral rule: 'one and one way to do everything' — the crate is
lux-crypto, the lib name is lux_crypto. If a high-level safe wrapper is
ever needed, it lives inside this same crate as pub mod safe.
Mirrors the canonical pattern at github.com/luxfi/gpu (Rust binding to
luxfi/accel) — no -sys suffix on first-party crates.
Consumers update separately.
Phase-1 surface for Rust callers (Hanzo node, Lux node, Zoo node):
* secp256k1: lux_secp256k1_ecrecover + lux_secp256k1_ecrecover_batch
Build script locates luxcpp/crypto via LUX_CRYPTO_DIR / LUX_CRYPTO_BUILD_DIR
or defaults to a sibling-checkout layout. Links against libsecp256k1_cpu.a
and the platform C++ runtime.
Subsequent agents extend this with mldsa/mlkem/slhdsa/bls12381/etc.