mirror of
https://github.com/luxfi/evm.git
synced 2026-09-24 00:27:44 +00:00
This is a tracked file in a public repository. It carried a deployment analysis naming a cluster, namespace and statefulset, a recovery narrative, transaction hashes and balances from a running network, an address described as one the author controls, and a run of dated Problem/Status-FIXED postmortems. That is operational record, and it belongs to the private one. The RewardManager section keeps the mechanism, the config that activates it, the in-process proof, and the per-chain DAO addresses a reader needs to configure it; what it exercised on a running network is now stated as what was verified rather than as where and on which pods. The durable facts inside the postmortems are kept as properties: no beacon chain, so the Cancun blob fields are not part of a Lux EVM block; a genesis file has to reproduce the chain's block 0; importing history moves the database under anything reading it. Also drops "subnet" from two lines describing our own chains. Co-authored-by: Hanzo Dev <[email protected]>
944 lines
39 KiB
Markdown
944 lines
39 KiB
Markdown
# Lux EVM Module
|
||
|
||
## Project Overview
|
||
Lux EVM (formerly EVM) is the Ethereum Virtual Machine implementation for Lux L2 chains. This module provides EVM compatibility for the Lux network.
|
||
|
||
## CRITICAL VERSION REQUIREMENTS
|
||
**ALWAYS use these Lux-specific versions:**
|
||
- `github.com/luxfi/node v1.22.64` - Latest Lux node version
|
||
- `github.com/luxfi/geth v1.16.64` - Our fork of go-ethereum (with PQ crypto precompiles)
|
||
- `github.com/luxfi/crypto v1.17.27` - Cryptographic primitives
|
||
- `github.com/luxfi/precompiles v0.1.2` - Standalone precompile contracts
|
||
- `github.com/luxfi/p2p` - P2P networking package
|
||
- `github.com/luxfi/warp` - Warp messaging package
|
||
- `github.com/luxfi/consensus` - Consensus package
|
||
|
||
### IMPORTANT: Package Usage
|
||
- Use `lp118` package for p2p handlers
|
||
- Import: `github.com/luxfi/p2p/lp118`
|
||
- All handler IDs: `lp118.HandlerID`
|
||
- All functions: `lp118.NewCachedHandler`, `lp118.NewSignatureAggregator`
|
||
- NEVER import from ava-labs packages
|
||
- NEVER use go-ethereum directly, always use luxfi/geth
|
||
|
||
### p2p.Handler Interface
|
||
The `p2p.Handler` interface uses these methods:
|
||
- `Gossip(ctx, nodeID, gossipBytes)` - NOT AppGossip
|
||
- `Request(ctx, nodeID, deadline, requestBytes) ([]byte, *p2p.Error)` - NOT AppRequest
|
||
|
||
### p2p.Sender Interface
|
||
The `p2p.Sender` interface requires:
|
||
- `SendRequest(ctx, nodeIDs, requestID, request) error`
|
||
- `SendResponse(ctx, nodeID, requestID, response) error`
|
||
- `SendError(ctx, nodeID, requestID, errorCode, errorMessage) error`
|
||
- `SendGossip(ctx, config p2p.SendConfig, msg) error`
|
||
|
||
### p2p.Network Methods
|
||
- `Request(ctx, nodeID, requestID, deadline, request)` - NOT AppRequest
|
||
- `Response(ctx, nodeID, requestID, response)` - NOT AppResponse
|
||
- `Gossip(ctx, nodeID, gossipBytes)` - NOT AppGossip
|
||
|
||
### warp Package Types
|
||
- `NewUnsignedMessage(networkID uint32, sourceChainID ids.ID, payload []byte)` - takes ids.ID directly
|
||
- `Validator.NodeID` is `ids.NodeID` - NOT []byte
|
||
|
||
## Module Structure
|
||
```
|
||
/home/z/work/lux/evm/
|
||
├── plugin/evm/ # Main VM implementation
|
||
├── core/ # Core blockchain logic
|
||
├── consensus/ # Consensus engine (dummy for Lux)
|
||
├── eth/ # Ethereum protocol implementation
|
||
├── miner/ # Block building and mining
|
||
├── precompile/ # Precompiled contracts and warp
|
||
├── network/ # P2P networking
|
||
├── params/ # Chain configuration
|
||
├── scripts/ # Build and test scripts
|
||
└── warp/ # Cross-chain messaging
|
||
```
|
||
|
||
## Current Build Status
|
||
**✅ ALL TESTS PASSING - v0.8.18**
|
||
|
||
All 62 test packages pass. Key fixes:
|
||
1. **PQ Crypto Precompiles** - ML-DSA, SLH-DSA, ML-KEM integrated via geth v1.16.64
|
||
2. **Import Cycle Fixed** - precompiles v0.1.2 has no geth/core/vm dependency
|
||
3. **Bind Tests Fixed** - All ABI binding tests now pass
|
||
|
||
### Package Versions (2025-12-25)
|
||
| Package | Version | Status |
|
||
|---------|---------|--------|
|
||
| evm | v0.8.18 | ✅ All tests pass |
|
||
| geth | v1.16.64 | ✅ With PQ precompiles |
|
||
| precompiles | v0.1.2 | ✅ Standalone |
|
||
| crypto | v1.17.27 | ✅ All tests pass |
|
||
| node | v1.22.64 | ✅ Builds clean |
|
||
|
||
### Post-Quantum Crypto Precompiles
|
||
LP-aligned addresses (P=2 for PQ/Identity family):
|
||
- **ML-DSA** (FIPS 204) - Lattice-based signatures - `0x12202`
|
||
- **SLH-DSA** (FIPS 205) - Hash-based signatures - `0x12203`
|
||
- **ML-KEM** (FIPS 203) - Key encapsulation - `0x12201`
|
||
|
||
## EVM Upgrade Defaults (2026-03-29)
|
||
|
||
All EVM network upgrades are enabled at genesis (timestamp 0) by default:
|
||
- **EVMTimestamp** = 0 (always)
|
||
- **DurangoTimestamp** = 0 (Shanghai: PUSH0, warm coinbase)
|
||
- **EtnaTimestamp** = 0 (Cancun: MCOPY, TSTORE, TLOAD, BLOBHASH, BLOBBASEFEE)
|
||
- **FortunaTimestamp** = 0
|
||
- **GraniteTimestamp** = 0
|
||
|
||
`EVMDefaultChainConfig` also sets `ShanghaiTime` and `CancunTime` at 0 with
|
||
`BlobScheduleConfig` so geth's jump table selects the full Cancun instruction set.
|
||
|
||
The mapping: Durango -> Shanghai, Etna -> Cancun. These are set in `SetEthUpgrades()`.
|
||
|
||
**Stateful precompiles** (nativeminter, feemanager, etc.) are NOT enabled in the
|
||
default config because they require explicit permission configuration (admin
|
||
addresses). Call `SetAllGenesisPrecompiles()` on the extras config to enable them.
|
||
|
||
**Genesis precompile activation**: `ApplyPrecompileActivations` now runs at genesis
|
||
(parentTimestamp=nil). Previously it returned early, preventing genesis precompile
|
||
state from being written. The fix ensures deterministic genesis because precompile
|
||
configs are part of the chain config.
|
||
|
||
## C-Chain Tx-Fee Routing — RewardManager → DAO Gov Safe (LIVE PATH)
|
||
|
||
**Owner decision (supersedes the 50/50 below): 100% of every C-Chain tx fee accrues
|
||
to the chain's DAO Gov Safe, DAO-governed and redirectable on-chain.** This decouples
|
||
*collection* from *policy* — the DAO later decides burn / validators / treasury via
|
||
governance, on-chain, without another node upgrade. Real money on a 2T supply — staged
|
||
devnet→testnet→mainnet, never touch mainnet fee config without staged proof + owner go.
|
||
|
||
### Mechanism — existing RewardManager precompile, NO new fee-path code
|
||
The routing is stock C-Chain machinery, activated by config:
|
||
- `rewardmanager` precompile at **0x10205** (`precompile/contracts/rewardmanager/`).
|
||
- Activated via **precompileUpgrades** (`upgrade.json`) at a dated timestamp (coordinated
|
||
fork, NOT a genesis edit), gated so mainnet is inert until set.
|
||
- `initialRewardConfig.rewardAddress = <DAO Gov Safe>` → `StoreRewardAddress`.
|
||
`adminAddresses = [<DAO Gov Safe>]` → the DAO can call `setRewardAddress` on-chain
|
||
anytime (the "continually governed / redirectable" requirement; role-gated at
|
||
`contract.go:195` — non-admin callers revert).
|
||
- Routing path (all existing production code): `GetCoinbaseAt`
|
||
(`core/blockchain_reader.go:411`) reads `GetStoredRewardAddress` → sets
|
||
`header.Coinbase = reward address` → `core/state_transition.go:546` `creditTxFee`
|
||
credits the **full** fee to the coinbase. So 100% of the fee lands at the DAO Safe.
|
||
- The 50/50 `creditTxFee`/`FeeSplitTimestamp` code (below) stays committed but **DORMANT**
|
||
(FeeSplitTimestamp nil ⇒ legacy full-fee-to-coinbase branch), so it is transparent to
|
||
RewardManager and available if the DAO ever wants an in-protocol split.
|
||
|
||
### Proven (in-process, production code paths)
|
||
`core/reward_manager_routing_test.go` — `TestRewardManagerRoutesFeesToDAOSafe`: with
|
||
RewardManager active + reward = Lux DAO Gov Safe `0x8E29b816…`, the production
|
||
`GetCoinbaseAt` returns the DAO Safe (NOT blackhole); a **real `setRewardAddress` tx
|
||
from the admin** redirects routing to a new address live (observed via `GetCoinbaseAt`).
|
||
Combined with `TestCreditTxFeeLegacy` (full fee → coinbase, FeeSplit off) this proves
|
||
100% → reward address + on-chain DAO redirect. RewardManager's own suite
|
||
(`precompile/contracts/rewardmanager/`) covers role-gating + storage.
|
||
|
||
### Verified end to end on a multi-node network
|
||
Activation, routing and redirect were exercised on a running 5-node network with
|
||
an unmodified node and evm build — RewardManager is already present, so this is a
|
||
config change and not a rebuild.
|
||
|
||
- **Activation**: append `rewardManagerConfig` to `precompileUpgrades` with
|
||
`initialRewardConfig.rewardAddress` set to the chain's DAO Safe and
|
||
`adminAddresses` to the address that will govern it, then restart the fleet to
|
||
load it.
|
||
- **100% routing**: every tx fee accrues to the reward address; the blackhole
|
||
address stays flat.
|
||
- **On-chain redirect**: `setRewardAddress` from an admin moves accrual to the new
|
||
address from the next block, and back again — the DAO keeps control without a
|
||
node upgrade.
|
||
- **Determinism**: the reward balance and the state root agree across every node
|
||
at the same height, which is what makes this a consensus change rather than a
|
||
local accounting one.
|
||
|
||
### Per-chain DAO reward addresses (read canonical from `~/work/lux/standard/deployments/org-safes/`)
|
||
- **Lux C-Chain 96369** → DAO Gov Safe `0x8E29b816c6C35b13cE1ff68D33E245C2bda8ac3D`
|
||
- **Zoo 200200** → DAO Safe `0x229599f227231d8C90fcF1a78589F5DC4b7A6962`
|
||
- **Hanzo / Pars** → DAO Safes not yet in org-safes/ — STAGE before activation.
|
||
Deployable `upgrade.json` templates: `~/work/lux/standard/deployments/rewardmanager/`
|
||
(`lux-96369.json`, `zoo-200200.json`; `blockTimestamp` sentinel 9999999999 = inert until
|
||
the operator sets the coordinated fork time).
|
||
|
||
### How the upgrade schedule reaches the node
|
||
The C-Chain upgrade schedule is a file at `<chain-config-dir>/C/upgrade.json`. An
|
||
operator delivering it by ConfigMap copies the key into that path at boot; the
|
||
node reads it on start, so a schedule change is a restart and not a rebuild.
|
||
|
||
## Tx-Fee 50/50 Split — burn + staking-reward fold (DORMANT option, NOT the live path)
|
||
|
||
> Superseded as the live behavior by the RewardManager DAO routing above. This code is
|
||
> committed but gated OFF (`FeeSplitTimestamp` nil everywhere) and kept as a ready option
|
||
> if the DAO ever chooses an in-protocol burn+stake split. The P-Chain fold-in was NOT
|
||
> built (design only). Original design follows.
|
||
|
||
Owner decision (superseded): every C-Chain transaction fee is divided **50% true burn**
|
||
(real supply reduction) + **50% folded into the P-Chain staking reward** (validators'
|
||
returns grow from fee flow, unified into the native reward payout — NOT a separate
|
||
C-Chain coinbase stream).
|
||
|
||
### Current reality this replaces
|
||
The C-Chain credits the **entire** fee (base fee + tip, EVM-mode accounting) to
|
||
`block.Coinbase`, which defaults to the blackhole `0x0100…0000`
|
||
(`core/state_transition.go` fee-credit site; coinbase forced to blackhole by
|
||
`GetCoinbaseAt`). Nothing is burned; the fee just piles up in an uncontrolled EOA
|
||
(~3,778 LUX stuck there). The intended split was never built. Note: geth's own
|
||
`core/state_transition.go:569` is a *different* path used only by geth-direct
|
||
chains — the C-Chain runs **evm's vendored** `core/state_transition.go`, so the
|
||
split lives there.
|
||
|
||
### Mechanism (the ONE seam, deterministic, config-gated)
|
||
Single fee-disbursement site: `evm/core/state_transition.go` `execute()`. The
|
||
per-tx credit is delegated to `creditTxFee` (`evm/core/fee_split.go`):
|
||
|
||
- **Gate** — `extras.ChainConfig.FeeSplitTimestamp` (a *standalone* fee-routing
|
||
fork, sibling to `AllowFeeRecipients`; intentionally NOT in the `NetworkUpgrades`
|
||
opcode-fork chain — it is orthogonal to EVM/Durango/Quasar/… and has no ordering
|
||
relationship to them). `IsFeeSplit(time)` gates activation. A compatibility check
|
||
(`checkConfigCompatible`) freezes the activation time once effective, so a node
|
||
cannot silently reschedule it and fork.
|
||
- **Split** — `fee` = `gasUsed × effectiveGasPrice` (a consensus value):
|
||
- `rewardShare = fee >> 1` (floor(fee/2)) → credited to `extras.FeeRewardVault`
|
||
(`0x0100…0002`), a protocol-owned account that holds real, tracked balance.
|
||
- `burnShare = fee − rewardShare` (ceil(fee/2)) → **credited to no account**.
|
||
Never re-crediting it removes it from the account trie: the sum of all balances
|
||
(the supply) drops by exactly `burnShare`. This is a **true burn**, the same
|
||
mechanism as the EIP-1559 base-fee burn — NOT a transfer to a dead EOA (which
|
||
leaves supply unchanged). The odd wei on an odd fee goes to the burn.
|
||
- **Legacy path unchanged** — when `FeeSplit` is inactive, the full fee goes to the
|
||
coinbase exactly as before.
|
||
|
||
**Determinism**: `fee` is a consensus value; the split is pure uint256 integer math
|
||
(one right shift) to a fixed address — every validator computes an identical
|
||
post-state, so the handler cannot fork the chain. A running multi-node net that
|
||
keeps finalizing *is* the determinism proof.
|
||
|
||
### Conservation invariant
|
||
Per tx (fee F): `Δ(Σ balances) = −burnShare`, `Δ(vault) = +rewardShare`,
|
||
`rewardShare + burnShare = F`. Whole-system, after the vault is atomically exported
|
||
to P-Chain and paid to validators (a *move*, not a mint):
|
||
`total_supply_after = total_supply_before − Σ burnShare`. The reward half is
|
||
supply-neutral (redistributed); the curve-based staking mint is orthogonal and
|
||
unchanged. **No mint for the fee half ⇒ structurally impossible to double-mint.**
|
||
|
||
### Implemented + PROVEN on real block execution (C-Chain half)
|
||
Files: `evm/core/fee_split.go` (helper), `evm/core/state_transition.go` (seam),
|
||
`evm/params/extras/config.go` (`FeeRewardVault`, `FeeSplitTimestamp`, `IsFeeSplit`,
|
||
compat, description). Tests (all pass, `CGO_ENABLED=0 go test ./core/ ./params/extras/`):
|
||
- `core/fee_split_test.go` — split math, conservation, odd-wei rule, determinism
|
||
(identical post-state root), legacy-path preserved.
|
||
- `params/extras/fee_split_test.go` — activation-gate boundary + compat freeze.
|
||
- `core/fee_split_block_test.go` — **end-to-end on produced+accepted blocks**:
|
||
10 LUX genesis, 5 transfers @ 21000 gas × 225 gwei ⇒
|
||
- blackhole `0x0100…0000` balance = **0** (stuck behavior replaced)
|
||
- vault `0x0100…0002` = **11,812,500,000,000,000 wei** (exactly 50%)
|
||
- **BURNED = 11,812,500,000,000,000 wei** — supply 10e18 → 9.9881875e18 (real decrease)
|
||
- burn == vault (exact 50/50 on even fees); sender debit == value + fee. Conservation exact.
|
||
|
||
### P-Chain fold-in (designed; scoped — the larger, consensus-critical lift)
|
||
The reward half must reach P-Chain validators as staking reward. Chosen model **R1
|
||
(move, not mint)** — simplest correct, conservation by construction:
|
||
1. **Periodic atomic export** of the `FeeRewardVault` balance C→P (Avalanche/Lux
|
||
shared-memory export/import — the native conservation-exact value-move; today
|
||
exports are user-initiated, so a *system-triggered* epoch export is new machinery:
|
||
a hook in the C-Chain `FinalizeAndAssemble`/atomic path emitting an export UTXO to
|
||
a canonical P-Chain fee-reward-pool address, draining the vault).
|
||
2. **P-Chain fee-reward pool** — new persisted state (`vms/platformvm/state`:
|
||
`Get/SetFeeRewardPool`) funded by the import. (New persisted field ⇒ state
|
||
serialization/migration ⇒ consensus-critical; must be gated + migration-tested.)
|
||
3. **Distribution** — at `RewardValidatorTx` commit
|
||
(`vms/platformvm/txs/executor/proposal_tx_executor.go` `rewardValidatorTx`, ~line
|
||
285 where `reward := validator.PotentialReward`), add the validator's pro-rata
|
||
share of the pool (deterministic: by stake-weight over the accrual epoch) to the
|
||
payout UTXO — unifying it into the native staking-reward path with no second mint.
|
||
4. **Supply sync** — decrement P-Chain `currentSupply` by the epoch's burn `B` so the
|
||
reward curve (`vms/platformvm/reward/calculator.go`, driven by
|
||
`remainingSupply = SupplyCap − currentSupply`) sees true post-burn supply.
|
||
|
||
Rejected alternative **R2 (burn-on-C + re-mint-on-P)**: same net supply, but needs a
|
||
trustless cross-chain counter read and an exact burn==mint match (a double
|
||
supply-touch = double-mint/loss risk). Violates "no double-mint, simplest correct".
|
||
|
||
> Interpretation flag for owner: "unifies into the staking-reward **mint**" is
|
||
> realized as unifying into the staking-reward **payout**, funded by moved fees, not
|
||
> a second mint — the conservation-safe reading. Confirm before P-Chain build.
|
||
|
||
### Rollout (gated — do NOT skip a stage)
|
||
1. **Devnet 96367** — build the C-Chain plugin via **ARC CI** (never local docker),
|
||
deploy to the 5-validator devnet, set `feeSplitTimestamp` in the C-Chain upgrade
|
||
config to a near-future time. Send txs; verify via RPC on **all 5** nodes:
|
||
`eth_getBalance(0x0100…0002)` grows by Σfee/2; `eth_getBalance(0x0100…0000)` stays
|
||
flat; per-tx `gasUsed`+effective price ⇒ expected burn; identical state root /
|
||
block hash at each height across all 5 (determinism); capture before/after + tx
|
||
hashes. (Unit + block-level tests above already prove the invariants deterministically.)
|
||
2. **Testnet** — same config, longer soak; confirm no fork, supply-decrease trend.
|
||
3. **Mainnet 96369** — ONLY after owner go: add `feeSplitTimestamp` (future) to the
|
||
C-Chain upgrade config via a dated fork tx (not a genesis edit). Separate owner
|
||
decision: sweep vs. burn the ~3,778 LUX already stuck at `0x0100…0000`.
|
||
|
||
Guardrails honored: luxfi packages only; patch-semver; ARC CI builds (local builds
|
||
here were unit-tests only); deterministic; supply conserved exactly.
|
||
|
||
## Key Implementation Details
|
||
|
||
### Context Management
|
||
- VM uses `context.Context` instead of consensus.Context struct
|
||
- Access consensus data via helper functions:
|
||
- `consensus.GetChainID(ctx)`
|
||
- `consensus.GetNetworkID(ctx)`
|
||
- `consensus.GetNodeID(ctx)`
|
||
- `consensus.GetLogger(ctx)`
|
||
- `consensus.GetWarpSigner(ctx)`
|
||
|
||
### Interface Compatibility
|
||
- Block implements both `chain.Block` and `consensuschain.Block`
|
||
- BuildBlock returns `consensuschain.Block` for compatibility
|
||
- AppSender uses `set.Set[ids.NodeID]` for node sets
|
||
- Version uses `consensus/version.Application` not node's version
|
||
|
||
### Package Dependencies
|
||
**NEVER use these packages:**
|
||
- ❌ `github.com/ethereum/go-ethereum` - Use `github.com/luxfi/geth`
|
||
- ❌ `github.com/ava-labs/*` - Use `github.com/luxfi/*`
|
||
- ❌ `github.com/luxfi/node v1.16.x` - Use v1.13.4 for compatibility
|
||
|
||
**Always use:**
|
||
- ✅ `github.com/luxfi/consensus` - Local consensus package
|
||
- ✅ `github.com/luxfi/crypto` - Local crypto package
|
||
- ✅ `github.com/luxfi/warp` - Local warp package
|
||
- ✅ `github.com/luxfi/geth` - Our Ethereum fork
|
||
|
||
### Build Commands
|
||
```bash
|
||
cd /home/z/work/lux/evm
|
||
go build ./... # Currently fails due to interface issues
|
||
go test ./... # Will work after build issues are resolved
|
||
```
|
||
|
||
### Common Issues and Fixes
|
||
|
||
1. **Version Requirements**
|
||
- Always use node v1.16.15 or later Lux versions
|
||
- Never use ava-labs packages
|
||
- Check go.mod replace directives
|
||
|
||
2. **Interface Compatibility**
|
||
- Block needs SetStatus method (even if no-op)
|
||
- BuildBlock must return consensuschain.Block
|
||
- Context is context.Context, not a struct
|
||
|
||
3. **Missing Metrics**
|
||
- Metrics registration is currently disabled (TODO)
|
||
- Will be re-enabled when consensus context supports it
|
||
|
||
4. **ID Type Conversions**
|
||
```go
|
||
// Convert between node's IDs and consensus IDs
|
||
func nodeIDToConsensus(id nodeids.NodeID) ids.NodeID {
|
||
var consensusID ids.NodeID
|
||
copy(consensusID[:], id[:])
|
||
return consensusID
|
||
}
|
||
```
|
||
|
||
## Testing
|
||
- Run with `-short` flag for quick tests
|
||
- 28 packages with tests, 14 without (expected)
|
||
- Tests will pass after build issues are resolved
|
||
|
||
## Important Notes
|
||
- This module is actively being migrated from evm
|
||
- Maintains backwards compatibility with existing Lux L2 chains
|
||
- Uses single validator POA for development (k=1 consensus)
|
||
- Major refactoring needed to reconcile ID type differences between packages
|
||
|
||
## Documentation Status (2025-11-12)
|
||
|
||
### ✅ Documentation Enhanced
|
||
Successfully created comprehensive documentation for the Lux EVM implementation.
|
||
|
||
#### Documentation Created
|
||
1. **Enhanced index.mdx** (`/Users/z/work/lux/evm/docs/content/docs/index.mdx`)
|
||
- Complete EVM overview and architecture
|
||
- Key differences from standard EVM
|
||
- Smart contract deployment guide
|
||
- Gas optimization strategies
|
||
- Comprehensive API reference (eth, web3, net, admin, debug, validators, warp)
|
||
- Integration with Lux blockchain
|
||
- Performance tuning configuration
|
||
- Security best practices
|
||
- Troubleshooting guide
|
||
- Migration guides from Ethereum and C-Chain
|
||
|
||
#### Documentation Features Added
|
||
- **Architecture Section**: VM, Core, Precompiles detailed
|
||
- **API Reference**: 40+ JSON-RPC endpoints documented
|
||
- **Code Examples**: JavaScript, Solidity, configuration files
|
||
- **Performance Guide**: State management, transaction pool, benchmarking
|
||
- **Security Guide**: Access control, gas limits, cross-chain security
|
||
- **Troubleshooting**: Common issues and debug commands
|
||
- **Migration Guides**: From Ethereum and C-Chain
|
||
|
||
#### Build Status
|
||
- ✅ Documentation site builds successfully
|
||
- ✅ Next.js 16.0.1 with Turbopack
|
||
- ✅ Static site generation working
|
||
- ✅ All pages render correctly
|
||
|
||
### Completeness Score: 95/100
|
||
|
||
#### What's Complete
|
||
- ✅ Overview and introduction (100%)
|
||
- ✅ Architecture documentation (100%)
|
||
- ✅ API reference (100%)
|
||
- ✅ Smart contract deployment (100%)
|
||
- ✅ Gas optimization (100%)
|
||
- ✅ Integration guide (100%)
|
||
- ✅ Performance tuning (100%)
|
||
- ✅ Security considerations (100%)
|
||
- ✅ Troubleshooting (100%)
|
||
- ✅ Migration guides (100%)
|
||
|
||
#### What Could Be Added (5%)
|
||
- Additional code examples for each precompile
|
||
- Detailed tutorials for specific use cases
|
||
- Video documentation links
|
||
- Interactive API explorer
|
||
- Benchmark results and graphs
|
||
|
||
### Precompiled Contracts Available
|
||
1. **DeployerAllowList** - Contract deployment permissions
|
||
2. **FeeManager** - Dynamic fee configuration
|
||
3. **NativeMinter** - Native token minting
|
||
4. **RewardManager** - Validator rewards
|
||
5. **TxAllowList** - Transaction permissions
|
||
6. **Warp** - Cross-chain messaging
|
||
7. **PQCrypto** - Post-quantum cryptography
|
||
8. **Quasar** - Advanced consensus features
|
||
|
||
## Readonly Database Support (2025-11-22)
|
||
|
||
### Status: ✅ VERIFIED WORKING
|
||
|
||
Successfully implemented and verified readonly database access for legacy PebbleDB databases.
|
||
|
||
### Key Changes
|
||
1. **Database Factory Fix** (`~/work/lux/database/factory/pebbledb.go`)
|
||
- Added `readOnly bool` parameter to `newPebbleDB()` function
|
||
- Passes readonly flag to `pebbledb.New()` instead of hardcoded `false`
|
||
- Committed to database repo (commit aaee95a)
|
||
|
||
2. **EVM Integration** (`~/work/lux/evm/go.mod`)
|
||
- Added replace directive: `replace github.com/luxfi/database => ../database`
|
||
- Enables EVM to use local database with readonly fix
|
||
|
||
3. **Test Verification** (`test-readonly-db.go`)
|
||
- Successfully opens 7.1GB legacy PebbleDB in readonly mode
|
||
- Can read all keys without write access
|
||
- No corruption or modification risk
|
||
|
||
### Legacy Database Details
|
||
- **Location**: `/Users/z/work/lux/state/chaindata/lux-mainnet-96369/db/pebbledb`
|
||
- **Size**: 7.1GB (751 files)
|
||
- **Blockchain ID**: `dnmzhuf6poM6PUNQCe7MWWfBdTJEnddhHRNXz2x7H6qSmyBEJ`
|
||
- **Chain ID**: 96369
|
||
- **Purpose**: Legacy evm data for regenesis export
|
||
|
||
### Correct Migration Approach
|
||
|
||
**IMPORTANT**: Do NOT manually migrate database files between formats.
|
||
|
||
The proper workflow using lux-cli and VM interfaces:
|
||
1. **Deploy L2**: Use `lux l2 create` and `lux l2 deploy` to create a Net
|
||
2. **Export Data**: Use VM's exporter interface via lux-cli export commands
|
||
3. **Import to C-Chain**: Use VM's importer interface via `lux migrate import`
|
||
|
||
### VM Importer/Exporter Interface
|
||
|
||
Each VM must implement:
|
||
- **Exporter Interface**: Serialize blockchain state to portable format
|
||
- **Importer Interface**: Deserialize and load blockchain state
|
||
- **Format**: VM-agnostic, standardized data structure
|
||
|
||
### Current lux-cli Status
|
||
|
||
The `lux migrate` command exists but is incomplete:
|
||
- `lux migrate prepare` - Placeholder, needs migration-tools implementation
|
||
- `lux migrate import` - Not yet implemented
|
||
- `lux migrate bootstrap` - Partial implementation
|
||
- `lux migrate validate` - Not implemented
|
||
|
||
### Implementation Needed
|
||
|
||
To complete the migration workflow:
|
||
|
||
1. **VM Exporter** (`plugin/evm/export.go`):
|
||
```go
|
||
func (vm *VM) Export(ctx context.Context) ([]byte, error) {
|
||
// Export blockchain state to standardized format
|
||
// Include: genesis, blocks, state trie, metadata
|
||
}
|
||
```
|
||
|
||
2. **VM Importer** (`plugin/evm/import.go`):
|
||
```go
|
||
func (vm *VM) Import(ctx context.Context, data []byte) error {
|
||
// Import blockchain state from standardized format
|
||
// Validate and load into C-Chain database
|
||
}
|
||
```
|
||
|
||
3. **lux-cli Migration Tools**:
|
||
- Implement `migration-tools/migrate.go` that calls VM exporter/importer
|
||
- Complete `lux migrate prepare` to use VM interfaces
|
||
- Implement `lux migrate import` for C-Chain import
|
||
|
||
### Architecture Principles
|
||
|
||
- ✅ Use VM's native export/import interfaces
|
||
- ✅ Let each VM handle its own data format
|
||
- ✅ Generic migration via standardized interfaces
|
||
- ❌ NO manual database file copying
|
||
- ❌ NO format-specific conversion scripts
|
||
- ❌ NO direct database manipulation outside VM
|
||
|
||
### Current Implementation Status (2025-11-23)
|
||
|
||
**✅ Fixed:**
|
||
1. Import paths updated to use `luxfi/geth` instead of `go-ethereum`
|
||
2. Import paths updated to use `luxfi/ids` instead of `luxfi/node/ids`
|
||
3. Chainmigrate interfaces.go fixed with correct imports
|
||
4. Duplicate ChainMigrator definition resolved (renamed struct to Migrator)
|
||
5. Broken implementation files disabled (.go.broken extension)
|
||
6. Package consistency verified - all luxfi packages used correctly
|
||
|
||
**📦 Required Package Imports:**
|
||
- Ethereum types: `github.com/luxfi/geth` (NOT go-ethereum)
|
||
- IDs: `github.com/luxfi/ids` (NOT luxfi/node/ids)
|
||
- Logging: `github.com/luxfi/log` (ALWAYS use luxfi/log for consistency)
|
||
- Chainmigrate: `github.com/luxfi/node/chainmigrate`
|
||
|
||
**🔄 In Progress:**
|
||
- Fixing exporter.go to match actual VM structure
|
||
- Need to access NetworkID from chainCtx, not config
|
||
- Need to find correct method for GetTd (total difficulty)
|
||
- Need to create proper error types (ErrMissing, ErrNotImplemented)
|
||
- Need to convert uint256.Int to *big.Int for balance
|
||
|
||
**⏳ Next Steps:**
|
||
1. Complete exporter.go fixes to compile successfully
|
||
2. Create importer.go implementation
|
||
3. Test export functionality with readonly database
|
||
4. Create migration-tools in lux-cli that use these interfaces
|
||
5. Complete `lux migrate` command implementation
|
||
6. Test full export → import workflow
|
||
7. Verify C-Chain can serve exported data via RPC
|
||
## lux-cli Integration (2025-11-23)
|
||
|
||
### ✅ COMPLETE: ChainExporter integrated with lux-cli
|
||
|
||
**Integration Architecture:**
|
||
```
|
||
lux-cli migrate
|
||
↓
|
||
migration-tools/migrate (symlink)
|
||
↓
|
||
node/cmd/chainmigrate/chainmigrate (binary)
|
||
↓
|
||
node/chainmigrate/interfaces.go (ChainExporter interface)
|
||
↓
|
||
evm/plugin/evm/exporter.go (implementation)
|
||
```
|
||
|
||
**CLI Tool Location:**
|
||
- Binary: `/Users/z/work/lux/node/cmd/chainmigrate/chainmigrate`
|
||
- Symlink: `/Users/z/work/lux/cli/migration-tools/migrate`
|
||
|
||
**Usage via lux-cli:**
|
||
```bash
|
||
lux migrate prepare \
|
||
--source-db ~/.node/chaindata/subnet-96369/db/pebbledb \
|
||
--output ./mainnet-migration \
|
||
--network-id 96369 \
|
||
--validators 5
|
||
```
|
||
|
||
**Direct Binary Usage:**
|
||
```bash
|
||
node/cmd/chainmigrate/chainmigrate \
|
||
--src-pebble /path/to/source/db \
|
||
--dst-leveldb /path/to/dest/db \
|
||
--chain-id 96369 \
|
||
--start-block 0 \
|
||
--end-block 1000 \
|
||
--batch-size 100
|
||
```
|
||
|
||
**Features:**
|
||
- ✅ Uses luxfi/log for logging
|
||
- ✅ Uses luxfi/geth for Ethereum types
|
||
- ✅ Uses ChainExporter interface
|
||
- ✅ Configurable batch sizes
|
||
- ✅ Block range selection
|
||
- ✅ Export-only and import-only modes
|
||
|
||
**Integration Tests:** All passing ✅
|
||
|
||
**Next Steps:**
|
||
1. Complete full EVM integration (initialize VM with readonly DB)
|
||
2. Implement importer.go for destination chain
|
||
3. Test end-to-end export → import workflow
|
||
|
||
## Integration Approach - RPC-BASED (2025-11-23)
|
||
|
||
### ✅ RPC Control: lux-cli uses netrunner + RPC only
|
||
|
||
**Previous Approaches (WRONG):** ❌
|
||
1. Created ad-hoc cmd/chainmigrate binary in node repo
|
||
2. Used symlinks to bridge binaries
|
||
3. Used ChainExporter interface as Go import in lux-cli
|
||
4. Direct Go package dependencies
|
||
|
||
**Current Approach (CORRECT):** ✅
|
||
- **lux-cli**: RPC client for fleet control
|
||
- **netrunner**: Deploys and manages node fleet
|
||
- **EVM MigrateAPI**: RPC endpoints for export/import
|
||
- NO Go package imports between cli and evm
|
||
- Pure RPC communication only
|
||
|
||
**Architecture:**
|
||
```
|
||
lux-cli (RPC client)
|
||
↓ HTTP JSON-RPC calls
|
||
netrunner (fleet manager)
|
||
↓ deploys nodes
|
||
EVM node (with MigrateAPI)
|
||
↓ migrate_getBlocks
|
||
↓ migrate_importBlocks
|
||
Database (PebbleDB/LevelDB)
|
||
```
|
||
|
||
**Implementation:**
|
||
```go
|
||
// lux-cli/cmd/migratecmd/utils.go
|
||
func runMigration(sourceRPC, destRPC string, chainID int64) error {
|
||
// Get current block via RPC
|
||
blockNum, err := getCurrentBlock(ctx, sourceRPC)
|
||
|
||
// Call migrate_getBlocks via RPC (no Go imports!)
|
||
req := &RPCRequest{
|
||
Method: "migrate_getBlocks",
|
||
Params: []interface{}{0, blockNum, 100},
|
||
}
|
||
callRPC(sourceRPC, req, &blocks)
|
||
|
||
// Import via RPC to destination
|
||
req = &RPCRequest{
|
||
Method: "migrate_importBlocks",
|
||
Params: []interface{}{blocks},
|
||
}
|
||
callRPC(destRPC, req, &result)
|
||
}
|
||
```
|
||
|
||
**EVM RPC Endpoints:**
|
||
```go
|
||
// plugin/evm/api_migrate.go
|
||
type MigrateAPI struct {
|
||
vm *VM
|
||
}
|
||
|
||
// RPC: migrate_getChainInfo
|
||
func (api *MigrateAPI) GetChainInfo() (*ChainInfo, error)
|
||
|
||
// RPC: migrate_getBlocks (batch, max 100 blocks)
|
||
func (api *MigrateAPI) GetBlocks(start, end, limit uint64) ([]*BlockData, error)
|
||
|
||
// RPC: migrate_streamBlocks (streaming via channels)
|
||
func (api *MigrateAPI) StreamBlocks(start, end uint64) (chan *BlockData, chan error)
|
||
|
||
// RPC: migrate_importBlocks
|
||
func (api *MigrateAPI) ImportBlocks(blocks []*BlockData) (int, error)
|
||
```
|
||
|
||
**Benefits:**
|
||
- True fleet control via RPC (lux-cli controls remote nodes)
|
||
- No Go package coupling between repos
|
||
- Can control nodes anywhere (local, remote, cloud)
|
||
- Netrunner handles deployment, lux-cli handles orchestration
|
||
- Works with any number of nodes
|
||
- Clean separation: deploy vs control vs execution
|
||
|
||
**Workflow:**
|
||
1. Deploy source EVM with netrunner (readonly DB):
|
||
```bash
|
||
netrunner engine start evm-source --data-dir=/readonly/db
|
||
```
|
||
|
||
2. Deploy destination C-Chain with netrunner:
|
||
```bash
|
||
netrunner engine start c-chain
|
||
```
|
||
|
||
3. Run migration via lux-cli (auto-discovers RPC endpoints):
|
||
```bash
|
||
lux migrate prepare
|
||
# RPC endpoints discovered from netrunner at runtime
|
||
# Source: ext/bc/<blockchain-id>/rpc (old 96369 net)
|
||
# Dest: ext/bc/C/rpc (C-Chain)
|
||
# Internal RPC uses port 9630 (not 9650)
|
||
# Hosts/ports known at runtime, not hardcoded
|
||
```
|
||
|
||
**RPC Path Format:**
|
||
- **C-Chain**: `ext/bc/C/rpc` (uses C alias)
|
||
- **Old 96369 Net**: `ext/bc/dnmzhuf6poM6PUNQCe7MWWfBdTJEnddhHRNXz2x7H6qSmyBEJ/rpc` (uses blockchain ID)
|
||
|
||
## MigrateAPI Registration Status (2025-11-23)
|
||
|
||
### ✅ COMPLETE: MigrateAPI Registered with EVM Node
|
||
|
||
The MigrateAPI has been successfully registered with the EVM node and is now available via RPC.
|
||
|
||
**Changes Made:**
|
||
1. Added `MigrateAPIEnabled` config flag to `plugin/evm/config/config.go`
|
||
2. Set default to `true` in `plugin/evm/config/default_config.go`
|
||
3. Registered MigrateAPI in `plugin/evm/vm.go` (similar to WarpAPI)
|
||
4. Fixed type errors in `plugin/evm/api_migrate.go`:
|
||
- Changed `Transactions` field from `[]types.Transaction` to `[]*types.Transaction`
|
||
- Fixed `WithBody` call to use `types.Body` directly
|
||
|
||
**Available RPC Methods:**
|
||
- `migrate_getChainInfo` - Returns blockchain metadata (chain ID, network ID, current height, etc.)
|
||
- `migrate_getBlocks` - Exports blocks in batches (max 100 blocks per call)
|
||
- `migrate_streamBlocks` - Streams blocks via channels (not yet exposed via JSON-RPC)
|
||
- `migrate_importBlocks` - Imports blocks to the blockchain
|
||
|
||
**Configuration:**
|
||
```json
|
||
{
|
||
"migrate-api-enabled": true // Default: true
|
||
}
|
||
```
|
||
|
||
**Testing Status:**
|
||
- ✅ EVM plugin builds successfully
|
||
- ✅ MigrateAPI properly registered in RPC handler
|
||
- ✅ CLI commands (export-data, import-data) implemented
|
||
- ⏳ End-to-end RPC testing pending
|
||
|
||
**Next Steps:**
|
||
1. Deploy EVM node with readonly database
|
||
2. Test `migrate_getChainInfo` RPC call
|
||
3. Test `migrate_getBlocks` with various block ranges
|
||
4. Test full export → import workflow via lux-cli
|
||
5. Verify imported data on destination chain
|
||
|
||
---
|
||
|
||
## Properties this EVM holds
|
||
|
||
**No beacon chain.** Lux networks run their own consensus, so the Cancun-era
|
||
EIP-4844 beacon fields are not part of a Lux EVM block and the blob-fee path is
|
||
not reachable on a fork that does not enable it.
|
||
|
||
**A genesis file has to reproduce the chain's block 0.** For a chain being
|
||
brought up against existing history, the genesis hash computed from genesis.json
|
||
must equal the original block 0 hash exactly; import checks it rather than
|
||
assuming it, because a genesis that differs describes a different chain.
|
||
|
||
**Importing history is not a read-only operation.** `admin_importChain` moves the
|
||
chain database underneath everything reading it, so it runs against a node that
|
||
is not concurrently serving those reads.
|
||
|
||
## Post-Quantum Cryptography Precompiles (2025-12-24)
|
||
|
||
### Status: ✅ COMPLETE - All PQ Crypto Precompiles Implemented and Tested
|
||
|
||
Lux EVM includes native precompiled contracts for NIST FIPS 203-205 post-quantum cryptography algorithms.
|
||
|
||
### Precompile Addresses (LP-aligned)
|
||
|
||
| Precompile | Address | Description |
|
||
|------------|---------|-------------|
|
||
| **PQCrypto Unified** | `0x0000000000000000000000000000000000012201` | All PQ crypto operations (P=2 PQ/Identity) |
|
||
| **ML-DSA Verify** | `0x0000000000000000000000000000000000012202` | Dedicated ML-DSA verification |
|
||
| **SLH-DSA Verify** | `0x0000000000000000000000000000000000012203` | Dedicated SLH-DSA verification |
|
||
|
||
### Gas Costs (Per Mode)
|
||
|
||
#### ML-DSA Signature Verification (FIPS 204)
|
||
|
||
| Mode | Security | Mode Byte | Gas Cost |
|
||
|------|----------|-----------|----------|
|
||
| ML-DSA-44 | Level 2 | `0x44` | **75,000** |
|
||
| ML-DSA-65 | Level 3 | `0x65` | **100,000** |
|
||
| ML-DSA-87 | Level 5 | `0x87` | **150,000** |
|
||
|
||
#### ML-KEM Key Encapsulation (FIPS 203)
|
||
|
||
| Mode | Security | Mode Byte | Encap Gas | Decap Gas |
|
||
|------|----------|-----------|-----------|-----------|
|
||
| ML-KEM-512 | Level 1 | `0x00` | **6,000** | **6,000** |
|
||
| ML-KEM-768 | Level 3 | `0x01` | **8,000** | **8,000** |
|
||
| ML-KEM-1024 | Level 5 | `0x02` | **10,000** | **10,000** |
|
||
|
||
#### SLH-DSA Signature Verification (FIPS 205)
|
||
|
||
| Mode | Hash | Security | Mode Byte | Gas Cost |
|
||
|------|------|----------|-----------|----------|
|
||
| 128s | SHA-256 | Level 1 | `0x00` | **50,000** |
|
||
| 128f | SHA-256 | Level 1 | `0x01` | **75,000** |
|
||
| 192s | SHA-256 | Level 3 | `0x02` | **100,000** |
|
||
| 192f | SHA-256 | Level 3 | `0x03` | **150,000** |
|
||
| 256s | SHA-256 | Level 5 | `0x04` | **175,000** |
|
||
| 256f | SHA-256 | Level 5 | `0x05` | **250,000** |
|
||
| 128s | SHAKE | Level 1 | `0x10` | **50,000** |
|
||
| 128f | SHAKE | Level 1 | `0x11` | **75,000** |
|
||
| 192s | SHAKE | Level 3 | `0x12` | **100,000** |
|
||
| 192f | SHAKE | Level 3 | `0x13` | **150,000** |
|
||
| 256s | SHAKE | Level 5 | `0x14` | **175,000** |
|
||
| 256f | SHAKE | Level 5 | `0x15` | **250,000** |
|
||
|
||
### Implementation Files
|
||
|
||
```
|
||
precompile/contracts/
|
||
├── mldsa/
|
||
│ ├── contract.go # ML-DSA precompile (182 lines)
|
||
│ ├── contract_test.go # 334 lines, 10 test cases
|
||
│ └── module.go # Registration
|
||
└── pqcrypto/
|
||
├── contract.go # Unified PQ precompile (382 lines)
|
||
├── contract_test.go # 234 lines, 20 test cases
|
||
├── module.go # Registration
|
||
└── config.go # Configuration
|
||
```
|
||
|
||
### Mode Byte Encoding
|
||
|
||
**Critical**: Precompile mode bytes differ from library internal values:
|
||
|
||
```go
|
||
// Precompile mode bytes (used in input)
|
||
ModeMLDSA44 uint8 = 0x44 // Library: mldsa.MLDSA44 = 0
|
||
ModeMLDSA65 uint8 = 0x65 // Library: mldsa.MLDSA65 = 1
|
||
ModeMLDSA87 uint8 = 0x87 // Library: mldsa.MLDSA87 = 2
|
||
```
|
||
|
||
The precompile implementation converts between these formats in the `Run()` method.
|
||
|
||
### Function Selectors (PQCrypto Unified)
|
||
|
||
| Selector | Bytes | Operation |
|
||
|----------|-------|-----------|
|
||
| `"mlds"` | `0x6d6c6473` | ML-DSA Verify |
|
||
| `"encp"` | `0x656e6370` | ML-KEM Encapsulate |
|
||
| `"decp"` | `0x64656370` | ML-KEM Decapsulate |
|
||
| `"slhs"` | `0x736c6873` | SLH-DSA Verify |
|
||
|
||
### Test Status
|
||
|
||
```
|
||
=== ML-DSA Tests ===
|
||
TestMLDSAVerify_ValidSignature PASS
|
||
TestMLDSAVerify_InvalidSignature PASS
|
||
TestMLDSAVerify_WrongMessage PASS
|
||
TestMLDSAVerify_InputTooShort PASS
|
||
TestMLDSAVerify_EmptyMessage PASS
|
||
TestMLDSAVerify_LargeMessage PASS
|
||
TestMLDSAVerify_GasCost PASS
|
||
TestMLDSAPrecompile_Address PASS
|
||
|
||
=== PQCrypto Tests ===
|
||
TestPQCryptoPrecompile PASS
|
||
TestMLDSAVerify PASS
|
||
TestMLKEMEncapsulateDecapsulate PASS
|
||
TestSLHDSAVerify PASS
|
||
TestGasCalculation (15 subtests) PASS
|
||
|
||
Total: 20 tests, 0 failures
|
||
```
|
||
|
||
### Documentation
|
||
|
||
Full specification documented in:
|
||
- **LP-3520**: Post-Quantum Cryptography Precompile Implementation Guide
|
||
- **LP-4200**: Post-Quantum Cryptography Suite for Lux Network
|
||
- **LP-3502**: ML-DSA Post-Quantum Signature Precompile
|
||
|
||
### Dependencies
|
||
|
||
- `github.com/luxfi/crypto/mldsa` - ML-DSA implementation (FIPS 204)
|
||
- `github.com/luxfi/crypto/mlkem` - ML-KEM implementation (FIPS 203)
|
||
- `github.com/luxfi/crypto/slhdsa` - SLH-DSA implementation (FIPS 205)
|
||
- Backend: Cloudflare CIRCL (audited, FIPS compliant)
|
||
|
||
---
|
||
|
||
## Pluggable Backends + Auto-Import
|
||
|
||
### Backend selection (build tags)
|
||
|
||
| Build | Backend | Notes |
|
||
|-------|---------|-------|
|
||
| `go build ./plugin` | Go EVM (Block-STM) | Default. Pure Go. |
|
||
| `-tags gpu` | Go EVM + Metal GPU bridge | `core/parallel/gpu_bridge.go`. Requires working `luxfi/gpu` module. Currently broken upstream — MLX bindings (`mlx_zeros`, `mlx_from_slice_int64`, `mlx_floor`, `mlx_full`, etc.) are stubs in `~/work/luxcpp/mlx-c-api/mlx_c_api.c` returning NULL with mismatched signatures. Don't use until upstream lands real MLX impls. |
|
||
| `-tags cevm` | C++ EVM via cgo | `core/parallel/backend_cevm.go`. Real GPU path — links `~/work/luxcpp/cevm/build-phase5b/lib/{libevm,libevm-gpu-state,libevm-metal-hosts,libevm-kernel-metal}`. Requires `bash chains/evm/cevm/fetch-luxcpp.sh` to populate libs. |
|
||
| `-tags revm` | Rust EVM via FFI | `core/parallel/backend_revm.go`. Requires `librustc_revm.a` from `luxfi/revm`. |
|
||
|
||
`gpu_bridge.go:4` build tag is `cgo && darwin && gpu` (opt-in).
|
||
|
||
### `--import-chain-data` plumbing
|
||
|
||
luxd's `--import-chain-data=<path.rlp>` flag now flows through to the EVM plugin:
|
||
|
||
1. `node/config/config.go:2012-2028` config bridge injects the path into
|
||
`nodeConfig.ChainConfigs["C"].Config` JSON map.
|
||
2. EVM plugin reads `vm.config.ImportChainData` (declared in
|
||
`plugin/evm/config/config.go`, JSON key `import-chain-data`).
|
||
3. After `initializeChain()` in `plugin/evm/vm.go::Initialize()`, if
|
||
`ImportChainData != ""`, calls `importBlocksFromFile(chain, path,
|
||
persistAccepted)` from `plugin/evm/admin_api.go:220`. Same code path as
|
||
`admin_importChain` RPC.
|
||
4. Batches of 2,500 blocks. State trie committed every `CommitInterval`
|
||
(default 4,096) blocks; `acceptedBlockDB` updated atomically with each commit.
|
||
|
||
Canonical mainnet hashes/state root and required precompiles live in
|
||
`~/work/lux/genesis/LLM.md` "Canonical Requirements" — single source of truth.
|
||
|
||
### Build commands
|
||
|
||
```bash
|
||
cd ~/work/lux/evm
|
||
|
||
# Default: builds and installs the plugin at the canonical path
|
||
# (~/.lux/plugins/<EVMID> where EVMID = CB58(ids.ID{'e','v','m'}) per luxfi/constants.EVMID).
|
||
# Handles codesign on darwin in one shot. No hardcoded plugin paths, no aliases.
|
||
./scripts/build.sh
|
||
|
||
# Variants (build, then have luxd point its --plugin-dir at the chosen build):
|
||
./scripts/build.sh /tmp/evm-default # plain Go EVM (default)
|
||
GOFLAGS='-tags cevm' ./scripts/build.sh /tmp/evm-cevm # C++ backend (real GPU)
|
||
GOFLAGS='-tags revm' ./scripts/build.sh /tmp/evm-revm # Rust REVM backend
|
||
```
|
||
|
||
The plugin filename is the binary's location: luxd's chain manager looks up
|
||
`<plugin-dir>/<VMID>` and `constants.EVMID = ids.ID{'e','v','m'}` (CB58 =
|
||
`mgj786NP…`) is the canonical primary-network C-Chain ID. Same ID is used
|
||
for every EVM-based L2 chain in Lux. No second filename, no aliases.
|
||
|
||
### Known upstream gaps
|
||
|
||
- `luxfi/gpu@v0.30.0` MLX C bindings unimplemented — stubs in
|
||
`~/work/luxcpp/mlx-c-api/mlx_c_api.c`. Don't use `-tags gpu` until landed.
|
||
- `luxfi/accel@v1.0.7` API drift — `accel.VMSession`, `NewVMSession`,
|
||
`WithPriority`, `PriorityHigh` undefined. Blocks `chains/keyvm` and likely
|
||
other chains/*vm. Independent of EVM stack.
|
||
- `luxfi/coreth` is DEPRECATED per `coreth/DEPRECATED.md` — use this repo
|
||
(`luxfi/evm`) for all new C-Chain and L1 EVM work.
|
||
|