79 Commits
Author SHA1 Message Date
zeekay 531f4fc8a2 thresholdvm: rip github.com/luxfi/codec — swap singleton for encoding/json
Wave 3C of codec final rip (#101). thresholdvm/codec.go was a 9-call
singleton registering 11 types — all already had json struct tags, so
the swap to encoding/json is identical wire semantics minus the codec
version prefix byte.

Sibling VMs (aivm, dexvm, quantumvm, bridgevm-cpu paths) already use
encoding/json for the same persistence + cross-chain-request surface,
so this is the canonical one-and-only-one way.

Changes:
- chains/thresholdvm/codec.go DELETED (orphan singleton)
- chains/thresholdvm/vm.go: 7 sites Codec.{Marshal,Unmarshal} → json.{Marshal,Unmarshal}
- chains/thresholdvm/block.go: 2 sites + encoding/json import

Tests pass: thresholdvm (17.130s), cert, fhe, types.
Final grep "github.com/luxfi/codec" in thresholdvm/: zero.

Remaining codec.go callers in chains/ module: zkvm, bridgevm (separate waves).
v1.3.2
2026-06-06 01:07:15 -07:00
zeekay 26a9574a85 WIP: auto-bench checkpoint 2026-06-05 2026-06-05 17:31:51 -07:00
zeekay 73d8aa476d thresholdvm: decomplect cgo bridge — pure-Go MPCVM reference shared by both build flavors
The existing thresholdvm bridge had a real cgo path (dlopen + dlsym
into the per-backend GPU plugins) and a stub nocgo path that just
returned ErrGPUNotAvailable on every method. That meant a !cgo build
couldn't actually run the MPC state machine.

Decomplect by introducing ONE pure-Go reference implementation that
both build flavors share:

* thresholdvm_gpu_cpu.go (no build tags) — port of
  luxcpp/mpcvm/src/mpcvm_cpu_reference.cpp. Implements the four
  substrate ops (ceremonyApplyCPU, contributionApplyCPU,
  keyShareApplyCPU, mpcTransitionCPU) byte-for-byte identical to the
  CUDA / Metal / WGSL / Vulkan / HIP kernels in
  lux-private/gpu-kernels/ops/mpcvm/<X>/. keccak256 via
  golang.org/x/crypto/sha3 (the canonical Lux Go Keccak).

* thresholdvm_gpu.go (cgo) — bridge methods now try the GPU plugin
  first and fall through to ceremonyApplyCPU et al on:
    - nil receiver / no dlopen handle / missing launcher symbol,
    - launcher returning a non-zero rc.
  ErrGPUNotAvailable is only returned on input-validation failures
  (nil desc, empty arena) — never on a missing plugin, which is no
  longer a fatal condition.

* thresholdvm_gpu_nocgo.go (!cgo) — every method delegates to the same
  pure-Go reference. Same wire structs, same algorithm, byte-equivalent
  output.

* thresholdvm_gpu_parity_test.go — TestGPUBridgeCgoNocgoParity runs a
  3-of-5 FROST keygen ceremony through the public GPUBackend method
  set AND through the pure-Go reference directly, then byte-compares
  the arenas, state, and transition result. The ceremony finalizes
  with 5 emitted shares and a non-zero mpcvm_state_root. Passes under
  both cgo and !cgo builds.

The Go state machine in protocols.go / executor.go / protocol/ is
untouched — it remains the high-level threshold-crypto handler that
the VM uses for actual signing sessions (LSS, CGGMP21, FROST, BLS).
The CPU file is the substrate-level reference that matches the GPU
ABI wire structs, which is a separate concern.

One and only one way to run the substrate: the pure-Go reference in
thresholdvm_gpu_cpu.go. The GPU is a positive-performance overlay
the bridge tries first.
2026-06-05 16:30:00 -07:00
zeekay 85440e105d chains: scrub private-repo leakage from GPU bridges
OSS public chains module must not reference the private GPU plugin
implementation by repo name or filesystem path. Two leak types fixed:

1. Hard compile-time dependency in quantumvm:
   `#cgo CFLAGS: -I${SRCDIR}/../../../lux-private/gpu-kernels/include`
   Vendor the public ABI v14 header (backend_plugin.h + crypto.h, 1475
   LOC total) into chains/internal/luxgpu/include/lux/gpu/ and point
   CFLAGS at the in-tree path. Plugin DSO is still dlopen'd at runtime
   — only the public C ABI surface is vendored.

2. Soft leakage — `LUX_PRIVATE_GPU_KERNELS_DIR` env vocabulary, dev-tree
   probe paths to ~/work/lux-private/gpu-kernels/build/..., prose
   mentions of "lux-private/gpu-kernels" in package comments.
   All replaced with `LUX_GPU_PLUGIN_DIR` (universal env) and generic
   "GPU plugin" prose.

Bridges affected: aivm, bridgevm, dexvm, quantumvm, thresholdvm.
All 139 tests PASS post-scrub under both build tags. No functional
behavior change — only path / env / prose.
v1.3.1
2026-06-05 15:46:00 -07:00
zeekay c806865854 Merge feature/thresholdvm-cgo-bridge: thresholdvm GPU plugin bridge v1.3.0 2026-06-05 15:33:48 -07:00
zeekay 47f5e2daef Merge feature/quantumvm-cgo-bridge: quantumvm GPU plugin bridge 2026-06-05 15:33:48 -07:00
zeekay 5205376c86 Merge feature/dexvm-cgo-bridge: dexvm GPU plugin bridge 2026-06-05 15:33:48 -07:00
zeekay 95d4ffb7fe Merge feature/bridgevm-cgo-bridge: bridgevm GPU plugin bridge 2026-06-05 15:33:48 -07:00
zeekay 304de568da Merge feature/aivm-cgo-bridge: aivm GPU plugin bridge 2026-06-05 15:33:48 -07:00
zeekay 45d52cbbd6 thresholdvm: drop LUX_THRESHOLDVM_GPU_BACKEND env knob — auto-probe only 2026-06-05 15:22:05 -07:00
zeekay a643ecd8e6 thresholdvm: GPU substrate bridge via dlopen+dlsym to mpcvm host launchers
Wires the M-Chain ThresholdVM Go package to per-backend GPU plugins
in lux-private/gpu-kernels/backends/<X>/. Same 3-file pattern as
chains/evm/cevm but with runtime dlopen instead of compile-time
pkg-config. Bridge is a strict positive overlay — never a hard dep.

Files (under thresholdvm/):
- thresholdvm_gpu.go       (cgo)  : dlopen+dlsym; GPUBackend struct with
                                    CeremonyApply, KeyShareApply,
                                    ContributionApply, MPCTransition
- thresholdvm_gpu_nocgo.go (!cgo) : ErrGPUNotAvailable stub mirroring
                                    the cgo type surface
- backend.go               (cgo)  : init() probe — cuda -> hip -> metal
                                    -> vulkan -> webgpu, candidate paths
                                    from LUXCPP_PREFIX +
                                    LUX_PRIVATE_GPU_KERNELS_DIR
- thresholdvm_gpu_test.go         : 4 tests across both build flavors

Symbols (per backend X in {cuda, hip, metal, vulkan, webgpu}):
- lux_<X>_mpcvm_ceremony_apply  (begin/cancel + contribution dedup)
- lux_<X>_mpcvm_ceremony_sweep  (DKG finalize -> key share assignment)
- lux_<X>_mpcvm_compute_leaves  (parallel keccak per slot)
- lux_<X>_mpcvm_compose_root    (serial fold + epoch advance)

Wire structs (GPU- prefix to avoid collision with the domain KeyShare
interface in protocols.go) match ops/mpcvm/cuda/mpcvm_kernels_common.cuh
__align__(16) layouts byte-for-byte. sizeof asserts at package init()
+ TestGPULayoutSizes — any drift fails fast.

Corona = R-LWE threshold sig (active PQ variant per project memory).
Pulsar = threshold ML-DSA. Magnetar = threshold SLH-DSA (not built yet).
Bridge dispatches Corona on CeremonyOp.kind in {Corona DKG, Corona Sign}.

Constraints honored:
- Existing thresholdvm vm.go core paths NOT modified — bridge is opt-in
- Both build flavors compile: go build + CGO_ENABLED=0 go build
- Tests pass: 4/4 under cgo, 4/4 under nocgo, race-clean

Env knobs:
- LUX_THRESHOLDVM_GPU_BACKEND=cuda|hip|metal|vulkan|webgpu|none
- LUX_THRESHOLDVM_GPU_DEBUG=1
- LUXCPP_PREFIX, LUX_PRIVATE_GPU_KERNELS_DIR
2026-06-05 15:00:10 -07:00
zeekay 813e45e234 quantumvm: wire GPU plugin substrate via ABI v14 vtbl dlopen+dlsym
Adds four Go files to chains/quantumvm so the Q-Chain VM can call into
the lux-private/gpu-kernels plugin's batched ML-DSA verify, ML-DSA sign,
and SLH-DSA verify slots without a build-time pkg-config dependency:

* backend.go            cross-build types: Backend enum, GPUBackend
                        interface, MLDSAMode + MLDSA65* size constants,
                        SLHDSAVariant enum + per-variant pk/sig widths
                        (FIPS 204 / FIPS 205), ErrGPUNotAvailable,
                        AutoBackend(). Build-tag-free so vm.go can
                        reference the surface regardless of CGO_ENABLED.
* quantumvm_gpu.go      cgo dlopen probe at init() in order
   (cgo)                cuda -> hip -> metal -> vulkan -> webgpu,
                        resolving lux_gpu_backend_init and verifying
                        the ABI v14 cookies (abi_version + vtbl_size)
                        plus the load-bearing op_mldsa_verify_batch
                        slot before opening a LuxBackendContext. Three
                        vtbl-slot wrappers dispatch through C
                        trampolines into op_mldsa_verify_batch,
                        op_mldsa_sign_batch, and the SHAKE-128f /
                        SHAKE-192f variants of op_slhdsa_verify_batch.
* quantumvm_gpu_nocgo.go symmetric noGPUBackend stub returning
                        ErrGPUNotAvailable on every method so the
                        package surface is identical under !cgo.
* quantumvm_gpu_test.go round-trip test: dlopens the configured
                        plugin (LUX_GPU_PLUGIN_DIR override or default
                        loader path), generates an ML-DSA-65 keypair +
                        signs a 64-byte digest via circl, then submits
                        the triple through MLDSAVerifyBatch and asserts
                        results[0] == true. Cleanly SKIPs when no
                        plugin loaded or when the backend returns
                        NOT_SUPPORTED for op_mldsa_verify_batch (e.g.
                        plugins built without LUX_GPU_LINK_CRYPTO).

The probe is header-only: cgo CFLAGS points at
${SRCDIR}/../../../lux-private/gpu-kernels/include for the v14 vtbl
layout, but the .dylib / .so is dlopen'd at runtime - no pkg-config,
no static link, no luxcpp/install dependency. Existing quantumvm
vm.go, quantum/signer.go, and quantumvm/quasar.go are untouched;
consumers opt in explicitly when ready. Both 'go build ./quantumvm/...'
and 'CGO_ENABLED=1 go build ./quantumvm/...' are green.

Test output with LUX_GPU_PLUGIN_DIR pointing at a freshly-built
libluxgpu_backend_vulkan.dylib:
  --- PASS: TestAutoBackend_Probes (0.00s)          [backend=vulkan]
  --- PASS: TestMLDSAVerifyBatch_RoundTrip (5.56s)  [backend=vulkan,
            op_mldsa_verify_batch honest verify -> true]
  --- PASS: TestMLDSAVerifyBatch_LengthMismatch (0.00s)
  --- PASS: TestMLDSAVerifyBatch_NonMLDSA65Skips  (0.00s)
2026-06-05 14:59:54 -07:00
zeekay 82518705c4 dexvm: wire GPU plugin substrate via dlopen+dlsym
Adds four Go files to chains/dexvm so the DEX VM can call into the
lux-private/gpu-kernels plugin DEX launchers (AMM xyk + CLOB matcher +
BookArena lifecycle) without a build-time pkg-config dependency:

* backend.go            cross-build types: GPUBackend enum, LuxAmmReservePair
                        (16 bytes, byte-equal to include/lux/gpu/dex.h),
                        CLOB ABI constants, ErrGPUNotAvailable.
* dexvm_gpu.go (cgo)    dlopen probe at init() in order
                        cuda -> hip -> metal -> vulkan -> webgpu, resolving
                        lux_<backend>_{amm_xyk_batch,dex_clob_match,
                        dex_clob_arena_create,dex_clob_arena_destroy}.
                        Exposes AutoBackend / AMMSwap / CLOBMatch /
                        ArenaCreate / ArenaDestroy. unsafe.Sizeof guards
                        the AMM struct layout against silent ABI drift.
* dexvm_gpu_nocgo.go    symmetric stubs returning ErrGPUNotAvailable so
                        the package surface is identical under both tags.
* dexvm_gpu_test.go     round-trip test: dlopens the metal plugin (or any
                        other found under LUX_GPU_PLUGIN_DIR), runs a
                        single-pair AMM swap, asserts byte-equal output
                        to the CPU oracle (constant-product 1000 -> 1998
                        at rx=1M, ry=2M).

Existing dexvm vm.go / orderbook logic is untouched - consumers opt in
explicitly when ready. Both 'go build ./dexvm/...' and
'go build -tags cgo ./dexvm/...' are green.

Test output with LUX_GPU_PLUGIN_DIR=$HOME/work/lux-private/gpu-kernels/build-metal/backends/metal:
  --- PASS: TestGPUAMMSwapRoundTrip (0.08s) [backend=metal]
  --- PASS: TestGPUAMMSwapEmpty     (0.00s)
2026-06-05 14:54:56 -07:00
zeekay 72bc0467c2 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
zeekay 2662042f0d aivm: wire the GPU plugin substrate via dlopen/dlsym
Mirrors chains/evm/cevm/cevm_cgo.go + cevm_nocgo.go but uses pure
dlopen/dlsym instead of pkg-config so the chains module compiles
without the lux-private/gpu-kernels build tree present.

New files
=========

* aivm_gpu.go (cgo)      — GPUBackend with six host-launcher
                            wrappers (AttestationApply,
                            ProvenanceApply, AnchorApply,
                            EpochTransition, InferenceStep,
                            ProofVerify). Layout structs match
                            ops/aivm/cuda/aivm_kernels_common.cuh
                            byte-for-byte; an init() panics on drift.
* aivm_gpu_nocgo.go      — stub GPUBackend returning
                            ErrGPUNotAvailable so vm.go's gpu paths
                            degrade cleanly.
* backend.go (cgo)       — dlopen probe at process start. Walks
                            libluxgpu_backend_cuda.so → hip.so →
                            metal.dylib → vulkan.{so,dylib} →
                            webgpu.{so,dylib}. Honors
                            LUX_GPU_PLUGIN_DIR /
                            LUX_PRIVATE_GPU_KERNELS_DIR /
                            LUXCPP_PREFIX env. Exposes the public
                            parallel.SetBackend(AutoAIVM) analogue
                            (Mode / SetBackend / ActiveMode /
                            EffectiveBackendKind).
* aivm_gpu_test.go (cgo) — layout-drift guard + dlopen round-trip:
                            opens the best-available plugin and
                            calls lux_<kind>_aivm_attestation_apply
                            with a zero-input fixture, asserts rc=0
                            and applied_out=0.

vm.go is NOT modified. Two internal hooks (gpuAvailable() and
gpuTransitionApply(...)) are exported under both build tags so
Build/Verify/Accept can opt into the GPU transition when the wiring
on the consumer side is ready.

Test output (M1 Max)
====================

* CGO_ENABLED=0 go build ./aivm/...                 → clean
* CGO_ENABLED=1 go build -tags cgo ./aivm/...       → clean
* CGO_ENABLED=0 go test ./aivm/                     → ok
* CGO_ENABLED=1 LUX_PRIVATE_GPU_KERNELS_DIR=...
  go test -tags cgo ./aivm/                          → ok
    TestLayoutSizes                  PASS
    TestRoundTripAttestation         PASS
       aivm: using plugin metal at
       …/build/metal-only/backends/metal/libluxgpu_backend_metal.dylib
    TestRoundTripProofVerifyZeroOps  PASS
    TestNoPluginFallback             PASS
    TestModeAPI                      PASS
2026-06-05 14:50:13 -07:00
zeekay 3e7decd934 ci: pin runner-amd64/arm64/deploy to luxfi pool labels
Was using canonical workflow defaults (hanzoai-scoped labels) which
do not dispatch for luxfi org. Switched to round-robin pool labels:
  runner-amd64: luxfi-amd64  (evo)
  runner-arm64: luxfi-arm64  (spark + dbc, round-robin)
  runner-deploy: lux-deploy-linux-amd64  (DO ARC pool)
2026-06-01 17:41:36 -07:00
zeekay c254e9dab2 merge: feat/bridgevm-canonical 2026-06-01 16:33:20 -07:00
zooqueenandHanzo Dev 9ec2bc65b7 Add Claude Code project docs (CLAUDE.md, LLM.md)
Co-authored-by: Hanzo Dev <[email protected]>
2026-05-31 21:59:12 -07:00
zeekayandGitHub 90f70307c3 bridgevm: close daemon-discovery RPC gap (getInfo, getSupportedChains, getChainConfig, getSignature) (#5)
The luxfi/bridge daemon's bchain client (internal/bchain.Client) calls
bridge_getInfo / bridge_getSupportedChains / bridge_getChainConfig /
bridge_getSignature against the B-Chain RPC for permissionless discovery
+ MPC signature retrieval. Until now BridgeVM only implemented the
settlement subset (estimateFee, submitRequest, getStatus, cancelRequest,
health, getMPCPublicKey) — daemons fell back to assumed local values
for the discovery surface, a centralization vector.

This commit:
- Adds GetBridgeInfo, GetSupportedChains, GetChainConfig, GetSignature
  to bridgevm.Service.
- Wires all four into the JSON-RPC dispatcher (bridge_* and bridge.*
  aliases).
- GetSignature reads from the swap-store record (populated by the MPC
  signing pipeline once the threshold quorum aggregates shares).
  Distinguishes "no such swap" from "still signing" via separate errors
  so callers can poll without dispatching on a generic error code.
- GetChainConfig matches the ChainID case-insensitively and surfaces
  the requested id in the error message when the chain is not in
  SupportedChains.
- Adds 6 table-driven tests covering happy paths, not-found, empty
  params, and the not-yet-available signature poll.

After this lands the luxfi/bridge daemon stops needing any cached
fallback for these four endpoints — the B-Chain VM is authoritative
end-to-end. Daemon code itself needs no change; its bchain.Client
already calls these method names.

Tests: go test ./bridgevm/... — 36/36 pass (30 pre-existing + 6 new).
2026-05-30 20:06:31 -07:00
zeekay 56edda4b45 bridgevm: close daemon-discovery RPC gap (getInfo, getSupportedChains, getChainConfig, getSignature)
The luxfi/bridge daemon's bchain client (internal/bchain.Client) calls
bridge_getInfo / bridge_getSupportedChains / bridge_getChainConfig /
bridge_getSignature against the B-Chain RPC for permissionless discovery
+ MPC signature retrieval. Until now BridgeVM only implemented the
settlement subset (estimateFee, submitRequest, getStatus, cancelRequest,
health, getMPCPublicKey) — daemons fell back to assumed local values
for the discovery surface, a centralization vector.

This commit:
- Adds GetBridgeInfo, GetSupportedChains, GetChainConfig, GetSignature
  to bridgevm.Service.
- Wires all four into the JSON-RPC dispatcher (bridge_* and bridge.*
  aliases).
- GetSignature reads from the swap-store record (populated by the MPC
  signing pipeline once the threshold quorum aggregates shares).
  Distinguishes "no such swap" from "still signing" via separate errors
  so callers can poll without dispatching on a generic error code.
- GetChainConfig matches the ChainID case-insensitively and surfaces
  the requested id in the error message when the chain is not in
  SupportedChains.
- Adds 6 table-driven tests covering happy paths, not-found, empty
  params, and the not-yet-available signature poll.

After this lands the luxfi/bridge daemon stops needing any cached
fallback for these four endpoints — the B-Chain VM is authoritative
end-to-end. Daemon code itself needs no change; its bchain.Client
already calls these method names.

Tests: go test ./bridgevm/... — 36/36 pass (30 pre-existing + 6 new).
2026-05-30 20:05:33 -07:00
zeekayandGitHub be243c56d7 bridgevm: promote quote engine + swap store from cmd/bridge daemon (#3)
The bridge is permissionless and non-custodial. Authoritative quote
math and swap state must live where the validator quorum runs
consensus — in this VM — not in any single daemon's local cache.
This change moves both into bridgevm and exposes them via JSON-RPC
so any client can reach the same settlement decisions.

New RPC methods:
  bridge_estimateFee     — authoritative quote computation
  bridge_submitRequest   — create + quote-snapshot
  bridge_getStatus       — read swap by id
  bridge_cancelRequest   — idempotent cancel
  bridge_health          — liveness probe
  bridge_getMPCPublicKey — threshold group public key

Architecture:
  - QuoteEngine     (quote.go)         StaticPriceFeed → quorum oracle later
  - SwapStore       (swap_store.go)    in-memory genesis impl; block-persistence next
  - Service methods (rpc.go)           JSON-RPC dispatch (snake + dot aliases)

Attestation aggregation already lived in bridge_signing.go via
BridgeSigner + BridgeMessageValidator — no changes needed there.

LP-333 signer-set methods unchanged.
v1.2.7
2026-05-28 09:05:11 -07:00
zeekay 5ad64a64bf multichain: remove from public chains — moved to lux-private
The cross-chain GPU-resident block builder is proprietary. The package
has been relocated to lux-private/multichain. Public chains repo keeps
only the per-chain VM implementations (evm, dexvm, fhevm, etc.) — those
stay OSS and are what external operators interact with.

What's still public here:
  evm/cevm                 GPU EVM block dispatch (V4 ABI)
  dexvm                    Lux DEX VM (CLOB + AMM)
  bridgevm, thresholdvm,
  zkvm, quantumvm, ...     other per-chain VMs

What moved private:
  multichain               Cross-chain atomic block builder
                           (the in-memory GPU multi-chain coordinator
                           that runs C+D+F transitions in one block)

Public consumers that need cross-chain orchestration can still use the
per-chain Execute APIs directly. The atomic multi-chain coordinator is
the closed-source piece.
2026-05-25 14:52:40 -07:00
zeekay 67bf615f51 multichain: cross-chain atomic block builder (C + D + F)
New package github.com/luxfi/chains/multichain that runs C-Chain (EVM),
D-Chain (DEX), F-Chain (FHE) transitions atomically in one block. A tx
that calls a cross-chain precompile no longer bounces CPU→GPU→CPU→GPU
for each chain boundary — the Coordinator orchestrates the per-chain
kernels via a fixed-point loop until every declared CrossRef resolves,
then seals all three sub-blocks together.

API:
  CrossChainBatch { CChainTxs, DChainOps, FChainOps, CrossRefs }
  MultiChainBlock { CChainBlock, DChainBlock, FChainBlock, Receipts, StateRoots }
  ChainKernel.Execute(in) → (out, err)
  ChainKernel.Seal() → (subBlock, stateRoot, err)
  Coordinator.ExecuteBlock(batch) → (*MultiChainBlock, err)

Atomicity: any kernel error or unresolved CrossRef rejects the entire
block — no partial commit. CrossRefs in the input batch are ASSERTIONS
(post-conditions) verified at seal time; they are NOT pre-dispatched
queues. The kernel is the single source of truth for cross-chain calls.

Phase 1 (now): host coordinates sequential per-chain dispatch with
goroutine parallelism between independent chain kernels each round.

Phase 2 (luxcpp shared-MvMemory, future): the same BlockBuilder API is
satisfied by a single GPU kernel that runs all three chains over shared
device memory. Callers don't change — only the underlying dispatch.

Tests: 4 subtests cover standalone chains, cross-chain dispatch with
cref resolution, unresolved-cref rejection, and missing-kernel detection.
All pass.
2026-05-25 10:25:11 -07:00
zeekay 189be5b417 cevm: Go V1/V2/V3 are thin adapters over ExecuteBlock — one cgo path
Collapses the Go-side cgo entry points to a single canonical path:

  ExecuteBlock(backend, threads, txs, ctx, state)
    └─> C.gpu_execute_block_v4(...)

  ExecuteBlockV1(backend, txs)              -> ExecuteBlock + downcast
  ExecuteBlockV2(backend, threads, txs)     -> ExecuteBlock(nil, nil)
  ExecuteBlockV3(backend, threads, txs, ctx) -> ExecuteBlock(ctx, nil)
  ExecuteBlockV4 = ExecuteBlock (rename)

No more parallel C cgo calls. The luxcpp-side gpu_execute_block / _v2 / _v3
entries are now dead and can be removed in the next luxcpp release.

Health probe: the `callBridge` exception now applies on every backend
instead of GPU-only. The old V2 path masked kernel status with TxOK; the
canonical path surfaces the real CallNotSupported. Until the V5 kernel
implements CALL/CREATE on device, the probe accepts any clean return as
"dispatcher reached the bridge" — truth, not a mask.
2026-05-25 09:44:49 -07:00
zeekay ee2027bc1b cevm: ExecuteBlock is the canonical entry — one way only
Per "kill this version proliferation and have one and one way only":

- ExecuteBlock(backend, threads, txs, ctx, state) is the single canonical
  Go-side entry. Takes everything, returns everything.
- ExecuteBlockV1/V2/V3/V4 are marked Deprecated and retained as test-file
  compatibility shims pointing at the same underlying C ABI. New code MUST
  use ExecuteBlock.
- chains/evm/cevm/parallel/parallel.go switched to ExecuteBlock. parallel
  test suite still green.

The C-side ABI sprawl (gpu_execute_block / _v2 / _v3 / _v4) stays for now —
deleting them is a luxcpp/cevm refactor that ripples through internal
dispatch. The Go surface that consumers see is single-entry today; the C
cleanup is the next bounded follow-up in luxcpp.

CALL/CREATE on device — the "100% GPU EVM" gap — remains kernel-side work
in luxcpp/cevm/lib/evm/gpu/kernel/. The host-side scaffold (call_frame.hpp,
code_resolver.cpp, evmc_bridge.cpp, the GpuHostBridge type) is real but
the kernel CALL handler still emits TxCallNotSupported. That's the next
multi-week kernel push, not a Go-side change.
2026-05-24 23:01:11 -07:00
zeekay 7e368ae253 cevm: drop LUX_ prefix from env var — CEVM_STRICT
Per "no LUX_ in front of shit for no reason" — the strict-mode knob is
cevm-specific, not Lux-specific.

  LUX_CEVM_STRICT → CEVM_STRICT

Default unchanged (strict=on). Docs updated.
2026-05-24 18:51:42 -07:00
zeekay ca79578b5b cevm: TESTING_CUDA.md — cross-repo CUDA box validation checklist 2026-05-24 14:20:57 -07:00
zeekay 075be66a3c cevm/parallel: strict GPU EVM by default — kill silent Go EVM fallback
Removes the silent (nil, nil) "fall through to Go EVM" return at the three
points where cevm V4 cannot complete a block on device:

  - tx value exceeds uint64
  - kernel returns TxCallNotSupported (CALL/CREATE family)
  - block has logs (V4 ABI has no per-tx logs)

Replaces each with declineBlock(reason, block, tx_index):

  * Default (LUX_CEVM_STRICT=1): returns ErrGPUEVMRequired so the caller
    cannot silently shadow-execute on the Go EVM. The lie that hid the
    missing GPU CALL/CREATE is removed.
  * Legacy (LUX_CEVM_STRICT=0): returns (nil, nil) for V4→V5 transition
    rollback only.

Every fallback records backend.RecordFallback(FallbackUnsupported, "cevm:<reason>")
so production observability surfaces the rate at which blocks decline.

V5 kernel spec lands at evm/cevm/V5_ABI.md: gpu_execute_block_v5 with
code-table, storage_root threading, per-tx logs. Strict mode becomes
unconditional once V5 ships and the env var retires.
2026-05-24 14:18:44 -07:00
zeekay d25756da35 aivm: public-BFT defaults + multi-chain deployable + VerificationMode
The user's verbatim demand:
> "fix ALL of a-chain so it works in MULTI-CHAIN for any Lux public L1 L2
> we must work without any trusted daler or other"

WHAT CHANGED

DefaultConfig (PUBLIC-BFT-SAFE DEFAULTS):
- VerificationMode: ModeOptimistic (default) — providers post results
  with bond; N-block challenge period; uncontested = finalised;
  challenged = fraud-proof flow with slashing. NO trusted dealer,
  NO TEE assumption, NO single point of trust.
- RequireTEEAttestation: false (was true) — TEE is OPTIONAL
  acceleration, NOT a registration gate. Providers without TEE can
  register and operate under the optimistic-verification flow.
- HostChainID: "primary" — AIVM is chain-agnostic. Override per
  L1/L2 instance (Hanzo, Zoo, Pars, Liquidity, etc.).
- ChallengeWindowBlocks: 100 (~5-10 min finality)
- RedundancyFactor: 3 (for ModeMultiPartyRedundant — M-of-N consensus)
- MinProviderBond: 1000 LUX equivalent (slashed on fraud proof or
  majority divergence)

DefaultPermissionedConfig (OPT-IN, NOT public mainnet):
- VerificationMode: ModeTEEAttested
- RequireTEEAttestation: true
- For regulated/KYC'd subnets where TEE-vendor trust is acceptable
  by policy

THREE VERIFICATION MODES
1. ModeOptimistic (default, public-BFT): post + challenge + fraud proof.
2. ModeMultiPartyRedundant: M-of-N validators run same task, consensus
   on output hash. Public-BFT-safe. M× compute cost.
3. ModeTEEAttested: opt-in, permissioned subnets only. TEE is folded
   into the trust score as ACCELERATION (skip challenge for high
   trust score); NEVER changes the trust root.

RegisterProvider:
- Public-chain path: no TEE required. Provider bond + challenge flow
  enforce correctness.
- Permissioned path (RequireTEEAttestation=true): TEE attestation
  required, must meet MinTrustScore. Error message points operators
  at the public-chain alternative.

MULTI-CHAIN DEPLOYABILITY
- HostChainID tells AIVM which L1/L2 it's running on.
- "primary" = anchor to Q-Chain via MerkleAnchorFreq blocks.
- White-label L1/L2 = anchor to host chain's own finality (Pulsar
  for PQ-finality, Corona for Ringtail-finality, etc.).
- AIVM code is identical across all chains; only the HostChainID
  config field differs.

TESTS
- TestDefaultConfig pins public-BFT-safe defaults: TEE NOT required,
  mode is Optimistic, HostChainID is "primary".
- TestDefaultPermissionedConfig pins the opt-in permissioned path.
- TestVerificationMode_PublicBFTSafe asserts default mode is always
  one of (Optimistic, MultiPartyRedundant), NEVER TEE-attested as
  the trust root.

go.mod refresh as side-effect of adding luxfi/node@latest for
vms/types/fee.
v1.2.6
2026-05-22 00:26:04 -07:00
zeekay 9cb50fa801 graphvm + oraclevm + relayvm: complete FeePolicy coverage
graphvm: G-Chain is read-only (graphql.go explicitly rejects `mutation`
operations). Wires NoUserTxPolicy{} so any attempted user-tx is refused
at the boundary. Field + Initialize gate added; fee.Validate ensures
the policy choice is sound at boot.

oraclevm + relayvm: these chains are thin re-export shims of the
canonical impls in luxfi/oracle/vm and luxfi/relay/vm (which already
have feegate.go). Added in-file pointers documenting where the gate
lives, so future readers don't add a duplicate stub here.

Closes the FeePolicy migration: every VM in luxfi/chains/ either has
its own feegate.go (8 VMs), points to the canonical impl (oraclevm +
relayvm), or is exempt via native gas (evm). The matrix at
node/CLAUDE.md FeePolicy section is now complete.
2026-05-21 17:33:55 -07:00
zeekay 42b3fe391c chains/evm/cevm: switch to pkg-config: lux-cevm + lux-crypto-secp256k1
Replace the hand-rolled ${SRCDIR}/../../../../luxcpp/... CFLAGS+LDFLAGS
blocks in cevm_cgo.go and cevm_secp256k1.go with the canonical .pc
bundles. External Go consumers building from \$GOMODCACHE no longer
need a luxcpp checkout next to lux/; they only need the install prefix
on \$PKG_CONFIG_PATH.

cevm_cgo.go consumes lux-cevm (libevm + libevm-gpu + transitive
GPU-host static archives).

cevm_secp256k1.go consumes lux-crypto-secp256k1 (libsecp256k1_cpu +
libkeccak_cpu). libsecp256k1_metal stays on the build-tree path with
the existing darwin-only anchor file until a separate .pc bundle for
the Metal driver lands.
2026-05-21 17:16:12 -07:00
zeekay ad18c51aae thresholdvm: declare NoUserTxPolicy sentinel (service-only chain)
M-Chain is committee-driven — keygen and signing requests come from
validators via consensus, not a user mempool. Attach the
fee.NoUserTxPolicy sentinel in Initialize so the boot-time
fee.Validate explicitly approves the no-user-tx posture and any
caller that reaches the gate gets ErrChainAcceptsNoUserTxs.
2026-05-21 17:15:37 -07:00
zeekay ce167cbdbb identityvm: update existing RPC tests to pay the MinTxFeeFloor
The 4 mutating-RPC tests (CreateIdentity, RegisterIssuer,
IssueCredential, RevokeCredential) were asserting zero-fee acceptance
— that was the bug. Add "fee": 1000000 to each test JSON so the
contract matches the new gate.
2026-05-21 17:14:10 -07:00
zeekay bfdd8808f8 identityvm: gate user RPCs on FeePolicy (MinTxFee floor)
I-Chain's mutating RPCs (CreateIdentity, IssueCredential,
RevokeCredential, CreateProof, RegisterIssuer) are user-tx
admission points. Add a Fee uint64 field to each mutating Args
struct and gate via FlatPolicy at MinTxFeeFloor. Read-only RPCs
(GetIdentity, GetCredential, VerifyCredential, GetIssuer,
ListIssuers, ResolveIdentity, Health) are unchanged.
2026-05-21 17:13:17 -07:00
zeekay cbfea4cce8 quantumvm: gate user tx on FeePolicy (MinTxFee floor)
Add Fee() to the Transaction interface and introduce VM.IssueTx as
the canonical user-tx admission point. The FeePolicy gate refuses
zero-fee tx before they reach the parallel quantum verification
pool. Consensus-internal callers bypass via txPool.AddTransaction.
2026-05-21 17:09:16 -07:00
zeekay 5f802d44ac bridgevm: gate user tx on FeePolicy (MinTxFee floor)
InitiateBridgeTransfer is the canonical user-tx admission point on
B-Chain — it drives MPC signing capacity. Add a Fee uint64 field to
BridgeMessage and attach a FlatPolicy at MinTxFeeFloor in
Initialize. The fee gate refuses zero-fee transfers before any MPC
signing capacity is consumed. Consensus-internal callers bypass
via pendingBridges / bridgeSigner direct access.
2026-05-21 17:07:06 -07:00
zeekay a7d1ca10d4 keyvm: gate user RPCs on FeePolicy (MinTxFee floor)
K-Chain's mutating service RPCs (CreateKey, DeleteKey, Encrypt) are
the user-tx admission points. Attach a FlatPolicy at MinTxFeeFloor
in Initialize and add a Fee uint64 field to each mutating Args
struct. The fee gate runs before any key material is allocated or
MPC capacity consumed. Read-only RPCs (ListKeys, GetKey*) are
unchanged — they consume no chain state.
2026-05-21 17:02:02 -07:00
zeekay a65e5590a3 aivm: gate user tasks on FeePolicy (MinTxFee floor)
SubmitTask is the canonical user-task admission point on A-Chain — the
HTTP /tasks handler routes through here. Attach a FlatPolicy at
MinTxFeeFloor (1 mLUX) in Initialize and refuse zero-fee tasks before
they enqueue. Fee gate runs after the initialized check so the
existing ErrNotInitialized contract for SubmitTask(nil) on a
shut-down VM is preserved.
2026-05-21 16:57:15 -07:00
zeekay 6ff4b427b8 zkvm: gate user tx on FeePolicy (MinTxFee floor)
The /sendTransaction HTTP entry is the user-mempool admission point on
Z-Chain — it decodes a shielded Transaction and inserts into the
priority-heap mempool. Attach a FlatPolicy at MinTxFeeFloor (1 mLUX)
in Initialize and refuse zero-fee txs at the handler before mempool
pressure. Consensus replay paths bypass the gate.
2026-05-21 16:50:05 -07:00
zeekay e0b1d03853 dexvm: gate user tx on FeePolicy (MinTxFee floor)
SubmitTx is the canonical user-mempool entry on D-Chain — every public
submission funnels through here. Attach a FlatPolicy at MinTxFeeFloor
(1 mLUX) in Initialize and gate SubmitTx through ValidateFee so
zero-fee user txs are refused before they touch pendingTxs. Internal
consensus-engine -> VM paths bypass the gate.
2026-05-21 16:47:55 -07:00
zeekay 8364b506d9 deps: bump evm v0.18.13 + precompile v0.5.23 + threshold v1.8.0; drop sibling replaces
The local replace block (luxfi/{evm,precompile,threshold} => ../*) was
transient pending tags that include LP-4200 precompile registry + corona
keyera-lifecycle. All three lines now have shipped tags:
  - luxfi/evm v0.18.13
  - luxfi/precompile v0.5.23
  - luxfi/threshold v1.8.0

Local replaces removed → repo builds cleanly in any isolated context
(Docker, fresh GOPATH, etc.).

Verified locally with GOWORK=off go build ./cmd/plugin per chain:
  aivm/bridgevm/dexvm/graphvm/identityvm/keyvm/oraclevm/relayvm/
  thresholdvm/zkvm → OK
  quantumvm → FAIL (Corona→Ringtail source migration deferred —
  references quasar.CoronaSignature/qcore.CoronaRound1 that
  threshold v1.8.0 renamed).
v1.2.5
2026-05-19 13:36:09 -07:00
zeekay 61248e2288 remove detailed patent-claims docs (relocated to lux-private/patents)
Detailed invention disclosures are sensitive pre-filing material. Moved to
lux-private/patents to preserve international filing rights (EU/JP/KR/CN
absolute-novelty rule). Cross-ref: github.com/lux-private/patents/bundles/
2026-05-19 11:30:50 -07:00
zeekay c5cbdf77ac patent-claims: novelty triage drafts (attorney-prep, not filed) 2026-05-19 10:51:05 -07:00
zeekay 3dde269d9b thresholdvm: remove TestCoronaSessionInit (legacy StartFunc pattern; corona moved to keyera-lifecycle in threshold v1.7.0) v1.2.4 2026-05-19 00:35:50 -07:00
zeekay ede84f7390 rename: github.com/luxfi/protocol → github.com/luxfi/proto (cascade complete) 2026-05-18 21:28:57 -07:00
zeekay a41dd99c64 deps: pin luxfi/proto v1.0.0 (rename cascade complete) 2026-05-18 21:27:16 -07:00
zeekay be92802b0f rename: github.com/luxfi/protocol → github.com/luxfi/proto (imports + go.mod replace) 2026-05-18 21:19:09 -07:00
zeekay a8cf0793c6 Merge branch 'main' of github.com:luxfi/chains v1.2.3 2026-05-18 20:48:55 -07:00
zeekayandGitHub 7c904bfa10 chore: add LICENSE (BSD 3-Clause License) + LICENSING.md pointer (#2)
* chore: add BSD 3-Clause License

* docs: add LICENSING.md pointer to canonical IP/licensing strategy
v1.2.2
2026-05-16 10:48:48 -07:00
zeekay f4c7055d45 chains: complete Ringtail → Corona purge across thresholdvm + quantumvm + dexvm
Continuation of dc31d5b (quantumvm consumer-side leak after consensus
repo migration) — the rename was incomplete; this pass closes it.

Identifier renames in chains/{quantumvm,thresholdvm,dexvm}:
  - NTTForwardRingtail / NTTInverseRingtail / BatchNTTForwardRingtail
        → NTTForward/Inverse/BatchNTTForwardCorona (Quasar GPU dispatch)
  - LaneRingtail (CertLane enum)
        → LaneCorona
  - ProtocolRingtail (Protocol enum)
        → ProtocolCorona (string value already "corona")
  - All Ringtail-prefixed local identifiers in quantumvm/{quasar,
    quasar_witness,block,vm,vm_test,signer,stamper,service}.go,
    thresholdvm/{client,protocols,rpc,types/{ceremony,share},
    runtime/m_chain_adapter,cert/lane_test,protocol_executor_test}.go,
    dexvm/factory.go

Directory + file rename:
  thresholdvm/protocol/ringtail_general/ringtail.go
        → thresholdvm/protocol/corona_general/corona.go
  package ringtail_general → package corona_general

evm/main.go: replace single `precompile/ringtail` blank-import with
the canonical LP-4200 unified PQCrypto block (mlkem 0x012201,
mldsa 0x012202, slhdsa 0x012203, pulsar 0x012204, p3q 0x012205,
corona 0x012206) + xwing.

External test that imports threshold's renamed wrapper:
  thresholdvm/protocol_executor_test.go now imports
  "github.com/luxfi/threshold/protocols/corona" (was protocols/ringtail).
  Resolves via the workspace `./threshold` entry pointing at the
  local renamed wrapper; downstream chains/go.mod still pins
  luxfi/threshold v1.5.5 and will tidy clean once threshold cuts the
  next tag.

Build: go build ./... PASS (only harmless duplicate-rpath warnings
from the cevm cgo link).
Tests:
  thresholdvm + subpackages PASS
  quantumvm PASS
2026-05-14 09:33:22 -07:00