96 Commits
Author SHA1 Message Date
zeekay c0b3d81c0e deps: evm v1.99.29 + precompile v0.5.49 (hardened 0x9999 receipt-settlement)
Bump github.com/luxfi/evm v1.99.28 -> v1.99.29 (removes deprecated DexZap
live-backend wiring) and github.com/luxfi/precompile v0.5.47 -> v0.5.49
(complete, red-swarm-hardened 0x9999 V4 receipt-settlement surface). dexvm
remains the D-Chain matcher/receipt producer; the C-Chain settles inline.
v1.3.12
2026-06-20 15:02:05 -07:00
zeekay 1d845d7e97 merge: reconcile docs (8dde3d0) onto the v1.3.11 bridgevm BLS-scheme fix
origin/main had drifted to a docs-only commit that did not include the
bridgevm BLS threshold-scheme registration (v1.3.11, 7761e80) — without it the
v1.30.16 bridge regression recurs. Merge keeps both.
2026-06-20 15:00:52 -07:00
zooqueen edd001ce65 docs: LLM.md canonical, CLAUDE.md -> symlink (convention) 2026-06-19 21:48:55 -07:00
zeekay 8437d0eb7a fix(bridgevm): register BLS threshold scheme in the plugin process
bridgevm runs as a standalone rpcchainvm plugin; mpc.go called
threshold.GetScheme(SchemeBLS) but never imported crypto/threshold/bls,
whose init() registers it. The full node binary pulled it in via
platformvm, but the v1.30.16 plugin build didn't -> B-Chain failed VM
init ('threshold: scheme not registered'). Blank-import to self-register.
v1.3.11
2026-06-19 20:12:33 -07:00
zeekay 3f2427bbaa deps: pin geth v1.17.11 + consensus v1.25.18 + evm v1.99.28 + precompile v0.5.47 (real semver); MVS-propagate transitive bumps v1.3.10 2026-06-19 14:44:18 -07:00
zeekay c3d1847eeb Merge feature/zchain-rollup-starkfri-pq: zkvm Z-Chain rollup + starkfri PQ 2026-06-19 14:26:02 -07:00
zeekay 29b808095c chains/zkvm: wire Z-Chain strict-PQ from one config bit (Red H1 wiring + LOW)
The Z-Chain is DEFINITIVELY strict-PQ (shielded settlement on the canonical
Lux strict-PQ profile), but the switches were inert: the default ZConfig
omitted StrictPQ (->false) and RegisterZKPrecompiles had ZERO callers.

Task 1 — drive BOTH switches from the single ZConfig.StrictPQ field:
- Default ZConfig now pins StrictPQ=true + ProofSystem='stark' (the only
  system accepted under strict-PQ). A genesis with no explicit ZConfig
  yields a strict-PQ chain; a permissive deployment MUST set StrictPQ=false
  explicitly.
- VM.Initialize now calls precompiles.RegisterZKPrecompiles(reg, config.
  StrictPQ) — same bit. On strict-PQ the classical Groth16 (0x80) / PLONK
  (0x81) verifiers are NOT registered (fail-closed by absence); only
  STARK/FRI (0x82) + the fail-closed stubs exist. Added VM.ZKPrecompiles()
  / VM.StrictPQ() accessors.

LOW (Red) — TestStrictPQ_RealBN254VKLoadErrors drove a test-local mirror
(reapplyStrictPQVKGuard), not the production loadVerifyingKeys. Added a
config path (ZConfig.VerifyingKeys) to supply real keys in-memory; the test
now drives the REAL NewProofVerifier->loadVerifyingKeys and asserts the
strict-PQ real-bn254-VK guard fires there. Deleted the mirror.

