Files
chains/bridgevm/bridgevm_gpu_nocgo.go
zeekay 430d46baf5 bridgevm: wire to GPU plugin substrate via dlopen + dlsym
Mirrors the evm/cevm pattern (cevm_cgo.go / cevm_nocgo.go +
backend_cgo.go). Three new files in bridgevm/:

  backend.go             — Backend enum, layout structs (byte-equal to
                            ops/bridgevm/cuda/bridgevm_kernels_common.cuh),
                            ErrGPUNotAvailable, GPUBackend interface,
                            unsafe.Sizeof asserts in init().
  bridgevm_gpu.go    cgo  — direct dlopen(3) + dlsym(3) for the per-backend
                            plugin libluxgpu_backend_<bk>.{so,dylib}.
                            Probes cuda → hip → metal → vulkan → webgpu in
                            order; first plugin exposing all five
                            lux_<bk>_bridgevm_* launchers wins.
  bridgevm_gpu_nocgo.go  — stub returning ErrGPUNotAvailable on every method.

Direct dlopen (NOT pkg-config) so the public chains module builds without
the private gpu-kernels repo present. Search path: \$LUX_GPU_PLUGIN_DIR,
\$LUXCPP_PREFIX/lib/lux-gpu, \$LUXCPP_PREFIX/lib, the dev tree under
~/work/lux-private/gpu-kernels/build/backends/<bk>, CWD, and finally the
system loader's default.

Five launcher signatures dispatched via cgo trampolines (one per shape) —
matches the C ABI in include/lux/gpu/bridgevm.h. Layout structs include
explicit '_pad*' fields to keep Go sizeof() byte-equal to the C++
alignas(16) layout; the init() sizeof asserts catch any drift at process
start with a per-struct panic message.

vm.go / bridge_signing.go / mpc.go are NOT touched — this is a thin
substrate; the round applier opts in later when it's ready to route
through ActiveGPUBackend().

bridgevm_gpu_test.go — four tests under //go:build cgo:
  TestActiveBackend          — AutoBackend() returns a known tag.
  TestStubReturnsErrGPUNotAvailable
                              — BackendNone path returns the sentinel.
  TestLayoutSizesMatchHeader — runtime-equivalent of the C++ static_asserts.
  TestSignerApplyZeroFixture — dlopen + dlsym + zero-fixture round trip
                                through lux_<best>_bridgevm_signer_apply.

Builds verified under both CGO_ENABLED=0 (nocgo path active) and
CGO_ENABLED=1 -tags cgo (cgo path active). All four cgo-tagged tests
pass on the local dev box (Vulkan plugin auto-detected from the
gpu-kernels build tree).
2026-06-05 14:53:18 -07:00

80 lines
2.1 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
//go:build !cgo
package bridgevm
// Non-cgo build of the BridgeVM GPU substrate. With CGO_ENABLED=0 we can't
// dlopen the plugin, so every GPUBackend method returns ErrGPUNotAvailable.
// The package-level AutoBackend() therefore reports BackendNone, and
// consumers (vm.go's round applier) should route to the CPU oracle.
//
// init() sets activeBackend to BackendNone explicitly — this mirrors the
// behaviour of the cgo build when the probe finds no plugin, so a caller's
// `if AutoBackend() == BackendNone { ... cpu fallback ... }` works
// identically under both build modes.
func init() {
setActiveBackend(BackendNone)
}
// ActiveGPUBackend returns a stub GPUBackend whose methods all return
// ErrGPUNotAvailable. Always non-nil so callers can dispatch without a nil
// check — they only need to handle the ErrGPUNotAvailable sentinel from
// the call sites.
func ActiveGPUBackend() GPUBackend { return nocgoBackend{} }
type nocgoBackend struct{}
func (nocgoBackend) Backend() Backend { return BackendNone }
func (nocgoBackend) SignerApply(
_ *BridgeVMRoundDescriptor,
_ []SignerOp,
_ []Signer,
) (uint32, error) {
return 0, ErrGPUNotAvailable
}
func (nocgoBackend) LiquidityApply(
_ *BridgeVMRoundDescriptor,
_ []LiquidityOp,
_ []LiquidityEntry,
) (uint32, uint64, uint64, error) {
return 0, 0, 0, ErrGPUNotAvailable
}
func (nocgoBackend) MessageInbox(
_ *BridgeVMRoundDescriptor,
_ []Message,
_ []Signer,
_ []DailyLimit,
_ []Message,
) (uint32, uint64, uint64, error) {
return 0, 0, 0, ErrGPUNotAvailable
}
func (nocgoBackend) MessageOutbox(
_ *BridgeVMRoundDescriptor,
_ []OutboundReq,
_ []DailyLimit,
_ []Message,
_ *BridgeVMEpochState,
) (uint32, uint64, uint64, error) {
return 0, 0, 0, ErrGPUNotAvailable
}
func (nocgoBackend) BridgeTransition(
_ *BridgeVMRoundDescriptor,
_ []Signer,
_ []LiquidityEntry,
_ []DailyLimit,
_ []Message,
_ []Message,
_ *BridgeVMEpochState,
_ *BridgeVMTransitionResult,
) error {
return ErrGPUNotAvailable
}