Documentation
¶
Overview ¶
Package parallel — cevm BlockExecutor for github.com/luxfi/evm.
LP-108 (2026-05-04) ENSURE step: the per-tx TransactionExecutor abstraction in luxfi/evm/core/parallel was the wrong shape for cevm. cevm.ExecuteBlock is block-batched; the per-tx wrapper in luxfi/evm/core/parallel/backend_cevm.go always returned (nil, nil). This package implements luxfi/evm/core/parallel's BlockExecutor interface (whole-block) which is the natural shape for cevm dispatch.
The implementation lives WITH cevm (not in luxfi/evm) so the import direction is correct: luxfi/evm declares the interface; luxfi/chains/evm/cevm/parallel imports luxfi/evm to satisfy it.
Wiring ¶
Explicit, and it has to stay explicit:
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,
})
luxfi/evm/core/parallel holds ONE executor: RegisterExecutor is a plain assignment to a package variable, so a second call replaces the first with no complaint. luxfi/evm's own cevmShadowExecutor takes that slot from an init() when the binary is built with -tags cevm. A package that registered itself on import would therefore replace a consensus-gated applier with this one, depending only on link order — so this package has no init().
This doc used to advertise `import _ ".../cevm/parallel" // registers` as an alternative. There is no init() and never was, so that form registers nothing: a caller following it got the Go EVM and no error saying otherwise.
Execution ¶
Three orthogonal steps, so that only the middle one needs the C++ library:
shape / blockContext / buildStateSnapshot — the block, in cevm's wire form cevm.ExecuteBlock — one cgo call assemble — what comes back, as receipts
Parity contract: every receipt produced here must byte-equal the receipt produced by Go EVM Block-STM for the same input tuple.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrGPUEVMRequired = errors.New("cevm: GPU EVM cannot execute this block (V4 ABI); waiting for V5 kernel — Go EVM fallback disabled by CEVM_STRICT")
ErrGPUEVMRequired is the sentinel ExecuteBlock returns when the cevm V4 path cannot complete a block on-device and the caller must NOT silently shadow-execute it on the Go EVM. Strict mode (the default) propagates this error; legacy mode collapses it to (nil, nil) so the caller falls through.
Strict mode is the production target. The legacy fallback exists only for the V4→V5 cevm transition window; flip CEVM_STRICT=0 to re-enable it for emergency rollback. Once the V5 kernel implements CALL/CREATE on device, the strict path becomes unconditional and the env var is retired.
Functions ¶
This section is empty.
Types ¶
type Executor ¶
type Executor struct {
// CevmBackend selects the cevm execution lane:
// cevm.CPUSequential — single-threaded CPU baseline (parity reference)
// cevm.CPUParallel — Block-STM on CPU
// cevm.GPUMetal — Metal kernel dispatch (M1/M2/M3)
// cevm.GPUCUDA — CUDA kernel dispatch (NVIDIA)
CevmBackend cevm.Backend
// Threads is the worker count for parallel backends. Ignored by
// CPUSequential; defaults to 1 when zero.
Threads uint32
}
Executor is a luxfi/evm/core/parallel.BlockExecutor that dispatches every block to cevm.ExecuteBlock in one cgo call.
func (*Executor) ExecuteBlock ¶
func (e *Executor) ExecuteBlock( config *ethparams.ChainConfig, header *types.Header, txs types.Transactions, statedb *state.StateDB, vmCfg vm.Config, ) ([]*types.Receipt, error)
ExecuteBlock implements evmparallel.BlockExecutor. Dispatches the whole block in one cgo call to cevm.ExecuteBlock and reconstructs receipts.
Returns (nil, nil) — the documented "fall through to sequential" signal — when CEVM_STRICT=0 and the block contains something cevm cannot run yet. Under the default strict mode those cases return ErrGPUEVMRequired instead. On hard errors it returns the error.