Tests (a)(c): default Z-Chain is strict-PQ + registers strictPQ=true;
classical 0x80/0x81 absent, 0x82 present; a groth16 shielded proof is
REFUSED before reaching bn254; explicit StrictPQ=false flips both switches
in lockstep (profile-driven, not hardcoded); real-VK guard via the
production loader; non-strict chain still accepts a real bn254 VK.
2026-06-19 13:31:46 -07:00
zeekay f8fba1ba39 chains(zkvm): hard-disable classical shielded/ZK paths on strict-PQ (Red H1/H2/H4)
H1 — shielded-tx ProofVerifier was classical-only (groth16/plonk) and
fail-closed only via all-zero dummy VKs; real bn254 VKs would re-enable a
CRQC-forgeable shield/unshield mint/steal path. Add ZConfig.StrictPQ and a
single gate refuseClassicalUnderStrictPQ(proofType) called at the top of
VerifyTransactionProof AND per-tx in the GPU batch path (which verifies
groth16 inline, bypassing VerifyTransactionProof). Under strict-PQ only
"stark" is accepted — wired to precompile/starkfri (cSHAKE256/Goldilocks
FRI, fail-closed until the prover binds), public inputs bound to the tx's
nullifiers+commitments. loadVerifyingKeys now ERRORS on a non-dummy bn254
VK under strict-PQ (explicit fail-closed, not implicit dummy-keys). The
remaining prover work (p3q_prove C ABI + shielded/ML-DSA AIR) is tracked
as a code comment; shielded value is effectively disabled on strict-PQ
chains until it lands — the correct no-classical-fallback posture.

H2 — Groth16/PLONK precompiles (0x80/0x81) were registered unconditionally
and Run([]byte) has no AccessibleState to call RefuseUnderStrictPQ.
RegisterZKPrecompiles(registry, strictPQ) now omits Groth16/PLONK on
strict-PQ chains (registering STARK 0x82 + fail-closed Halo2/Nova stubs
only) so 0x80/0x81 fail closed by absence; non-strict chains keep them as
an optional building block (kept, not deleted). CrossChainZKVerifier gains
StrictPQ that refuses routing Groth16/PLONK while still routing STARK.

H4 — verifyPLONK computed a self-cancelling pairing, discarded the result,
ignored public inputs, and returned valid for ANY >=544-byte blob (total
bypass). Now fails closed (errPLONKVerifierIncomplete) after structural
parsing — NEVER universal-accepts.

Groth16/bn254/PLONK remain present-but-gated; STARK/FRI (P3Q) is the only
accepted proof path on strict-PQ chains.

Tests: strict-PQ refuses groth16/plonk/bulletproofs (direct + GPU-batch);
real-VK-load errors; STARK fails-closed unbound and accepts bound with
nullifier+commitment-bound public inputs; non-strict path unchanged;
strict registry omits classical + keeps STARK; cross-chain strict refuses
classical; PLONK never universal-accepts. H-02 regression updated to the
new wired-STARK fail-closed behavior.
2026-06-19 12:48:26 -07:00
zeekay cbf7dc9da6 chains/zkvm: Z-Chain rollup proof verifier switched Groth16 -> STARK/FRI (P3Q)
Make the Z-Chain MLDSA-rollup verification path post-quantum. The
rollup aggregates per-validator ML-DSA-65 sigs over the round digest;
the proof was classical Groth16/bn254 (pairing-based, quantum-breakable)
and is now a strict-PQ STARK/FRI proof (P3Q: Plonky3 fork, cSHAKE256
Merkle over Goldilocks, FRI; no KZG, no pairings, no trusted setup).

VERIFIER (the clean half, done):
- precompiles/zk_verifiers.go: STARKVerifier stub -> delegates to
  precompile/starkfri.Verify. Parses [proof_len][proof][pub_len][pub];
  proof must carry the 'P3Q1' magic. FAILS CLOSED (errVerifierUnavailable,
  never resultValid) when no FRI binding is registered (CGO_ENABLED=0 /
  no -tags starkfri_p3q) — no forgery oracle. The classical
  Groth16Verifier/PLONKVerifier are KEPT intact at their own addresses.
- precompiles/crosschain.go: route VerifierTypeSTARK to STARKVerifierAddr
  (was errNotImplemented).
- tests: STARK now proven to delegate to starkfri (accept->0x01,
  reject->0x00, bad-magic rejected before callback, unbound fails closed)
  and to route cross-chain; Groth16/PLONK tests unchanged.

