mirror of
https://github.com/luxfi/crypto.git
synced 2026-07-27 01:54:50 +00:00
luxfi/crypto becomes the single Go entry point for ALL Lux-family crypto. Every public function in this module now dispatches between three implementations through a runtime-selectable backend: - vanilla: pure-Go reference (always available) - cgo: native binding (blst, libsecp256k1, ckzg) where present - gpu: batch acceleration via github.com/luxfi/accel The dispatcher reads LUX_CRYPTO_BACKEND (auto|vanilla|cgo|gpu); auto picks the most capable backend the binary was compiled and linked with. New canonical packages: backend/ runtime backend selector (env + programmatic) internal/gpuhost/ accel session lifecycle, single per-process keccak/ Keccak-256 with batch GPU dispatch sha256/ SHA-256 with batch GPU dispatch sha3/ SHA3 / SHAKE family ripemd160/ RIPEMD-160 (Bitcoin/Lux address derivation) ed25519/ Ed25519 with batch GPU verify bn254/ canonical alias for bn256 (matches FIPS naming) modexp/ canonical alias for bigmodexp evm256/ EIP-196/197 precompile ABI wrappers poseidon/ Poseidon2 hash via gnark-crypto pedersen/ Pedersen commitments over BN254 ntt/ Number-Theoretic Transform reference polymul/ negacyclic polynomial multiplication Extended existing packages with batch GPU paths: bls/batch.go BatchVerify routes through accel.BLSVerifyBatch mldsa/batch.go BatchVerify (ML-DSA-65) via accel.DilithiumVerifyBatch mlkem/batch.go BatchEncapsulate / BatchDecapsulate via Kyber kernels secp256k1/batch.go BatchVerifySignature via accel.ECDSAVerifyBatch GPU dispatch is gated on (a) backend.Default(), (b) batch size threshold, and (c) accel.Available(). When any gate fails the call falls through to the vanilla CPU path; output is byte-identical. The legacy gpu/ stub is replaced with a thin probe surface (Available, Backend, Devices, Version) that delegates to the same gpuhost session. Tests show vanilla and gpu backends produce identical outputs across all batch entry points (-race clean). See AUDIT.md for the per-algorithm state matrix and honest gaps.
131 lines
3.3 KiB
Go
131 lines
3.3 KiB
Go
// Package backend defines the runtime backend selector for luxfi/crypto.
|
|
//
|
|
// Every crypto package in this module has up to three implementations:
|
|
//
|
|
// - vanilla: pure-Go reference (always available)
|
|
// - cgo: native C library binding (blst, libsecp256k1, ckzg, ...)
|
|
// - gpu: batch acceleration via github.com/luxfi/accel
|
|
//
|
|
// The package selects which implementation to run based on the value of
|
|
// Default(). Callers can override programmatically with SetDefault(),
|
|
// or globally with the LUX_CRYPTO_BACKEND environment variable.
|
|
//
|
|
// The default value is Auto — pick the most capable backend the binary
|
|
// was compiled and linked with, in the order GPU > CGo > Vanilla.
|
|
package backend
|
|
|
|
import (
|
|
"os"
|
|
"strings"
|
|
"sync/atomic"
|
|
)
|
|
|
|
// Backend identifies a crypto implementation choice.
|
|
type Backend uint32
|
|
|
|
const (
|
|
// Auto selects the best available backend automatically.
|
|
Auto Backend = iota
|
|
// Vanilla forces the pure-Go reference implementation.
|
|
Vanilla
|
|
// CGo forces the native C-library backed implementation when available.
|
|
CGo
|
|
// GPU forces routing through github.com/luxfi/accel when available.
|
|
GPU
|
|
)
|
|
|
|
// String returns the canonical lowercase name of the backend.
|
|
func (b Backend) String() string {
|
|
switch b {
|
|
case Auto:
|
|
return "auto"
|
|
case Vanilla:
|
|
return "vanilla"
|
|
case CGo:
|
|
return "cgo"
|
|
case GPU:
|
|
return "gpu"
|
|
default:
|
|
return "unknown"
|
|
}
|
|
}
|
|
|
|
// Parse converts a string identifier to a Backend. Empty string returns Auto.
|
|
func Parse(s string) (Backend, bool) {
|
|
switch strings.ToLower(strings.TrimSpace(s)) {
|
|
case "", "auto":
|
|
return Auto, true
|
|
case "vanilla", "go", "pure":
|
|
return Vanilla, true
|
|
case "cgo", "c", "native":
|
|
return CGo, true
|
|
case "gpu", "accel":
|
|
return GPU, true
|
|
default:
|
|
return Auto, false
|
|
}
|
|
}
|
|
|
|
var current uint32 // atomic Backend
|
|
|
|
func init() {
|
|
if v, ok := os.LookupEnv("LUX_CRYPTO_BACKEND"); ok {
|
|
if b, parsed := Parse(v); parsed {
|
|
atomic.StoreUint32(¤t, uint32(b))
|
|
}
|
|
}
|
|
}
|
|
|
|
// Default returns the active backend selection. The value is Auto unless
|
|
// SetDefault was called or LUX_CRYPTO_BACKEND was set in the environment.
|
|
func Default() Backend {
|
|
return Backend(atomic.LoadUint32(¤t))
|
|
}
|
|
|
|
// SetDefault overrides the active backend.
|
|
//
|
|
// Use the empty string or "auto" via Parse to revert to Auto behavior.
|
|
func SetDefault(b Backend) {
|
|
atomic.StoreUint32(¤t, uint32(b))
|
|
}
|
|
|
|
// Resolve picks a concrete backend for the caller. If Default() is Auto the
|
|
// resolution falls back through GPU → CGo → Vanilla, choosing the first
|
|
// backend reported as available by the supplied probes. probes may be nil;
|
|
// in that case Resolve returns Vanilla for Auto.
|
|
//
|
|
// This is the primary entry point used inside algorithm packages:
|
|
//
|
|
// switch backend.Resolve(gpuOK, cgoOK) {
|
|
// case backend.GPU: return keccak256GPU(in)
|
|
// case backend.CGo: return keccak256CGo(in)
|
|
// default: return keccak256Vanilla(in)
|
|
// }
|
|
func Resolve(gpuAvailable, cgoAvailable bool) Backend {
|
|
switch d := Default(); d {
|
|
case Vanilla:
|
|
return Vanilla
|
|
case CGo:
|
|
if cgoAvailable {
|
|
return CGo
|
|
}
|
|
return Vanilla
|
|
case GPU:
|
|
if gpuAvailable {
|
|
return GPU
|
|
}
|
|
if cgoAvailable {
|
|
return CGo
|
|
}
|
|
return Vanilla
|
|
default: // Auto
|
|
if gpuAvailable {
|
|
return GPU
|
|
}
|
|
if cgoAvailable {
|
|
return CGo
|
|
}
|
|
return Vanilla
|
|
}
|
|
}
|