Documentation
¶
Overview ¶
Command createchaintx is the focused, immediate-unblock tool for registering the 5 brand L2 EVMs (hanzo, zoo, pars, spc, osage) on a Quasar-era P-Chain.
Decoupled from luxfi/cli: this tool does not call info.getBlockchainID(alias=X) anywhere — it goes through luxfi/node/wallet/network/primary.MakeWallet which fail-softs to a P-only XCTX (BlockchainID = ids.Empty) when the network has no X-Chain registered. That's the actual unblock — every other path you might hit in luxfi/cli's PublicDeployer.loadWallet currently crashes because the upstream sdk/wallet/primary still tries to look up X first.
What this tool does, end-to-end:
Loads a BIP-39 mnemonic from one of three sources, in order of priority: a. --mnemonic-file=<path> (raw file, mnemonic is the only content) b. LUX_MNEMONIC env var c. KMS via env vars KMS_ENDPOINT + KMS_TOKEN + KMS_ORG, fetching the secret at path lux/<env>/staking named `mnemonic`: GET ${KMS_ENDPOINT}/v1/kms/orgs/<org>/secrets/lux/<env>/staking/mnemonic
Derives a single secp256k1 funding key on the canonical Lux BIP-44 UTXO path m/44'/9000'/0'/0/<index> (purpose=44', coin_type=9000', account=0', change=0, leaf=<index>, default index=5 → first non-staking-locked allocation slot per the mainnet genesis layout). 9000 is the Lux/Avalanche BIP-44 coin type — do not confuse with 96369, which is the Lux mainnet EVM chainID and never appears in a derivation path. Override with --index to use a different funded allocation slot.
Distinct paths exist for other key purposes — they are NOT this funding key: * device Lux key (Lux-internal hardened): m/44'/9000'/<nid>'/1'/<i>' * device PQ key (ML-DSA-65 staking): m/44'/9000'/<nid>'/0'/<i>' where <nid> is the primary-network ID (1/2/3/1337), NOT an EVM chainID.
For each of the 5 brand specs, loads the canonical brand genesis bytes from disk (paths are not relative to --configs-dir; the tool ships a compiled-in canonical mapping per brand-genesis-homes.md), then: a. IssueCreateNetworkTx(owner) → per-chain validator network b. IssueCreateChainTx(networkID, genesis, vmID, fxIDs=[], chainName=brand) Skips both steps if a chain with chainName=brand already exists (the idempotency contract — re-running this tool is safe).
Emits JSON of produced blockchain IDs to stdout (or --output=<path>).
With --apply-aliases, writes a kubectl-ready Patch JSON that updates the `luxd-chain-aliases` (or `chain-aliases`) ConfigMap in namespace lux-<env> with the new {blockchainID: [brand]} mapping.
The tool deliberately omits AddChainValidatorTx, bootstrap-wait, EVM heartbeat, and eth_blockNumber probing — those are the bootstrap-chain concerns, not the immediate-unblock concerns. Once the chains are registered on P-chain, the running luxd will pick them up on the next roll (after the chain-aliases CM is updated and StatefulSet is rolled).
Build:
cd ~/work/lux/genesis/cmd && GOWORK=off go build -o /tmp/createchaintx ./createchaintx/
Example invocations:
# Mainnet, mnemonic in a local file, write output to /tmp/result.json createchaintx \ --uri=https://api.lux.network \ --env=mainnet \ --mnemonic-file=/tmp/lux-master.mnemonic \ --output=/tmp/result.json # Devnet, mnemonic from KMS, also emit aliases patch for kubectl apply export KMS_ENDPOINT=https://kms.hanzo.ai export KMS_TOKEN=... export KMS_ORG=lux createchaintx \ --uri=http://luxd-0.lux-devnet.svc.cluster.local:9650 \ --env=devnet \ --output=/tmp/result.json \ --apply-aliases=/tmp/aliases-patch.json