PROVER (the honest remaining step, FLAGGED — NOT faked):
- zwitness.go: MLDSAGroth16 -> MLDSAStark rename; doc now states the
  proof is STARK/FRI. Body stays ErrZWitnessNotImplemented: ~/work/lux/p3q
  exposes a Rust prover but NO p3q_prove C ABI, and has NO MLDSA-rollup
  AIR. Emitting fake proof bytes on the finality path would be a forgery
  oracle, so the prover binding is left as the outstanding step.

go build ./zkvm/... + go test ./zkvm/precompiles/ green (CGO_ENABLED=0,
GOWORK=off). Real cgo-tagged starkfri binding (-tags starkfri_p3q)
compiles + KAT passes against the in-tree p3q staticlib.
2026-06-19 12:23:44 -07:00
zeekay 69d6251fa4 dexvm: bind import credit to consumed-UTXO asset/owner + custody hardening
executeImport reads the consumed UTXO owner|asset|amount from shared memory and binds the credit to it (rejects declared!=actual; native-aliasing closed); two-pass validate-then-consume so a rejected import mutates nothing. Withdraw-rail consume-once on fillRef.
2026-06-19 11:34:41 -07:00
zeekay 8f733194b3 chains/dexvm: atomic custody rail (custody.go) — deposit=import+credit, withdraw=debit+export
executeDeposit = executeImport (atomic C/X debit, consume-once) + clob_deposit relay (credit
D-Chain balance; refuses credited!=imported). executeWithdraw = clob_withdraw (debit, realized
clamped) + executeExport (credit exactly realized; refuses realized>want). Reuses the
conservation-tested ImportTx/ExportTx rail. custody_conservation_test: real atomic.SharedMemory,
deposit→trade→withdraw conserves C in==out, UTXO consumed once. NOTE: not yet wired into the
carried-fills BuildBlock plan (network-upgrade-gated follow-up, like #9).
v1.3.9
2026-06-17 21:10:33 -07:00
zeekay 9f96a5cae4 Merge dexvm-atomic-proxy: stateless atomic ZAP proxy + #9 carried-fills consensus fix v1.3.8 2026-06-17 17:12:55 -07:00
zeekay 562bee534a chains/dexvm: #9 consensus-fork fix — proposer-relays-once + carry-fills-in-block
Decomplect obtain-fills (proposer, BuildBlock, once network-wide) from settle-from-carried-
fills (deterministic, Accept). No validator relays at Verify/Accept -> block output is a pure
fn of (height, carried ts, tx bytes, carried fills) -> byte-identical StateRoot. NEW
carried_fills.go wire section (block + vertex) with a RESERVED fill-signature field for the
future trustless path (no 2nd wire bump). #7 computeStateRoot completed (commits state+atomic).
TestRED_PerValidatorRelay_SplitsConsensus PASS (0 cross-validator relay); redteam 21/0 (37/0);
conservation/determinism green; race-clean. NETWORK-UPGRADE-GATED wire-format change.
2026-06-17 17:12:55 -07:00
zeekay 4e21d9910a chains/dexvm: rip out matcher+state -> stateless atomic ZAP proxy
orderbook/perpetuals/lending/mev dirs + backend.go deleted; vm.go 2230->830 lines.
NEW atomic.go (shared-memory import/export at Block.Accept) + relay.go (rpc.ZAPDial,
frame byte-identical to zapwire, no luxfi/dex dep). State holds only nonce:/receipt:/
consumed: -- no order/pool/position keys. txs reduced to import/export/relay. NEW
conservation_test.go::TestEndToEndAtomicValueConservation. Verified -tags dchain build+tests
green -race; grep matchAllOrders|tryMatch|crossOrders empty.
2026-06-17 13:31:58 -07:00
zeekay a6e013831d deps: update to latest real-semver, drop local replaces, fix breaks 2026-06-11 09:09:40 -07:00
zeekay 563a3fd454 scrub Liquidity branding + corona→corona (OSS brand hygiene) 2026-06-10 23:44:07 -07:00
zeekay 4d40a8ba45 ci: route to canonical native arcd labels [self-hosted, linux, <arch>]
Replaces non-canonical scale-set / org-prefixed labels with the
existing labels every arcd host registers with. Matches evo for
amd64 and spark for arm64. No new labels added.
2026-06-10 20:18:09 -07:00
zeekay b83c8a7558 go.mod: bump go directive 1.26.3 → 1.26.4
Patch fix: crypto/x509, mime, net/textproto security fixes per Go 1.26.4 release notes (2026-06-02). Also compiler, runtime, go fix, crypto/fips140 bug fixes.
2026-06-06 21:51:01 -07:00
zeekay 376c40f2e6 deps: bump luxfi/vm v1.2.0, sampler v1.1.0, staking v1.5.0 (relicense)
Picks up the 2026-06-06 relicensing:
- luxfi/vm v1.2.0 → Lux Ecosystem License v1.2 (was Lux Research v1.0).
  License-only retag of the extracted runtime; patent reservation
  preserved for runtime optimization surfaces, royalty-free for
  Descending Chains.
- luxfi/sampler v1.1.0 → BSD-3-Clause (was Lux Research v1.0).
  License restored to match the luxfi/node provenance (originally
  extracted from node/utils/sampler).
- luxfi/staking v1.5.0 → BSD-3-Clause (was Lux Research v1.0).
  License restored to match the luxfi/node provenance.

No code changes in this commit — go.mod/go.sum only.
2026-06-06 19:02:25 -07:00
zeekay 4a9b1b3456 chains: migrate bridgevm/zkvm/thresholdvm to node/vms/pcodecs
Wave 2D codec-rip extension for chains repo:
- bridgevm/codec.go: codec.Manager + linearcodec.NewDefault → pcodecs
- zkvm/codec.go: same pattern
- thresholdvm/codec.go: same pattern
- Bump luxfi/warp v1.18.6 → v1.19.3 (closes warp→ids→codec/wrappers transitive)
- Bump luxfi/ids v1.2.14 → v1.2.15 (drops codec/wrappers from Prefix/Append)

luxfi/codec remains as // indirect via proto/zap_codec → codec/zapcodec
(the actual ZAP wire impl — physical relocation to luxfi/zap/codec
queued separately). Tests pass for all three VMs.
2026-06-06 15:40:20 -07:00
zeekay 4ecaecedb7 deps: bump p2p v1.21.1, node v1.29.3, vm v1.1.11, evm v0.19.4 (Wave 2G-Cascade) 2026-06-06 06:30:20 -07:00
zeekay b8a2a5c4dc 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.
2026-06-05 15:46:00 -07:00
zeekay 083543f918 Merge feature/thresholdvm-cgo-bridge: thresholdvm GPU plugin bridge 2026-06-05 15:33:48 -07:00
zeekay 54f8f22150 Merge feature/quantumvm-cgo-bridge: quantumvm GPU plugin bridge 2026-06-05 15:33:48 -07:00
zeekay 7670c90853 Merge feature/dexvm-cgo-bridge: dexvm GPU plugin bridge 2026-06-05 15:33:48 -07:00
zeekay 32b6b57302 Merge feature/bridgevm-cgo-bridge: bridgevm GPU plugin bridge 2026-06-05 15:33:48 -07:00
zeekay 6728f2048c Merge feature/aivm-cgo-bridge: aivm GPU plugin bridge 2026-06-05 15:33:48 -07:00
zeekay e92bf8fd7d thresholdvm: drop LUX_THRESHOLDVM_GPU_BACKEND env knob — auto-probe only 2026-06-05 15:22:05 -07:00
zeekay 7c31eb595d 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 fc0a2410db 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 c1ef83cf34 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 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
zeekay 6ea1aab95d 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 4dd244e903 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 7f99a01ba2 merge: feat/bridgevm-canonical 2026-06-01 16:33:20 -07:00
zooqueenandHanzo Dev fdd9959f4f 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 f345620ee9 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 d37d07d8bd 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 c4ba2592ac 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.
2026-05-28 09:05:11 -07:00
zeekay 040b2bbd46 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 725a291299 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 d52e9ca2fb 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 63862e904a 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 223b307569 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 d084e4a839 cevm: TESTING_CUDA.md — cross-repo CUDA box validation checklist 2026-05-24 14:20:57 -07:00
zeekay 6d91317d83 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 45d0f5222f 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 Corona-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.
2026-05-22 00:26:04 -07:00
zeekay c334df09cd 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 3e229caa8c 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 e079072877 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