# Genesis Canonical genesis configurations for all Lux blockchain networks. **This repo is the single source of truth for chain IDs, genesis hashes, state roots, and required precompiles.** Other repos (`~/work/lux/{node,evm,state}`) reference these values; do not duplicate them. **Latest Tag**: v1.9.6 ## Post-E2E-PQ State (current) Genesis now pins a `ChainSecurityProfile` for every chain it generates, and resolves it at load time. The profile hash is committed into the chain's bootstrap so a profile-flip is a wrong-network event, not a silent classification change. ### Recent significant commits | SHA | Tag | Impact | |-----|-----|--------| | `85a8fc8` | v1.9.6 | Pin ChainSecurityProfile into Config + Resolve at load (closes F102 genesis layer) | | `1d73c8d` | v1.9.6 | Swap mldsa65 keygen from cloudflare/circl to luxfi/crypto/pq/mldsa | | `e698307` | v1.9.5 | HD branch hardening + LightMnemonic production refusal (F12/F30/F31/F35) | | `fe4781c` | v1.9.5 | `LUX_DISABLE_CCHAIN=1` omits C-Chain from primary genesis | | `2b16f45` | v1.9.5 | Operator-overridable C-Chain genesis via `LUX_CCHAIN_GENESIS_FILE` | ### Zoo testnet/devnet 39-char alloc address bug (May 2026) `zooai/universe/configs/genesis/{testnet,devnet}/genesis.json` (moved from `luxfi/genesis/configs/zoo-*/` in Task #109, 2026-06-04) shipped six alloc addresses with only 39 hex chars instead of 40 — the leading `0` nibble was stripped at genesis-generation time (commit `2b46a8b`, "regenerate all network configs"). The six bad addresses on both files were: | Truncated (39ch, shipped) | Correct (40ch, present in C-chain alloc) | |---|---| | `2aCB0ee16fd2B1bF465F85D7Ee112fA80C055FC` | `02aCB0ee16fd2B1bF465F85D7Ee112fA80C055FC` | | `3B8Bd0A20b05AADC9E457A4c967f45eEeC163c4` | `03B8Bd0A20b05AADC9E457A4c967f45eEeC163c4` | | `54D2e1dA5A1B5b9Da158acbA42Aed1d45F5CF02` | `054D2e1dA5A1B5b9Da158acbA42Aed1d45F5CF02` | | `5CAE5842A08165d4d736dA9E49438574283aaE9` | `05CAE5842A08165d4d736dA9E49438574283aaE9` | | `698495959f5570420BAA955dae5eA2864933ACf` | `0698495959f5570420BAA955dae5eA2864933ACf` | | `7283AA2c30523E9190A17b9598ff65599BAAe17` | `07283AA2c30523E9190A17b9598ff65599BAAe17` | Symptom: the EVM refused to bootstrap the chain — `parsing genesis: hex string of odd length`. The original CreateChainTx (`ZAKw...` on testnet, `2nLY...` on devnet) carries the broken genesis bytes immutably, so we had to re-issue under a new chain name and rewrite the gateway. The 39→40-char fix applied in genesis is now the SAME content the EVM expects. Operators bootstrapping a fresh zoo chain should pin the post-fix checksums in this file (see `### Verify Checksum`). Mainnet zoo (`zoo-mainnet/genesis.json`) was *not* affected — it has only the treasury account plus the `0x0200…0005` precompile. ### Chain bootstrap: chain-name collision (P-chain) `platform.IsChainNameTaken` is case-insensitive and global across all chains. A failed CreateChainTx (e.g. the broken zoo above) still permanently squats its `BlockchainName` on the P-chain ledger — you cannot reuse the name even after fixing the genesis. Work-around used on zoo testnet/devnet: issue under a throwaway name (`ZOOTEST123` / `ZOODEVTEST123`), then rewrite the krakend gateway endpoint so `/ext/bc/zoo/rpc` → `/ext/bc//rpc`. The route `/ext/bc//rpc` is registered by `luxfi/node/chains/manager.go` *only* on successful VM init — broken chains never claim the route, so gateway-side rewrite is sufficient. ### Active versions - Repo: `v1.9.6` (next: `v1.9.7`). - Pinned by: `luxfi/node v1.26.10`. - Pulls: `luxfi/consensus v1.23.4+` (for `ChainSecurityProfile` definition + `ComputeHash`), `luxfi/crypto v1.18.4+` (mldsa65 keygen). ### Cross-repo dependencies - `luxfi/consensus/config` → `ChainSecurityProfile`, `Resolve`, `ComputeHash`. - `luxfi/crypto/pq/mldsa/mldsa65` → validator key generation. - `luxfi/node/genesis/builder` → consumes this repo's JSON config and converts types (string → ids.NodeID, uint64 → time.Duration). ### Where to look for X - ChainSecurityProfile pin: `pkg/genesis/security_profile.go` - Profile hash verification: `pkg/genesis/security_profile.go:Resolve` - HD branch hardening: `pkg/wallet/hd/*.go` - Per-network configs: `configs/{mainnet,testnet,devnet,local}/` ### Open follow-ups - Mainnet/testnet/devnet genesis JSONs still reference the `legacy-compat` profile while operators migrate validator keys. The strict-PQ profile is encoded but not yet the default genesis pin. --- ## Canonical Requirements Every Lux chain genesis MUST satisfy these, or block import / consensus will fail: | Requirement | Mainnet C-Chain | How to verify | |---|---|---| | chainId | 96369 (NOT 1) | `jq -r .chainId configs/mainnet/cchain.json` | | Genesis hash | `0x3f4fa2a0b0ce089f52bf0ae9199c75ffdd76ecafc987794050cb0d286f1ec61e` | `geth init --datadir /tmp/v configs/mainnet/cchain.json 2>&1 \| grep "genesis hash"` | | State root | `0x2d1cedac263020c5c56ef962f6abe0da1f5217bdc6468f8c9258a0ea23699e80` | `jq -r .stateRoot configs/mainnet/cchain.json` | | Warp precompile in alloc | `0200000000000000000000000000000000000005` `nonce:0x1` `code:0x01` | `jq '.alloc."0200000000000000000000000000000000000005"' configs/mainnet/cchain.json` | | `warpConfig.blockTimestamp` | `1730446786` (== genesis ts `0x672485c2`) | must equal genesis timestamp | | Treasury | `0x9011E888251AB053B7bD1cdB598Db4f9DEd94714` = 2T LUX | `jq '.alloc."0x9011…"' configs/mainnet/cchain.json` | | File determinism | sorted, sha256 matches Canonical Genesis Checksums table below | `shasum -a 256 configs/mainnet/cchain.json` | If genesis hash drifts → check `cChainGenesis` in `genesis.json` is the literal canonical `cchain.json` content. Common drift: `chainId=1` + missing warp = wrong-network template. ## Networks ### C-Chain (Primary Network) | Network | Network ID | Chain ID | Genesis Hash | Treasury | |---------|------------|----------|--------------|----------| | Mainnet | 1 | 96369 | `0x3f4fa2a0b0ce089f52bf0ae9199c75ffdd76ecafc987794050cb0d286f1ec61e` | 2T LUX | | Testnet | 2 | 96368 | `0xfc909f7e992d9cb91485f114f6d333f3823a12f2c72bbf51ed2c8eea749b2d2e` | 2T LUX | | Devnet | 3 | 96367 | `0x836f6053473e4331bb347afc45b641f12075c63a302f4e56e64239a3ba4acd4b` | 2T LUX | | Local | 1337 | 1337 | - | 2T LUX | > **Historical note**: testnet was `0x1c5fe37764b8bc146dc88bc1c2e0259cd8369b07a06439bcfa1782b5d4fb0995` > and devnet was `0x53fe8be293555d20de41847f96081f4e8beca1ee2c206999ffbf7c70e497cf43` > before commits `2bf1ca3` (Shanghai/Cancun/Prague activated at genesis) and > `d3cbd78` (gasLimit bumped to 1B). Both networks were "block 0 fresh" > with no committed historical state, so the hash update is intentional; > rollouts after 2026-05-21 use the new hashes. Mainnet hash is unchanged > (its cChainGenesis is locked by the 1.08M-block historical chain). ### Primary-Network Letter Chains (all baked into genesis) Every primary network ships **all 10 letter-chain shards**, so every chain spawns at startup — no post-launch `CreateBlockchainTx` required. The shard schema is `{x,c,d,q,a,b,t,z,g,k}chain.json` (P-Chain is implicit; it is the primary network and carries the validator set + chain registry). Letter aliases (LP-134 user-facing naming): **F-Chain ≡ T-Chain** (threshold FHE encrypted compute), **M-Chain ≡ K-Chain** (KMS + MPC topology). The canonical letter on disk and in VM IDs is T / K; F / M are aliases registered on the same VM IDs (`builder.TChainAliases`, `builder.KChainAliases`). | Letter | VM | Mainnet | Testnet | Devnet | Localnet | |--------|--------------|---------|---------|--------|----------| | X | XVM (UTXO) | — | — | — | — | | C | EVM | 96369 | 96368 | 96367 | 31337 | | D | DexVM | 96469 | 96468 | 96470 | 31447 | | Q | QuantumVM | 96569 | 96568 | 96570 | 31557 | | A | AIVM | 96669 | 96668 | 96670 | 31667 | | B | BridgeVM | 96769 | 96768 | 96770 | 31777 | | T (=F) | ThresholdVM | 96869 | 96868 | 96870 | 31887 | | Z | ZKVM | 96969 | 96968 | 96970 | 31997 | | G | GraphVM | 97069 | 97068 | 97070 | 32107 | | K (=M) | KeyVM | 97169 | 97168 | 97170 | 32217 | Pattern: each letter's mainnet ID is `96369 + 100*Δ_from_C`; testnet = mainnet-1, devnet = mainnet+1 (mirrors the C-Chain triple). Localnet uses a separate `31337 + 110*Δ` series. All 36 EVM chain IDs are pairwise distinct so a misrouted transaction cannot be replayed against the wrong chain. The contract that every primary network ships all 10 shards is locked by `configs.TestGetGenesis_AllPrimaryChainsBakedIn` — removing a chain on mainnet/testnet/devnet/localnet is now a load-bearing test edit, not a silent operator switch. ### Application Chains | Chain | Mainnet ID | Testnet ID | Devnet ID | Treasury | |-------|-----------|-----------|-----------|----------| | Zoo | 200200 | 200201 | 200202 | 2T ZOO | | SPC | 36911 | 36910 | 36912 | 1B SPC | | Hanzo | 36963 | 36962* | 36964 | 1B AI | | Pars | 494949 | 494950 | 494951 | 2T PARS | *Note: Hanzo testnet was deployed with chain ID 36964 (devnet ID) due to a deployment error. The intended ID is 36962. ### Deployed Genesis Hashes (All Chains) | Chain | Mainnet | Testnet | Devnet | |-------|---------|---------|--------| | C-Chain | `0x3f4fa2a...1ec61e` | `0x53fe8be...97cf43` | `0x53fe8be...97cf43` | | Zoo | `0x7c548af...14933` | `0x0652fb2...d1979` | `0x0652fb2...d1979` | | SPC | `0x4dc9fd5...cfac8` | `0x210fcc1...0b692` | `0x0652fb2...d1979` | | Hanzo | `0x6cf786a...48e67` | `0x6cf786a...48e67` | `0x6cf786a...48e67` | | Pars | `0xa32921a...b2f34` | `0xa32921a...b2f34` | `0xa32921a...b2f34` | ## Genesis Treasury All networks use the same production treasury address: ``` Address: 0x9011E888251AB053B7bD1cdB598Db4f9DEd94714 Balance: 2,000,000,000,000,000,000,000,000,000,000 wei (2T LUX) Hex: 0x193e5939a08ce9dbd480000000 ``` ## Directory Structure ``` configs/ ├── mainnet/ │ ├── cchain.json # C-Chain genesis (chain ID 96369) │ ├── pchain.json # P-Chain genesis (ProtocolVM) │ ├── network.json # Network ID, message, startTime │ └── bootstrappers.json # Bootstrap nodes ├── testnet/ │ ├── cchain.json # C-Chain genesis (chain ID 96368) │ └── genesis.json ├── devnet/ │ └── cchain.json ├── local/ │ ├── cchain.json │ └── genesis.json ├── zoo-{mainnet,testnet,devnet}/ │ └── genesis.json # Zoo (200200/200201/200202) ├── spc-{mainnet,testnet,devnet}/ │ └── genesis.json # SPC (36911/36910/36912) ├── hanzo-{mainnet,testnet,devnet}/ │ └── genesis.json # Hanzo (36963/36962/36964) └── pars-{mainnet,testnet,devnet}/ └── genesis.json # Pars (494949/494950/494951) ``` ## C-Chain Configuration ### Mainnet (96369) ```json { "chainId": 96369, "gasLimit": 12000000, "targetBlockRate": 2, "minBaseFee": 25000000000, "stateRoot": "0x2d1cedac263020c5c56ef962f6abe0da1f5217bdc6468f8c9258a0ea23699e80", "baseFeePerGas": "0x5d21dba00" } ``` ### Network Parameters | Parameter | Mainnet | Testnet | Devnet | Local | |-----------|---------|---------|--------|-------| | Block Rate | 2s | 2s | 1s | 1s | | Gas Limit | 12M | 12M | 20M | 15M | | Min Base Fee | 25 gwei | 25 gwei | 1 gwei | 1 gwei | | Chain ID | 96369 | 96368 | 96367 | 1337 | ### Warp Precompile (Required for Genesis Hash) Both mainnet and testnet C-Chain genesis MUST include the warp precompile: ```json { "alloc": { "0200000000000000000000000000000000000005": { "balance": "0x0", "nonce": "0x1", "code": "0x01" }, "0x9011E888251AB053B7bD1cdB598Db4f9DEd94714": { "balance": "0x193e5939a08ce9dbd480000000" } } } ``` This produces the canonical state root: `0x2d1cedac263020c5c56ef962f6abe0da1f5217bdc6468f8c9258a0ea23699e80` ### Upgrade Timestamps C-Chain protocol upgrades activated Dec 25, 2024 @ 4:20pm UTC (timestamp 1735143600): ```json { "evmTimestamp": 0, "durangoTimestamp": 0, "quasarTimestamp": 1735143600, "fortunaTimestamp": 1735143600, "graniteTimestamp": 1735143600 } ``` ## Genesis Package (`pkg/genesis/`) ### Core Types ```go // Config - Top-level genesis configuration type Config struct { NetworkID uint32 Allocations []Allocation StartTime uint64 InitialStakeDuration uint64 InitialStakeDurationOffset uint64 InitialStakedFunds []ids.ShortID InitialStakers []Staker CChainGenesis string Message string } // Staker - Initial validator type Staker struct { NodeID ids.NodeID RewardAddress ids.ShortID DelegationFee uint32 Signer *ProofOfPossession Weight uint64 StartTime uint64 EndTime uint64 } // Allocation - Genesis allocation type Allocation struct { EVMAddr ids.ShortID `json:"evmAddr"` UTXOAddr ids.ShortID `json:"utxoAddr"` InitialAmount uint64 `json:"initialAmount"` UnlockSchedule []LockedAmount `json:"unlockSchedule"` } ``` **Address naming — `EVMAddr` + `UTXOAddr`. Always.** - `EVMAddr` (Go) ↔ `evmAddr` (JSON) — address on EVM-modeled chains (C and other EVM letter chains). - `UTXOAddr` (Go) ↔ `utxoAddr` (JSON) — address on UTXO-modeled chains (P, X; share the same 20-byte ShortID; bech32 prefix differentiates chain). Never use `ETHAddr` / `LUXAddr` / `ethAddr` / `luxAddr` in new code. The fields name the *chain model* (EVM, UTXO), not a specific implementation we happen to be wire-compatible with. The one exception is `ParseETHAddress(string) ids.ShortID` — that's the *input* description (parses an Ethereum-format hex string like `0x...`). The function output binds to `EVMAddr`. ### Bech32 Address Format Addresses use chain prefix + bech32 encoding: ``` Format: {chain}-{hrp}1{data}{checksum} Example: P-lux1ck0t9h5u7jvvzhx29n99guqjsfkpzt67wgx7wg Chain Prefixes: - P-lux1... (P-Chain — ProtocolVM) - X-lux1... (X-Chain/Exchange) - C-0x... (C-Chain/EVM hex) ``` **Important**: The bech32 checksum is computed using only the HRP ("lux"), not the chain prefix ("P-lux"). ## CLI Tools ### genesis (`cmd/genesis/`) Generate genesis configurations: ```bash # Generate from mnemonic LUX_MNEMONIC="test test..." ./genesis -network-id 96369 -validators 5 -output genesis.json # From existing keys ./genesis -network mainnet -keys-dir ~/.lux/keys -output genesis.json ``` ### extract-genesis (`cmd/extract-genesis/`) Extract genesis from existing chain data: ```bash ./extract-genesis -chaindata /path/to/chaindata -output cchain.json ``` ## State Repository Integration Historical blockchain state is maintained separately in [luxfi/state](https://github.com/luxfi/state). ### Available State Data | Network | Blocks | RLP Size | Location | |---------|--------|----------|----------| | Lux Mainnet | 1,082,780 | 1.2 GB | `rlp/lux-mainnet/lux-mainnet-96369.rlp` | | Lux Testnet | 218 | 695 KB | `rlp/lux-testnet/lux-testnet-96368.rlp` | | Zoo Mainnet | 799 | 1.3 MB | `rlp/zoo-mainnet/zoo-mainnet-200200.rlp` | | Zoo Testnet | 84 | 156 KB | `rlp/zoo-testnet/zoo-testnet-200201.rlp` | | SPC Mainnet | 11 | 7.8 KB | `rlp/spc-mainnet/spc-mainnet-36911.rlp` | ### Import Workflow ```bash # Clone repos git clone https://github.com/luxfi/genesis git clone https://github.com/luxfi/state # Initialize with genesis geth init --datadir /tmp/lux genesis/configs/mainnet/cchain.json # Import blocks geth import --datadir /tmp/lux state/rlp/lux-mainnet/lux-mainnet-96369.rlp ``` ### LuxEVM Header Formats State repo RLP uses LuxEVM header encoding: | Fields | Format | Usage | |--------|--------|-------| | 16 | Genesis block | No optional fields | | 17-19 | Post-genesis | ExtDataHash, ExtDataGasUsed, BlockGasCost | **Coreth field order** (positions 15+): ``` 15: ExtDataHash (common.Hash - value type, required) 16: BaseFee (*big.Int) 17: ExtDataGasUsed (*big.Int) 18: BlockGasCost (*big.Int) ``` ## Mainnet Validators | Node | NodeID | P-Chain Address | |------|--------|-----------------| | 1 | NodeID-FrtEjhat6RUqjEWCJgYZKqBaxY2Woyy5G | P-lux1ck0t9h5u7jvvzhx29n99guqjsfkpzt67wgx7wg | | 2 | NodeID-9hq49qGVZN7M7tXxdpF3AqptQGdmPCFnQ | P-lux1dclruwcn9ug8u0jjk3ukh676jr3lsy4er9m3l5 | | 3 | NodeID-8osEnSC4LQFdG1LMit12CBsE6BfKGHNAw | P-lux1qdv9zns0gpfesw0h28jqp2up6h77du2damqf88 | | 4 | NodeID-MrdgTgPuddyo7anomKr4akMcoKzVKcgbG | P-lux1jjs4nx7ul4d6pnsjtpv2khzu8p4yctegvass46 | | 5 | NodeID-Mgd5yHs4pe6qRjkBcW5Y7oqHA51j4afcC | P-lux1970ngvf6s6rsndrkvjzr6lfvf2tdl30529c435 | ## Token Decimals ```go // P-Chain/X-Chain: 6 decimals (microLUX as base unit) const ( MicroLux uint64 = 1 // 0.000001 LUX MilliLux uint64 = 1_000 // 0.001 LUX Lux uint64 = 1_000_000 // 1 LUX ) // C-Chain: 18 decimals (wei, standard EVM) // 1 LUX = 10^18 wei on C-Chain ``` ## Verification ### Genesis Hash Check ```bash # Verify mainnet C-Chain genesis geth init --datadir /tmp/verify configs/mainnet/cchain.json 2>&1 | grep "genesis hash" # Expected: 0x3f4fa2a0b0ce089f52bf0ae9199c75ffdd76ecafc987794050cb0d286f1ec61e # Verify state root cat configs/mainnet/cchain.json | jq -r '.stateRoot' # Expected: 0x2d1cedac263020c5c56ef962f6abe0da1f5217bdc6468f8c9258a0ea23699e80 ``` ### Network ID Verification ```bash cat configs/mainnet/network.json | jq '.networkID' # Expected: 96369 cat configs/testnet/network.json | jq '.networkID' # Expected: 96368 ``` ## Fortuna Timestamp Fix (2025-12-25) ### Problem Block import failed with gas limit mismatch when importing Zoo chain blocks: ``` invalid gas limit: have 12000000, want 10000000 ``` ### Root Cause Zoo genesis files had `fortunaTimestamp: 0` which activates Fortuna from block 0. Fortuna uses dynamic gas limits via `state.MaxCapacity()` returning 10M, but original blocks had 12M gas limit (Cortina rules). ### Solution Set far-future timestamps for the pre-Quasar Edition upgrades that the imported Zoo blocks predate (the `quasarTimestamp`/`fortunaTimestamp`/ `graniteTimestamp` JSON fields are preserved verbatim because they are the wire-format identifiers consumed by luxfi/evm; only the prose label moves to "Quasar Edition upgrades"): ```json { "quasarTimestamp": 253399622400, "fortunaTimestamp": 253399622400, "graniteTimestamp": 253399622400 } ``` ### Files Updated - `zooai/universe/configs/genesis/mainnet/genesis.json` (moved from `luxfi/genesis/configs/zoo-mainnet/` in Task #109) - `zooai/universe/configs/genesis/testnet/genesis.json` (moved from `luxfi/genesis/configs/zoo-testnet/` in Task #109) ### Verified Block Counts (2025-12-28) | Network | Chain ID | Blocks | Genesis Hash | |---------|----------|--------|--------------| | Lux Mainnet | 96369 | **1,082,780** | `0x3f4fa2a0b0ce089f52bf0ae9199c75ffdd76ecafc987794050cb0d286f1ec61e` | | Lux Testnet | 96368 | **218** | `0x1c5fe37764b8bc146dc88bc1c2e0259cd8369b07a06439bcfa1782b5d4fb0995` | | Zoo Mainnet | 200200 | **799** | `0x7c548af47de27560779ccc67dda32a540944accc71dac3343da3b9cd18f14933` | | Zoo Testnet | 200201 | **84** | `0x0652fb2fde1460544a5893e5eba5095ff566861cbc87fcb1c73be2b81d6d1979` | | SPC Mainnet | 36911 | **11** | `0x4dc9fd5cf4ee64609f140ba0aa50f320cadf0ae8b59a29415979bc05b17cfac8` | --- ## Canonical Genesis Checksums (SHA256) **IMPORTANT**: All genesis files are sorted alphabetically by key for determinism. These checksums are the canonical reference - if they don't match, the file has been modified. | File | SHA256 | |------|--------| | `mainnet/cchain.json` | `968e9f3cd19a9b88ca157db3894622272ded02f0f184b5386493ff55897001be` | | `testnet/cchain.json` | `ba211e1bbbd7807c2224d240628facb2dfb6c2d6cde2e274eb881a57609ed038` | | `zoo-mainnet/genesis.json` | `14c01e8bb5ac13144a3730c695847d53506647efbaada3f3240a16e7b10684f7` | | `zoo-testnet/genesis.json` | `b8eea8c6b3276ebadce7e8ef9296bc14b56990ae04cd200a4663f5af21193534` | | `zoo-devnet/genesis.json` | `4890a40fe7891722c90efb728f11b14aeef9795c2b897eb0140e1e0ae3b6254c` | | `spc-mainnet/genesis.json` | `9c01115559556fc245d4993b193889370bd99edd22a7fa1e9e3d7ddafbb63535` | | `spc-testnet/genesis.json` | `af12bb81dd9abce26b7a311f00fa2ac7f5adfb996e698b9f473252199f747b2c` | | `spc-devnet/genesis.json` | `317d54ac7846b0f174964552b4949d858072f6ffbc37f6c10092e01d595ce46f` | | `hanzo-mainnet/genesis.json` | `adae3c441b34db937dbcd961450bff5bcabd388a5479fe9ba7380ef61f083637` | | `hanzo-testnet/genesis.json` | `a2d00685bf7f414815dc3579552e19045183428c520f4f5b23a6726cf4002c32` | | `hanzo-devnet/genesis.json` | `1c489d29c08857696909f029a1b2cda554e059e86c630ae64f35a5243f4bd25c` | | `pars-mainnet/genesis.json` | `ca35306a73f4cbfeccc8018b71596b122f698a23f3c038993a2ad34ca315e539` | | `pars-testnet/genesis.json` | `9d7ff05187bb2570d2a1af8ccfa41a99dfaf8b56558decf127209ac6d5faec85` | | `pars-devnet/genesis.json` | `3fc55f6be7b46dd6955ab2ec95186a4aa7da13991650909cb5f9ecbaa51b06c7` | ### Verify Checksum ```bash cd ~/work/lux/genesis/configs shasum -a 256 zoo-mainnet/genesis.json # Should output: 241fd0209253e7a5a04c55c7a6f4f0ba864a83dd9840c4969d5a1b5b5f6c3366 ``` ### Re-sort if Modified ```bash # If file was modified, re-sort it: jq -S '.' genesis.json > genesis.sorted.json && mv genesis.sorted.json genesis.json ``` --- ## Genesis Hash Fix (2025-12-28) ### Problem Mainnet genesis hash was computing as `0xc3069db32ef986d8e287458e44066eb04205648e602dc2fede561c424a6516de` instead of the expected `0x3f4fa2a0b0ce089f52bf0ae9199c75ffdd76ecafc987794050cb0d286f1ec61e` from historical RLP blocks. ### Root Cause The `warpConfig.blockTimestamp` was set to 0, which caused `ApplyPrecompileActivations()` in coreth to add the warp precompile to genesis state BEFORE the alloc was applied. When warp wasn't in alloc, this changed the state trie and produced a different genesis hash. **Key insight from `coreth/core/genesis.go:271`:** ```go // ApplyPrecompileActivations runs FIRST (line 271) ApplyPrecompileActivations(g.Config, nil, blockContext, statedb) // Then alloc is applied (lines 276-283) for addr, account := range g.Alloc { // This overwrites precompile if in alloc, leaves it if not } ``` ### Solution The original mainnet genesis was created with warp precompile IN the alloc section: ```json { "alloc": { "0200000000000000000000000000000000000005": { "balance": "0x0", "nonce": "0x1", "code": "0x01" } }, "warpConfig": { "blockTimestamp": 1730446786, "quorumNumerator": 67, "requirePrimaryNetworkSigners": false } } ``` The `warpConfig.blockTimestamp` equals the genesis timestamp (`0x672485c2` = 1730446786), meaning warp is activated at genesis. Having warp in both alloc AND warpConfig ensures consistent state. ### Files Restored - `configs/mainnet/cchain.json` - Restored from git with warp in alloc - `configs/mainnet/genesis.json` - Updated cChainGenesis to match ### Verification ```bash # Start mainnet netrunner start --networks mainnet # Verify genesis hash curl -X POST -H 'Content-Type: application/json' \ --data '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x0",false],"id":1}' \ http://127.0.0.1:9630/ext/bc/C/rpc | jq '.result.hash' # Expected: "0x3f4fa2a0b0ce089f52bf0ae9199c75ffdd76ecafc987794050cb0d286f1ec61e" # Verify warp precompile in state curl -X POST -H 'Content-Type: application/json' \ --data '{"jsonrpc":"2.0","method":"eth_getCode","params":["0x0200000000000000000000000000000000000005","0x0"],"id":1}' \ http://127.0.0.1:9630/ext/bc/C/rpc | jq '.result' # Expected: "0x01" ``` --- ## Known Issues ### Documentation Discrepancies 1. **Network IDs**: Some older docs reference Network ID 1/2 instead of 96369/96368 2. **File paths**: Docs may reference `chain.rlp.gz` but actual files are `{network}-{chainid}.rlp` 3. **Block counts**: Documentation may be outdated - verify against actual RLP files ### State Repo Sync The state repo should be periodically updated with: - Latest block exports - Updated metadata.json files - Corrected documentation --- ## RLP Import via luxd `--import-chain-data` End-to-end auto-import of historical chain data on luxd startup. Replaces the prior geth-sidecar workflow. ### Flow 1. `luxd --import-chain-data=` (existing flag, was unwired). 2. `node/config/config.go` *config bridge* injects `import-chain-data` into `nodeConfig.ChainConfigs["C"].Config` JSON map. Merges with any existing C-Chain config. 3. EVM plugin reads `vm.config.ImportChainData` in `Initialize()` after `initializeChain()` returns. If non-empty, calls `importBlocksFromFile` (same code path as `admin_importChain` RPC). 4. RLP stream decoded in batches of 2,500 blocks. State trie committed every `CommitInterval` (4,096) blocks; `acceptedBlockDB` updated atomically with each commit so restart-safe. 5. Final state commit + last-accepted update at end-of-stream. ### Required cChainGenesis (NON-NEGOTIABLE) `genesis.json` `cChainGenesis` MUST be the canonical mainnet config: - `chainId`: 96369 (NOT 1 — chainId 1 in cChainGenesis means genesis.json was overwritten with a wrong-network template; restore from `cchain.json`) - Warp precompile in `alloc`: address `0200000000000000000000000000000000000005`, `nonce: "0x1"`, `code: "0x01"` - `warpConfig.blockTimestamp`: 1730446786 (== genesis timestamp 0x672485c2) If any of these drift, the EVM computes a non-canonical genesis hash (commonly `0xcd5083cb…`) and RLP block 1's `parentHash` won't match → import fails with `batch 0: block 1 parent mismatch - expected genesis 0xcd…, got 0x3f4fa2a0…`. Restore from canonical: ```bash python3 -c "import json canon = json.load(open('configs/mainnet/cchain.json')) g = json.load(open('configs/mainnet/genesis.json')) g['cChainGenesis'] = json.dumps(canon, separators=(',', ':'), sort_keys=True) json.dump(g, open('configs/mainnet/genesis.json', 'w'), indent=2, sort_keys=True)" ``` ### Wiring sites (when re-implementing) | Layer | File | What | |-------|------|------| | Flag | `node/config/keys.go` `ImportChainDataKey` | Already exists | | Flag | `node/config/flags.go:370` | Already exists | | Bridge | `node/config/config.go:2012-2028` | NEW: inject into `chainConfigs["C"]` after `getChainConfigs` | | Plugin config | `evm/plugin/evm/config/config.go` `Config.ImportChainData` | NEW: matches JSON key `import-chain-data` | | Plugin init | `evm/plugin/evm/vm.go` `Initialize()` post-`initializeChain` | NEW: calls `importBlocksFromFile` | | Import logic | `evm/plugin/evm/admin_api.go:220` `importBlocksFromFile` | Pre-existing — used by `admin_importChain` | ### macOS gotcha (kills luxd silently) After `cp` of the luxd binary to a new path, macOS gatekeeper can SIGKILL on launch (exit 137, no output). The provenance attribute (`com.apple.provenance`) plus an invalidated ad-hoc signature is the cause. Fix: ```bash codesign --force --sign - ~/work/lux/node/build/luxd codesign --force --sign - ~/work/lux/node/build/plugins/* ``` ### Plugin filename / VM ID The Lux EVM plugin has one canonical VM ID for both C-Chain and other EVM chains: ``` mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6 ``` This is `CB58(ids.ID{'e','v','m'})` per `luxfi/constants.EVMID`. luxd's chain manager, the lux-operator, and `luxfi/cli` all reference this one ID. Install the plugin binary at `~/.lux/plugins/mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6` — no other filename, no aliases. ### Verified output (mainnet) ``` read last accepted hash=0x3f4fa2a0b0ce089f52bf0ae9199c75ffdd76ecafc987794050cb0d286f1ec61e height=0 Loaded most recent local header hash=0x3f4fa2a0… Initializing snapshots headHash=0x3f4fa2a0… headRoot=0x2d1cedac263020c5c56ef962f6abe0da1f5217bdc6468f8c9258a0ea23699e80 Auto-importing chain data at startup path=…/lux-mainnet-96369.rlp ImportChain: inserting batch batch=0 blocks=2500 firstNum=1 ImportChain: batch done batch=0 imported=2500 height=2500 … ``` Throughput: ~550 blocks/sec early, ~150 blocks/sec by ~100k blocks (state-trie growth). 1.08M blocks → ~60-90 min wall time on M-series. ---