The comment read "ExecuteBlock is the legacy name for ExecuteBlock ... Deprecated:
use ExecuteBlock" — a rename rewrote both the old and new name to the same string,
leaving the only ExecuteBlock marked deprecated in favour of itself.
Co-authored-by: Hanzo Dev <[email protected]>
deps: gpu v1.1.2 — the older tags name the wrong pkg-config package
gpu v1.0.1/v1.1.0 declare `#cgo pkg-config: lux-gpu` while including
<lux/gpu.h>. Those are two different libraries with confusingly similar names:
luxgpu.pc unified GPU acceleration, -lluxgpu, Cflags -I${includedir}
lux-gpu.pc the DEX order matcher, -llux_gpu, Cflags -I${includedir}/lux
Under lux-gpu the include resolves to .../include/lux/lux/gpu.h, so every cgo
build failed with "fatal error: lux/gpu.h file not found" — the arm64 stall
signature. libluxgpu.dylib is also what actually exports _lux_gpu_ecrecover_batch.
gpu v1.1.2 already declares luxgpu; only the pin was stale.
With that fixed the link got one step further and hit a duplicate symbol:
cevm and dex/pkg/lx both define a global lux_secp256k1_metal_anchor, so any
binary linking both refuses. The anchor exists only to keep the Metal driver
alive through linker dead-code elimination — luxcpp resolves the DRIVER symbol
(secp256k1_ecrecover_address_batch_metal) via dlsym, never the anchor, so the
anchor name is internal and safe to qualify. Named lux_cevm_secp256k1_metal_anchor
after the package that owns it.
Co-authored-by: Hanzo Dev <[email protected]>
The package exported ExecuteBlockV1, V2, V3, V4 and ExecuteBlock for a single
operation, plus BlockResult and BlockResultV2 for a single result. V2/V3/V4
were pure argument adapters over the same implementation and V1 additionally
downcast the result into a lossy struct, so the versions described how the API
had grown rather than anything a caller needs to choose between.
Now: ExecuteBlock(backend, numThreads, txs, ctx, state) -> *BlockResult.
Callers without a block context or state snapshot pass nil, which is what the
adapters did on their behalf. BlockResult carries the full shape; the lossy
variant is gone. Nothing outside the package used the versioned names.
The duplicate tests went with them — TestExecuteBlockEmpty existed three times
and the backend smoke test twice, one per version, all exercising the same
function. Merged, keeping every distinct assertion.
go vet clean; ./evm/cevm and ./evm/cevm/parallel both pass.
Co-authored-by: Hanzo Dev <[email protected]>
Executes 250 blocks on the Metal backend. Before the luxcpp/cevm fix that
built the device, queue and pipelines once, this exhausted Metal and faulted
inside the driver; the crash needed volume, so no single-execution test caught
it. Runs in about a second.
Co-authored-by: Hanzo Dev <[email protected]>
The Go bindings called gpu_execute_block_v4 / gpu_free_result_v2, which
luxcpp/cevm main does not export — it renamed those to gpu_execute_block /
gpu_free_result. A luxd built CGO_ENABLED=1 against the shipped libs would have
failed to link, not merely mismatched a version. It stayed hidden because
production builds pure-Go and this box had stale branch-built libs installed.
cevm_v4compat.h and cevm_abi_v4compat_cgo.go existed only to bridge that gap —
113 lines whose own comment described the header and library being out of step.
Deleted; cgo already includes the library header directly.
ABIVersion is now taken from that header (C.EVM_GPU_ABI_VERSION) instead of a
hand-maintained Go constant that had drifted to 7 while the header said 6. One
definition, so the two cannot disagree; a runtime panic no longer has to catch
what the compiler can.
go vet clean; ./evm/cevm and ./evm/cevm/parallel both pass.
Co-authored-by: Hanzo Dev <[email protected]>
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.
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.
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.
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.
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.
quasar/* shipped a forgeable Verkle stub at 0x0300..0020 plus classical
BLS/Hybrid at 0x0300..0021-25 — pre-LP-4200 cruft now deleted at
github.com/luxfi/precompile. The canonical PQ verifiers live in the
LP-4200 0x012200 block.
VM consolidation (one module, one place only):
- Removed per-VM go.mod/go.sum/VERSION from {aivm,bridgevm,dexvm,evm,
graphvm,identityvm,keyvm,oraclevm,quantumvm,relayvm,thresholdvm,zkvm}
- All VMs now compile under github.com/luxfi/chains root module
- aivm/, dexvm/, identityvm/, keyvm/, oraclevm/ factory.go + vm.go updated
for AccelHost wiring
cevm Go-side (evm/cevm/):
- cevm.go, cevm_cgo.go, cevm_nocgo.go: ExecuteBlockV4(backend, threads,
txs, ctx, state) with StateAccount snapshot
- cevm_secp256k1.go: BatchRecoverSenders Metal LDFLAGS
- cevm_secp256k1_metal_anchor_darwin.{c,go}: anchor to keep linker from
dropping libsecp256k1_metal.a
- cevm_secp256k1_nocgo.go: stub for non-cgo builds
- plugin.go, fetch-luxcpp.sh, luxcpp-SHA256SUMS, LUXCPP_VERSION:
pinned luxcpp consumption
- evm/cevm/parallel/parallel.go: BlockExecutor adapter calls
cevm.ExecuteBlockV4 with state snapshot built from txs+statedb
Quantum/ZK witness:
- quantumvm/quasar_witness.go, zkvm/zwitness.go
go.mod: removed dead `replace github.com/ethereum/go-ethereum => luxfi/geth`
directive (caused dual-path conflict after math semver bump; no remaining
ethereum/go-ethereum imports in source). go mod tidy clean.
Tests: TestBatchRecoverSenders PASS through Metal anchor (cevm package).
Real adapter wiring cevm.ExecuteBlockV3 through luxfi/evm's
BlockExecutor interface. Replaces the (nil, nil) stub in
luxfi/evm/core/parallel/backend_cevm.go with an actual block-batch
dispatch.
Why this lives in chains/evm/cevm/parallel and not luxfi/evm:
* Import direction: luxfi/evm declares the interface; cevm consumer
imports luxfi/evm to satisfy it. Parallel-evm shouldn't import cevm.
* Build gate: this file requires the cgo bridge in cevm_cgo.go to
link libcevm.a + libluxgpu. Operators opt in by importing this
package; default builds skip it.
5-stage adapter:
1. Build []cevm.Transaction from types.Transactions (sender recovery,
To+code load, Value/GasPrice uint64 conversion).
2. Build cevm.BlockContext (timestamp, number, chain id, basefee,
coinbase, prevrandao, gas limit, blob basefee).
3. Dispatch one cevm.ExecuteBlockV3 cgo call.
4. Detect TxCallNotSupported — fall through to Go EVM (return nil,nil)
rather than mix backends mid-block.
5. Reconstruct receipts. PARITY-CRITICAL: until cevm V3 ABI exposes
per-tx logs, we only enable the path for value-transfer-only
blocks (no Data, no Code at To). Otherwise fall through.
Wiring example (operator bootstrap):
import (
"github.com/luxfi/evm/core/parallel"
cevmparallel "github.com/luxfi/chains/evm/cevm/parallel"
"github.com/luxfi/chains/evm/cevm"
)
parallel.RegisterExecutor(&cevmparallel.Executor{
CevmBackend: cevm.GPUMetal,
Threads: 0,
})
Build verified: CGO_ENABLED=0 GOWORK=off go build . — clean.
Production gate (LP-108):
* Correctness test: parity vs Go EVM Block-STM, value-transfer
blocks first; non-value-transfer blocked until V3-logs ABI.
* Single canonical owner: this is the one cevm BlockExecutor.
* Reproducible bench: pending — needs an end-to-end harness that
runs both Go EVM and cevm on the same value-transfer block stream.
Open work-items (tracked):
* cevm V3 ABI per-tx logs export (consensus-blocking for non-value
blocks).
* CALL/CREATE on cevm GPU (status=5 fallback today).
* evm-parity-test 0/133 (real CPU/GPU divergence; gas accounting +
EIP-2929).
- evm: bump precompile to v0.5.12 + fhe to v1.8.0 + gpu to v0.31.1
(gpu v0.30.0 had unresolved C.mlx_* CGO symbols)
- aivm, bridgevm, quantumvm: go mod tidy
- thresholdvm, zkvm: bump genproto to v0.0.0-20260217215200-42d3e9bedb6d
to resolve ambiguous googleapis/api/annotations import
All 12 chains now build and tests pass with GOWORK=off.
Refs #248
Pre-existing drift from before/during luxgpu migration: go.sum had stale
h1 hashes for luxfi/[email protected] that no longer matched the module
proxy contents, causing 'checksum mismatch' SECURITY ERROR on every
build/test.
Refreshed sums via 'go mod download' to canonical proxy.golang.org values.
No version bumps; no source changes.
- Remove attestation blank import (no init/module registration, dead code)
- Remove aes, chacha20, ecies (secret keys in calldata are public on-chain)
- Update comments for hpke (seal only) and ring (verify only)
Each VM builds as a standalone binary that the Lux node loads via
--plugin-dir. Node no longer bakes optional VMs in-process.
VMs: evm, dexvm, aivm, bridgevm, graphvm, identityvm, keyvm,
oraclevm, quantumvm, relayvm, servicenodevm, teleportvm,
thresholdvm, zkvm.
All 13 node-dependent VMs compile and report version correctly.
EVM requires CGo (luxcpp) — builds in CI only.