mirror of
https://github.com/luxfi/crypto.git
synced 2026-07-27 01:54:50 +00:00
Adds the canonical runtime substrate selector for luxfi/crypto and decomplects
all per-algorithm GPU dispatchers behind it.
New `backend` API:
- Default()/SetDefault/Resolved()/IsGPU/IsCGo/IsVanilla — runtime selection
- CGoAvailable()/GPUAvailable() — real probes (was stubbed)
- Probe() returning Snapshot{Default, Resolved, CGo, GPU, Disabled,
GPUBackend, GPUDeviceCount, AccelVersion, Fallbacks}
- GPUDisabled() reads LUX_GPU_DISABLE operator kill switch
- RecordFallback(reason, where) atomic counter + one-shot log per reason,
low-cardinality FallbackReason enum (disabled / unsupported / probe_failed
/ backend_unavailable / abi_mismatch)
Dispatcher cleanup (one-and-one-way):
- All Resolve(gpuhost.Available(), false) call sites replaced with IsGPU()
- hqc switched to IsVanilla() (its accel batch wins for any non-vanilla pick)
- gpu/gpu.go now delegates entirely to backend (no separate session)
- internal/gpuhost dropped Snapshot()/Provenance — backend.Probe() canonical
Build tag policy: CGo is the only gate. There is no `gpu` build tag.
LLM.md documents the canonical surface.
87 lines
1.8 KiB
Go
87 lines
1.8 KiB
Go
// Copyright (C) 2020-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package secp256k1
|
|
|
|
import (
|
|
"github.com/luxfi/accel"
|
|
"github.com/luxfi/crypto/backend"
|
|
"github.com/luxfi/crypto/internal/gpuhost"
|
|
)
|
|
|
|
func batchVerifyGPU(pubkeys, msgHashes, sigs [][]byte, out []bool) (bool, error) {
|
|
if !backend.IsGPU() {
|
|
return false, nil
|
|
}
|
|
sess := gpuhost.Session()
|
|
if sess == nil {
|
|
return false, nil
|
|
}
|
|
|
|
n := len(pubkeys)
|
|
if n == 0 {
|
|
return false, nil
|
|
}
|
|
pkSize := len(pubkeys[0])
|
|
if pkSize != 33 && pkSize != 65 {
|
|
return false, nil
|
|
}
|
|
for _, p := range pubkeys {
|
|
if len(p) != pkSize {
|
|
return false, nil
|
|
}
|
|
}
|
|
|
|
mFlat := make([]uint8, n*32)
|
|
for i, m := range msgHashes {
|
|
if len(m) != 32 {
|
|
return false, nil
|
|
}
|
|
copy(mFlat[i*32:(i+1)*32], m)
|
|
}
|
|
sFlat := make([]uint8, n*64)
|
|
for i, s := range sigs {
|
|
if len(s) != 64 {
|
|
return false, nil
|
|
}
|
|
copy(sFlat[i*64:(i+1)*64], s)
|
|
}
|
|
pFlat := make([]uint8, n*pkSize)
|
|
for i, p := range pubkeys {
|
|
copy(pFlat[i*pkSize:(i+1)*pkSize], p)
|
|
}
|
|
|
|
mT, err := accel.NewTensorWithData[uint8](sess, []int{n, 32}, mFlat)
|
|
if err != nil {
|
|
return false, nil
|
|
}
|
|
defer mT.Close()
|
|
sT, err := accel.NewTensorWithData[uint8](sess, []int{n, 64}, sFlat)
|
|
if err != nil {
|
|
return false, nil
|
|
}
|
|
defer sT.Close()
|
|
pT, err := accel.NewTensorWithData[uint8](sess, []int{n, pkSize}, pFlat)
|
|
if err != nil {
|
|
return false, nil
|
|
}
|
|
defer pT.Close()
|
|
rT, err := accel.NewTensor[uint8](sess, []int{n})
|
|
if err != nil {
|
|
return false, nil
|
|
}
|
|
defer rT.Close()
|
|
|
|
if err := sess.Crypto().ECDSAVerifyBatch(mT.Untyped(), sT.Untyped(), pT.Untyped(), rT.Untyped()); err != nil {
|
|
return false, nil
|
|
}
|
|
bytes, err := rT.ToSlice()
|
|
if err != nil {
|
|
return false, nil
|
|
}
|
|
for i, b := range bytes {
|
|
out[i] = b == 1
|
|
}
|
|
return true, nil
|
|
}
|