Update prose descriptions in README and LLM.md to use "chain" or "L2" instead of "subnet". Preserves API endpoint paths, JSON field names, CLI subcommand names, genesis config keys, Go struct fields, and deprecatedFlagsSupport.json backward compatibility mappings.
40 KiB
Lux Netrunner - AI Assistant Knowledge Base
Last Updated: 2026-01-07 Project: Lux Netrunner Organization: Lux Network Documentation Score: 85/100
Project Overview
Lux Netrunner is a powerful network orchestration and testing framework for blockchain development. It provides comprehensive tools for creating, managing, and testing multi-node blockchain networks with support for custom VMs, chains (L2 blockchains), and complex network topologies.
Essential Commands
Development
# Build from source
./scripts/build.sh
# Run tests
go test ./...
# Run E2E tests
./scripts/tests.e2e.sh
# Install binary
curl -sSfL https://raw.githubusercontent.com/luxfi/netrunner/main/scripts/install.sh | sh -s
Basic Operations
# Start RPC server
netrunner server --port=":8080" --grpc-gateway-port=":8081"
# Start network
netrunner control start --number-of-nodes=5 --node-path=/path/to/luxd
# Check health
netrunner control health
# Get status
netrunner control status
# Save snapshot
netrunner control save-snapshot snapshot-name
# Save hot snapshot (no node stop)
netrunner control save-hot-snapshot snapshot-name
# Load snapshot
netrunner control load-snapshot snapshot-name
Architecture
Core Components
- RPC Server: gRPC server with REST gateway for network control
- Network Manager: Orchestrates node lifecycle and network topology
- Node Process: Wrapper around blockchain node binaries
- Snapshot Manager: State persistence and recovery
- Test Framework: Comprehensive testing utilities
Supported Engines
- Lux - Native Lux blockchain (primary)
- Geth - Ethereum nodes
- Optimism - Layer 2 scaling solution
- Eth2 - Ethereum 2.0 beacon chain
Key Interfaces
network.Network- Network management interfacenode.Node- Individual node controlNodeProcessCreator- Node process factoryapi.Client- API client interface
Key Technologies
- Language: Go 1.21+
- RPC: gRPC with REST gateway
- Documentation: Next.js with Fumadocs
- Testing: Go testing package, E2E test framework
- Build: Make, shell scripts
- Containerization: Docker support
Development Workflow
- Setup: Clone repo, install Go 1.21+
- Build: Run
./scripts/build.sh - Test: Run
go test ./...for unit tests - E2E Test: Run
./scripts/tests.e2e.sh - Documentation: Edit MDX files in
/docs/content/docs/ - Doc Build: Run
cd docs && pnpm build
Documentation Status (85/100)
✅ Completed Documentation
- Introduction - Comprehensive overview, quick start, API examples
- Network Orchestration - Complete network management guide
- Test Network Setup - Detailed setup instructions
- Configuration Reference - Enhanced with templates, multi-engine support
- Testing Scenarios - All testing patterns documented
- Performance Testing (NEW) - TPS benchmarking, load testing, reports
- Network Simulation (NEW) - Topologies, failures, chaos testing
❌ Missing Documentation
- gRPC/REST API reference
- Multi-network management guide
- Custom VM development tutorial
- Production deployment guide
Key Capabilities
Network Simulation
- Topologies: Star, Mesh, Hierarchical, Custom
- Failures: Random, Cascading, Byzantine, Partition
- Conditions: Latency, Bandwidth limits, Packet loss
- Resources: CPU/Memory/Disk I/O constraints
- Time: Fast-forward and slow-motion simulation
Performance Testing
- Metrics: TPS, BPS, Latency, Resource usage
- Load Types: Sustained, Burst, Gradual ramp
- Analysis: Real-time monitoring, HTML reports
- Optimization: Database tuning, network config
Configuration Management
- Hierarchy: Node → Network → File → Default
- Features: Hot-reload, Templates, Multi-engine
- Validation: Pre-flight checks, port availability
Recent Documentation Enhancements (2025-11-12)
New Documentation Files Created
-
performance-testing.mdx(1020 lines)- Transaction throughput testing
- Block production benchmarks
- Network scalability tests
- Resource monitoring
- Performance reports and CSV export
-
network-simulation.mdx(890 lines)- Network topology simulation
- Failure injection scenarios
- Byzantine behavior testing
- Network condition simulation
- Chaos engineering
Enhanced Documentation
configuration.mdx- Added 250+ lines:- Dynamic runtime configuration
- Configuration templates
- Multi-engine support
- Monitoring configuration
- Chaos engineering settings
Testing Patterns
Test Types Supported
- Unit Testing - Component validation
- Integration Testing - Multi-node consensus
- Performance Testing - Throughput and latency
- Chaos Testing - Failure injection
- Regression Testing - Snapshot-based
- Load Testing - Sustained and burst
Example Test Scenarios
// Performance test
TestTransactionThroughput()
TestBlockProductionRate()
TestNetworkScalability()
// Chaos test
SimulateNodeFailures()
SimulateNetworkPartition()
SimulateByzantineNode()
// Load test
TestSustainedLoad()
TestBurstLoad()
Best Practices
- Start Simple - Begin with basic scenarios
- Use Snapshots - Regular automated snapshots
- Monitor Everything - Enable metrics from start
- Test Incrementally - Gradual complexity increase
- Document Changes - Update LLM.md with discoveries
Common Issues and Solutions
Issue: Nodes exit with code 1
Solution: Check binary path, port availability, genesis configuration
Issue: Network partition doesn't heal
Solution: Ensure proper bootstrap node configuration
Issue: Low TPS in tests
Solution: Optimize consensus parameters, use in-memory DB
Future Work
Priority 1 (High)
- Complete gRPC API documentation
- Multi-network management guide
- Production deployment guide
Priority 2 (Medium)
- Custom VM development tutorial
- Bridge functionality docs
- Video tutorials
Priority 3 (Low)
- Performance cookbook
- Troubleshooting guide
- Interactive examples
Context for All AI Assistants
This file (LLM.md) is symlinked as:
.AGENTS.mdCLAUDE.mdQWEN.mdGEMINI.md
All files reference the same knowledge base. Updates here propagate to all AI systems.
Rules for AI Assistants
- ALWAYS update LLM.md with significant discoveries
- NEVER commit symlinked files (.AGENTS.md, CLAUDE.md, etc.) - they're in .gitignore
- NEVER create random summary files - update THIS file
- USE absolute paths when referencing files
- TEST documentation builds before claiming completion
Note: This file serves as the single source of truth for all AI assistants working on this project.
Local Network Deployment Status (2025-11-12)
Current Achievement
✅ Successfully deployed 5-node local network using direct luxd execution
- Network ID: 12345
- Binary: /Users/z/work/lux/node/build/luxd v1.20.1
- Data Directory: /tmp/lux-5node-final/
- Node Ports: 9650, 9660, 9670, 9680, 9690 (HTTP), 9651, 9661, 9671, 9681, 9691 (Staking)
Bootstrap Status
✅ P-Chain: All 5 nodes bootstrapped successfully
❌ X-Chain: Not bootstrapping (nodes not validators)
❌ C-Chain: Not bootstrapping (nodes not validators)
❌ Q-Chain: Not bootstrapping (nodes not validators)
Root Cause Analysis
Issue: Nodes are not configured as validators in genesis Error: "node is not a validator" when attempting to get uptime Impact: Only P-Chain can bootstrap. X, C, and Q chains require validator status to participate in consensus.
Solution Path
To achieve full 4-chain bootstrap, we need to:
- Generate genesis file with 5 pre-configured validators
- Extract node IDs and BLS keys from running nodes
- Include these node IDs in genesis validator set
- Restart network with validator-enabled genesis
Build Status
✅ Netrunner: Built successfully (/Users/z/work/lux/netrunner/bin/netrunner - 43MB)
✅ Lux-CLI: Built successfully (/Users/z/work/lux/cli/bin/lux - 96MB)
✅ Luxd Node: Built successfully (/Users/z/work/lux/node/build/luxd - 57MB)
Deployment Methods Attempted
- ❌ Netrunner Server/Client: 503 error, network terminated prematurely
- ❌ Lux-CLI: Corrupted snapshot, node3 stopped unexpectedly
- ✅ Direct luxd execution: Successful P-Chain bootstrap
Next Steps
- Create genesis tool or use existing
github.com/luxfi/genesispackage - Generate 5-validator genesis file
- Configure nodes with proper staking keys
- Restart network and verify <60s bootstrap for all 4 chains
- Build e2e tests for X, C, Q chain operations
Files Created/Modified
/tmp/deploy-network.sh- 5-node deployment script/tmp/lux-5node-final/- Network data directory with 5 nodes/tmp/start_5node_network.go- Attempted netrunner Go integration
Key Learnings
- P-Chain bootstraps without validator status (platform chain special case)
- X, C, Q chains require nodes to be in validator set
- Genesis must be created BEFORE node deployment for validator networks
- Direct luxd execution is most reliable for custom network configurations
Local Network Deployment Issues and Solutions (2025-11-12)
Critical Version/Release Issues Discovered
1. Version Mismatch Between Releases and Tags
Problem: Latest GitHub release (v1.14.0) doesn't match latest Git tag (v1.20.3)
- File:
/Users/z/work/lux/node/.github/workflows/release.yml - Impact: Users/tools download v1.14.0 binaries when expecting v1.20.3 code
- Root Cause: No automated GitHub release workflow when tags are pushed
- Solution: Created workflow to automatically create GitHub releases on tag push
2. Published v1.20.3 Missing Critical Code
Problem: v1.20.3 release tarball missing WarpSet/WarpValidator implementations
- Files Missing:
consensus/validator/validators.go(WarpSet, WarpValidator types)consensus/validator/validator.go(GetWarpValidatorSet methods)
- Impact: Code that compiles locally fails when users download release
- Verification: Release tarball extracted and verified missing implementations
- Solution: Created new v1.20.4 tag and release with complete code
3. lux-cli Hardcoded Wrong Versions
Problem: lux-cli downloads wrong binary versions
- File:
/Users/z/work/lux/cli/pkg/constants/constants.go - Issues:
- Default luxd version:
v2.0.0(doesn't exist) - NetRunner version:
v1.13.0(too old) - BuildDir:
.lux/bin/luxgo(should beluxfi)
- Default luxd version:
- Impact:
lux network startdownloads broken/wrong binaries - Solution:
DefaultNodeVersion = "v1.20.4" // was v2.0.0 DefaultNetRunnerVersion = "v1.20.4" // was v1.13.0 BuildDir = ".lux/bin/luxfi" // was luxgo
4. No Automated Release Process
Problem: Tags created but no GitHub releases published
- Missing: Automated workflow to:
- Build binaries for all platforms (darwin-amd64/arm64, linux-amd64/arm64)
- Create GitHub release with binaries attached
- Generate checksums and release notes
- Solution: Created
.github/workflows/release.ymlwith:- Trigger on tag push (v*)
- Multi-platform binary builds
- Automated release creation
- Checksum generation
Port Configuration Issues
Default Port Series Wrong
Problem: Code uses 964x series, should use 963x
- Files:
/Users/z/work/lux/netrunner/local/network.go- Node creation/Users/z/work/lux/netrunner/cmd/control/start/start.go- CLI defaults
- Expected Layout:
Node 1: HTTP=9630, Staking=9631 Node 2: HTTP=9640, Staking=9641 Node 3: HTTP=9650, Staking=9651 Node 4: HTTP=9660, Staking=9661 Node 5: HTTP=9670, Staking=9671 - Issue: Code was incrementing from 9650 (964x), not 9630 (963x)
- Solution: Changed
baseHTTPPortfrom 9650 to 9630 in network.go
Genesis Configuration Issues
1. Invalid Bech32 Address Checksums
Problem: Manual genesis.json has invalid address checksums
- Error Message:
invalid checksum (expected v3r5gtp, got 06g97jh) for "lux1w5f4p2cq7ajjpphny0k8fhkp3wr7a7ggv3r5gtp" - Root Cause: Manual address creation without proper Bech32 checksum calculation
- Files Affected: Any manually created
genesis.json - Solution: Use proper Bech32 encoding library:
import "github.com/luxfi/crypto/address" addr, err := address.Format("lux", hrp, publicKeyHash)
2. Missing Validator Configuration
Problem: Nodes not configured as validators in genesis
- Error: "node is not a validator" when querying uptime
- Impact:
- P-Chain bootstraps (doesn't require validator status)
- X, C, Q chains FAIL (require validator status for consensus)
- Required Fields in Genesis:
"initialStakers": [ { "nodeID": "NodeID-...", "rewardAddress": "lux1...", "delegationFee": 20000, "stakeAmount": 2000000000000000 } ] - Solution: Generate genesis with all 5 node IDs in validator set
3. Genesis Generation Tool Needed
Problem: No automated way to create valid genesis
- Manual Process Error-Prone:
- Calculate Bech32 checksums
- Format addresses correctly
- Set proper stake amounts
- Include all node IDs
- Solution Created:
/Users/z/work/lux/genesis/cmd/genesis-gen/main.go- Generates 5-validator genesis automatically
- Proper Bech32 address encoding
- Configurable network ID
- Pre-funded accounts for testing
- Outputs to stdout or file
Validator Setup Requirements
Bootstrap Chain Requirements
P-Chain (Platform Chain):
- ✅ Bootstraps WITHOUT validator status
- ✅ Can sync from network as non-validator
- Special case: platform chain manages validators
X-Chain (Asset Exchange):
- ❌ Requires validator status to participate
- ❌ Won't bootstrap without being in validator set
- Error: "node is not a validator"
C-Chain (Smart Contracts):
- ❌ Requires validator status to participate
- ❌ Won't bootstrap without being in validator set
- EVM chain requires consensus participation
Q-Chain (Quantum-Resistant):
- ❌ Requires validator status to participate
- ❌ Won't bootstrap without being in validator set
- New chain requires validator consensus
Validator Genesis Requirements
{
"initialStakers": [
{
"nodeID": "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg",
"rewardAddress": "lux1wst8jt3z3fm9ce0z6akj3266zmgccdp03hjlaj",
"delegationFee": 20000,
"stakeAmount": 2000000000000000
}
]
}
Critical Fields:
nodeID- From node's staking certificaterewardAddress- Bech32-encoded with correct checksumstakeAmount- Minimum 2000 LUX (2000000000000000 nLUX)delegationFee- Commission percentage (20000 = 20%)
Solutions Implemented This Session
1. Fixed lux-cli Version References
File: /Users/z/work/lux/cli/pkg/constants/constants.go
// Before
DefaultNodeVersion = "v2.0.0"
DefaultNetRunnerVersion = "v1.13.0"
BuildDir = ".lux/bin/luxgo"
// After
DefaultNodeVersion = "v1.20.4"
DefaultNetRunnerVersion = "v1.20.4"
BuildDir = ".lux/bin/luxfi"
2. Created GitHub Release Workflow
File: /Users/z/work/lux/node/.github/workflows/release.yml
- Triggers on tag push (v*)
- Builds for darwin-amd64, darwin-arm64, linux-amd64, linux-arm64
- Creates GitHub release with binaries
- Generates SHA256 checksums
- Auto-populates release notes
3. Fixed Default Port Configuration
File: /Users/z/work/lux/netrunner/local/network.go
// Changed base port from 9650 to 9630
const baseHTTPPort = 9630
const baseStakingPort = 9631
4. Created Genesis Generation Tool
File: /Users/z/work/lux/genesis/cmd/genesis-gen/main.go
- Generates valid Bech32 addresses
- Creates 5-validator genesis automatically
- Configurable network ID
- Pre-funded test accounts
- Proper stake amounts and fees
5. Created New v1.20.4 Release
Actions Taken:
- Tagged commit with complete WarpSet/WarpValidator code
- Pushed tag to GitHub:
git push origin v1.20.4 - Automated workflow created GitHub release
- Release includes all required implementations
Deployment Process (Updated)
Method 1: Netrunner (Recommended - Easiest)
# Build netrunner
cd /Users/z/work/lux/netrunner
go build -o bin/netrunner
# Start network (handles genesis automatically)
./bin/netrunner control start \
--number-of-nodes=5 \
--node-path=/Users/z/work/lux/node/build/luxd \
--blockchain-specs='[{"vm_name":"qemuvm","genesis":"/path/to/genesis.json"}]'
Method 2: Genesis-Gen Tool + Manual Deployment
# Generate valid genesis
cd /Users/z/work/lux/genesis
go run cmd/genesis-gen/main.go \
--network-id=12345 \
--num-validators=5 \
--output=/tmp/genesis.json
# Start nodes manually with generated genesis
/Users/z/work/lux/node/build/luxd \
--network-id=12345 \
--genesis=/tmp/genesis.json \
--http-port=9630 \
--staking-port=9631 \
--data-dir=/tmp/node1
Method 3: Lux-CLI (After Version Fixes)
# Build latest lux-cli with version fixes
cd /Users/z/work/lux/cli
go build -o bin/lux
# Start network (now downloads correct v1.20.4 binary)
./bin/lux network start
Manual Deployment Checklist
When deploying manually (without netrunner):
-
Generate Valid Genesis:
go run genesis-gen/main.go --network-id=12345 --num-validators=5 -
Verify Genesis Addresses:
- All addresses have correct Bech32 checksums
- InitialStakers array has 5 entries (one per node)
- Stake amounts ≥ 2000 LUX
-
Start Bootstrap Node First:
luxd --network-id=12345 --genesis=/tmp/genesis.json \ --http-port=9630 --staking-port=9631 \ --data-dir=/tmp/node1 \ --bootstrap-ips= --bootstrap-ids= -
Get Bootstrap Node ID:
curl http://localhost:9630/ext/info | jq .result.nodeID -
Start Remaining Nodes:
luxd --network-id=12345 --genesis=/tmp/genesis.json \ --http-port=9640 --staking-port=9641 \ --data-dir=/tmp/node2 \ --bootstrap-ips=127.0.0.1:9631 \ --bootstrap-ids=<node1-id> -
Verify All Chains Bootstrap:
# Should show isBootstrapped: true for P, X, C, Q curl http://localhost:9630/ext/info | jq
Error Messages and Solutions
"invalid checksum (expected..., got...)"
Cause: Manually created address without proper Bech32 encoding
Solution: Use github.com/luxfi/crypto/address package
import "github.com/luxfi/crypto/address"
addr, _ := address.Format("lux", hrp, pubKeyHash)
"node is not a validator"
Cause: Node's NodeID not in genesis initialStakers array Solution: Include node's NodeID in genesis validator set
"initialStakers": [{"nodeID": "NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg", ...}]
"X-Chain not bootstrapping"
Cause: Node not configured as validator (X-Chain requires consensus participation) Solution: Restart with validator-enabled genesis containing node's ID
"download failed: release not found"
Cause: lux-cli trying to download non-existent version (v2.0.0) Solution: Update constants.go with DefaultNodeVersion = "v1.20.4"
"503 Service Unavailable" from netrunner
Cause: Network terminated prematurely due to node startup failure Solution: Check node binary path, port availability, genesis validity
Files Modified This Session
lux-cli Version Fixes
/Users/z/work/lux/cli/pkg/constants/constants.go
Release Workflow
/Users/z/work/lux/node/.github/workflows/release.yml(created)
Port Configuration
/Users/z/work/lux/netrunner/local/network.go/Users/z/work/lux/netrunner/cmd/control/start/start.go
Genesis Tools
/Users/z/work/lux/genesis/cmd/genesis-gen/main.go(created)
Documentation
/Users/z/work/lux/netrunner/CLAUDE.md(this file)
Key Takeaways for Future Sessions
-
Always verify GitHub release matches Git tag - Code can compile locally but be missing in published releases
-
Use 963x port series - Not 964x (9630/9631 for first node)
-
Validator status is critical - Only P-Chain bootstraps without it; X/C/Q require validator genesis
-
Manual genesis is error-prone - Use genesis-gen tool or netrunner automatic generation
-
Test with fresh data dirs - Corrupted state causes mysterious failures
-
Bootstrap nodes must start first - Other nodes need bootstrap-ips/bootstrap-ids to connect
-
Version constants matter - Wrong version in lux-cli breaks binary downloads
-
Bech32 checksums are mandatory - Manual address creation always fails validation
Success Criteria for Local Network
✅ Achieved:
- 5-node network starts successfully
- P-Chain bootstraps (<60s)
- All nodes visible to each other
- HTTP APIs responding
❌ Remaining:
- X-Chain bootstrap (requires validator genesis)
- C-Chain bootstrap (requires validator genesis)
- Q-Chain bootstrap (requires validator genesis)
- Cross-chain transactions
- Consensus participation
To Complete: Deploy with genesis-gen tool that includes all 5 node IDs as validators
Genesis cChainGenesis Format Fix (2025-11-16)
Issue
Error: could not unmarshal genesis JSON: json: cannot unmarshal object into Go struct field UnparsedConfig.cChainGenesis of type string
Root Cause: The cChainGenesis field in netrunner's default genesis was an object instead of a JSON string.
Location: /Users/z/work/lux/netrunner/network/default/genesis.json
Fix Applied: Converted cChainGenesis object to JSON string:
import json
with open('network/default/genesis.json', 'r') as f:
genesis = json.load(f)
if isinstance(genesis['cChainGenesis'], dict):
genesis['cChainGenesis'] = json.dumps(genesis['cChainGenesis'], separators=(',', ':'))
with open('network/default/genesis.json', 'w') as f:
json.dump(genesis, f, indent=2)
Result: Nodes can now start successfully with netrunner default genesis
Peer Connectivity Requirements
Discovery: Bootstrap configuration in YAML manifests wasn't being passed to luxd command lines.
Required Flags:
--bootstrap-ips=127.0.0.1:9631- Bootstrap node's staking port--bootstrap-ids=NodeID-7Xhw2...- Bootstrap node's NodeID
Solution: Created /scripts/start-local-network.sh that properly configures bootstrap for all nodes
Verification:
# Check if bootstrap flags are in process command line
ps aux | grep luxd | grep 9640 | grep bootstrap-ips
Staking Certificate Reuse
Discovery: Netrunner has pre-configured staking certificates in /local/default/node1-5/
Files Per Node:
staking.crt- TLS certificate (determines NodeID)staking.key- TLS private keysigner.key- BLS signing key (32 bytes)
NodeIDs Generated (from netrunner default certificates):
- Node 1:
NodeID-7Xhw2mDxuDS44j42TCB6U5579esbSt3Lg - Node 2:
NodeID-MFrZFVCXPv5iCn6M9K6XduxGTYp891xXZ - Node 3:
NodeID-NFBbbJ4qCmNaCzeW7sxErhvWqvEQMnYcN - Node 4:
NodeID-GWPcbFJZFfZreETSoWjPimr846mXEKCtu - Node 5:
NodeID-P7oB2McjBGgW2NXXWVYjV8JEDFoW9xDE5
Usage Pattern:
# Copy pre-configured keys to node data directory
for i in {1..5}; do
mkdir -p $BASE/node$i
cp $NETRUNNER/local/default/node$i/*.{crt,key} $BASE/node$i/
done
# Start node with explicit staking key paths
$LUXD --staking-tls-cert-file=$BASE/node1/staking.crt \
--staking-tls-key-file=$BASE/node1/staking.key \
--staking-signer-key-file=$BASE/node1/signer.key
Benefit: Ensures NodeIDs match netrunner default genesis validators
Lux CLI Network Architecture Proposal (2025-12-19)
Executive Summary
This document proposes a production-ready architecture for mainnet network management in the Lux CLI. The design focuses on proper validator key management, 5-node consensus with staking keys from ~/.lux/keys/, and clean separation from the legacy "local" development command.
Current State Analysis
What Exists
- networkcmd/ - Already has
start,stop,clean,statuscommands with partial mainnet support - localcmd/ - Minimal PoA development network (single-node, chain ID 1337) - TO BE REMOVED
- netrunner integration - CLI uses netrunner's gRPC server for network orchestration
- Key infrastructure - Keys exist at
~/.lux/keys/node-{0-4}/staking/withstaker.crtandstaker.key - Validator config -
~/.lux/keys/mainnet_validators.jsoncontains P-chain addresses and private keys
Current Issues
- localcmd confusion - The
lux local startcommand creates a single-node PoA network for development (chain ID 1337), which is conceptually different from the mainnet/testnet multi-validator network - Missing proper staking key integration - Current
StartMainnet()doesn't load the pre-generated staking keys from~/.lux/keys/node-{0-4}/ - No snapshot management - Missing
snapshot saveandsnapshot restoresubcommands - Incomplete node configuration - Nodes aren't configured with proper staking certificates
Proposed Architecture
1. Command Structure
lux network
start [--mainnet|--testnet] # Start 5-node network with validator keys
stop # Stop network, preserve state
status # Show network status
clean # Clean all network data
snapshot
save <name> # Save current state to named snapshot
restore <name> # Restore from named snapshot
list # List available snapshots
delete <name> # Delete a snapshot
2. Remove localcmd/
The lux local command should be removed entirely. Rationale:
- It creates confusion between "local development" and "local mainnet simulation"
- The 1337 chain ID PoA network is superseded by proper multi-validator networks
- Users should use
lux network startfor all local network needs - The
--mainnetflag already provides mainnet genesis (network ID 96369) - The
--testnetflag provides testnet genesis (network ID 96368)
Files to remove:
/Users/z/work/lux/cli/cmd/localcmd/local.go- Remove
localcmd.NewCmd(app)from/Users/z/work/lux/cli/cmd/root.go(line 131)
3. Key Directory Structure (Already Exists)
~/.lux/keys/
node-0/
staking/
staker.crt # TLS certificate for staking
staker.key # TLS private key for staking
bls/ # BLS keys for consensus signatures
ec/ # EC keys
mldsa/ # ML-DSA post-quantum keys
rt/ # Corona keys
node-1/ ... node-4/ # Same structure
mainnet_validators.json # P-chain addresses and private keys
4. Enhanced Network Start with Staking Keys
New types in pkg/network/types.go:
package network
// ValidatorConfig represents a single validator's configuration
type ValidatorConfig struct {
NodeIndex int
StakingCert string // Path to staker.crt
StakingKey string // Path to staker.key
BLSKey string // Path to BLS key
NodeID string // Computed from staking key
PChainAddr string // P-chain address for rewards
HTTPPort int // HTTP API port
StakingPort int // P2P staking port
}
// NetworkConfig represents the full network configuration
type NetworkConfig struct {
NetworkID uint32
Validators []ValidatorConfig
GenesisPath string
RootDataDir string
PortBase int
DBEngine string // pebble, leveldb, or badgerdb
}
// LoadValidatorConfigs loads all 5 validator configurations from disk
func LoadValidatorConfigs(keyPath string, portBase int) ([]ValidatorConfig, error) {
validators := make([]ValidatorConfig, 5)
for i := 0; i < 5; i++ {
nodeDir := filepath.Join(keyPath, fmt.Sprintf("node-%d", i))
stakingDir := filepath.Join(nodeDir, "staking")
certPath := filepath.Join(stakingDir, "staker.crt")
keyPath := filepath.Join(stakingDir, "staker.key")
validators[i] = ValidatorConfig{
NodeIndex: i,
StakingCert: certPath,
StakingKey: keyPath,
HTTPPort: portBase + (i * 2), // 9630, 9632, 9634, 9636, 9638
StakingPort: portBase + (i * 2) + 1, // 9631, 9633, 9635, 9637, 9639
}
}
return validators, nil
}
5. New Snapshot Commands
New file: /Users/z/work/lux/cli/cmd/networkcmd/snapshot.go:
package networkcmd
func newSnapshotCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "snapshot",
Short: "Manage network snapshots",
}
cmd.AddCommand(newSnapshotSaveCmd())
cmd.AddCommand(newSnapshotRestoreCmd())
cmd.AddCommand(newSnapshotListCmd())
cmd.AddCommand(newSnapshotDeleteCmd())
return cmd
}
func newSnapshotSaveCmd() *cobra.Command {
return &cobra.Command{
Use: "save <name>",
Short: "Save current network state to a named snapshot",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cli, _ := binutils.NewGRPCClient()
_, err := cli.SaveSnapshot(ctx, args[0])
return err
},
}
}
func newSnapshotRestoreCmd() *cobra.Command {
return &cobra.Command{
Use: "restore <name>",
Short: "Restore network from a named snapshot",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cli, _ := binutils.NewGRPCClient()
_, err := cli.LoadSnapshot(ctx, args[0], opts...)
return err
},
}
}
6. Port Allocation Strategy
| Node | HTTP Port | Staking Port |
|---|---|---|
| node-0 | 9630 | 9631 |
| node-1 | 9632 | 9633 |
| node-2 | 9634 | 9635 |
| node-3 | 9636 | 9637 |
| node-4 | 9638 | 9639 |
File Structure Changes Summary
Files to Remove
cmd/localcmd/local.go # Remove entire localcmd
Files to Modify
cmd/root.go # Remove localcmd.NewCmd(app) import and call
cmd/networkcmd/network.go # Add snapshot subcommand
cmd/networkcmd/start.go # Integrate staking key loading
cmd/networkcmd/status.go # Enhance to show validator IDs
Files to Add
cmd/networkcmd/snapshot.go # New snapshot save/restore/list/delete
pkg/network/types.go # New ValidatorConfig, NetworkConfig types
pkg/network/keys.go # New key loading utilities
Configuration Flow
User runs: lux network start --mainnet
1. Load validator keys from ~/.lux/keys/node-{0-4}/staking/
2. Validate all 5 validators have staker.crt and staker.key
3. Build per-node configurations with:
- Staking TLS cert/key paths
- Unique HTTP ports (9630, 9632, 9634, 9636, 9638)
- Unique staking ports (9631, 9633, 9635, 9637, 9639)
- BadgerDB database backend
4. Start netrunner gRPC server if not running
5. Call netrunner.Start() with:
- Global config: network-id=96369, sybil-protection-enabled=true
- Custom node configs for each validator
- Genesis from luxfi/genesis package (network ID 96369)
6. Wait for all 5 validators to become healthy
7. Display endpoints table
User runs: lux network snapshot save checkpoint1
1. Connect to running netrunner
2. Call SaveSnapshot("checkpoint1")
3. Snapshot saved to ~/.lux/snapshots/anr-snapshot-checkpoint1/
User runs: lux network stop
1. Call SaveSnapshot("default-XXX") to preserve state
2. Kill netrunner server process
3. "Network stopped successfully"
User runs: lux network snapshot restore checkpoint1
1. Start netrunner server
2. Call LoadSnapshot("checkpoint1", opts...)
3. Wait for healthy
4. Display endpoints
Implementation Priority
Phase 1: Core Network Start (HIGH PRIORITY)
- Implement
pkg/network/types.goandpkg/network/keys.go - Update
cmd/networkcmd/start.goto load staking keys - Test 5-node mainnet startup with proper validator keys
Phase 2: Snapshot Management (HIGH PRIORITY)
- Add
cmd/networkcmd/snapshot.go - Register snapshot subcommand in
network.go - Test save/restore workflow
Phase 3: Cleanup (MEDIUM PRIORITY)
- Remove
cmd/localcmd/local.go - Remove from
cmd/root.go - Update documentation
Security Considerations
- Key Protection: Staking keys at
~/.lux/keys/should have 0600 permissions - No EWOQ Keys: As per CLAUDE.md, absolutely no EWOQ keys
- Real Genesis: Use luxfi/genesis package, never generate custom genesis
- Sybil Protection: Always enable sybil-protection-enabled for mainnet
RLP Block Import Files (IMPORTANT - Do Not Lose!)
State File Locations
All RLP files are at: ~/work/lux/state/rlp/
| Chain | Network | File Path | Size |
|---|---|---|---|
| Zoo | Mainnet | ~/work/lux/state/rlp/zoo-mainnet/zoo-mainnet-200200.rlp |
1.3M |
| Zoo | Testnet | ~/work/lux/state/rlp/zoo-testnet/zoo-testnet-200201.rlp |
- |
| Lux (C-Chain) | Mainnet | ~/work/lux/state/rlp/lux-mainnet/lux-mainnet-96369.rlp |
1.2G |
| Lux (C-Chain) | Testnet | ~/work/lux/state/rlp/lux-testnet/lux-testnet-96368.rlp |
- |
| SPC | Mainnet | ~/work/lux/state/rlp/spc-mainnet/spc-mainnet-36911.rlp |
- |
Chain IDs
- Zoo Mainnet: 200200
- Zoo Testnet: 200201
- Lux Mainnet (C-Chain): 96369
- Lux Testnet (C-Chain): 96368
- SPC Mainnet: 36911
Import Commands
# Import Zoo mainnet blocks (~1.3M blocks)
curl -X POST http://127.0.0.1:9650/ext/bc/Zoo/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"debug_importRLPBlocks","params":["'$(base64 -i ~/work/lux/state/rlp/zoo-mainnet/zoo-mainnet-200200.rlp)'"],"id":1}'
# Import C-chain mainnet blocks (~1.2G)
curl -X POST http://127.0.0.1:9650/ext/bc/C/rpc \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"debug_importRLPBlocks","params":["'$(base64 -i ~/work/lux/state/rlp/lux-mainnet/lux-mainnet-96369.rlp)'"],"id":1}'
Key Details
- RLP files contain encoded blocks for historical chain state replay
- Import order: Import Zoo first (smaller), then C-Chain (larger)
- Network must be running with Zoo chain discovered before import
Network ID vs Chain ID Fix (2025-12-23)
Critical Bug Fixed
Problem: Multiple functions in genesis_config.go were using C-Chain IDs (configs.MainnetChainID/configs.TestnetChainID = 96369/96368) when they should use Network IDs (constants.MainnetID/constants.TestnetID = 1/2).
Impact: Networks would fail to start with "network ID mismatch: expected 2, got 96368" or similar errors.
Constants Clarification
| Constant | Value | Purpose |
|---|---|---|
constants.MainnetID |
1 | P2P Network ID for mainnet |
constants.TestnetID |
2 | P2P Network ID for testnet |
constants.CustomID |
1337 | P2P Network ID for local dev |
configs.MainnetChainID |
96369 | EVM Chain ID for C-Chain mainnet |
configs.TestnetChainID |
96368 | EVM Chain ID for C-Chain testnet |
Files Fixed
/Users/z/work/lux/netrunner/local/genesis_config.go:
| Function | Before | After |
|---|---|---|
NewMainnetConfigWithKeys() (line 644) |
configs.MainnetChainID |
constants.MainnetID |
NewTestnetConfigWithKeys() (line 652) |
configs.TestnetChainID |
constants.TestnetID |
NewMainnetConfigFromMnemonic() (line 985) |
configs.MainnetChainID |
constants.MainnetID |
NewTestnetConfigFromMnemonic() (line 990) |
configs.TestnetChainID |
constants.TestnetID |
Earlier fixes in same session (from conversation summary):
- Line 58:
configs.LocalID→configs.CustomID - Line 335:
configs.LocalID→configs.CustomID - Line 996:
configs.LocalID→configs.CustomID
/Users/z/work/lux/netrunner/network/config.go:
- Line 125:
constants.LocalID→constants.CustomID
/Users/z/work/lux/netrunner/server/network.go:
- Line 152:
luxd_constants.LocalID→luxd_constants.CustomID - Lines 174, 182: Changed from hardcoded 96369/96368 to
luxd_constants.MainnetID/TestnetID
Zoo Chain Deployment Success
After fixes, successfully deployed Zoo chain on mainnet:
- Network ID: 1 (mainnet)
- Zoo Chain ID: 200200 (0x30e08)
- Genesis Hash:
0x7c548af47de27560779ccc67dda32a540944accc71dac3343da3b9cd18f14933 - Treasury: ~500M ZOO at
0x9011E888251AB053B7bD1cdB598Db4f9DEd94714 - RPC Endpoint:
http://localhost:9630/ext/bc/zoo/rpc
RLP Block Import Limitation
Discovery: The L2 EVM doesn't support admin_importChain RPC method. Blocks in L2 EVM chains come through Lux consensus, not direct import.
Available RPC modules on Zoo chain: eth, net, rpc, web3 (no admin or debug)
Workaround: For testing, deploy fresh AMM contracts since genesis state is identical.
Example Usage
// Correct - uses Network ID
cfg, err := local.NewMainnetConfigFromMnemonic(binaryPath, 5)
// Wrong - would use Chain ID instead of Network ID
// Previously: local.NewConfigFromMnemonic(binaryPath, configs.MainnetChainID, 5)
Conclusion
This architecture provides a clean, production-ready approach to mainnet network management:
- Clear command structure:
lux network {start|stop|status|clean|snapshot} - Proper key integration: Uses existing staking keys from
~/.lux/keys/ - State management: Snapshot save/restore for reproducible testing
- No confusion: Removes legacy
lux localcommand entirely - Mainnet-first: Defaults to mainnet configuration with 5 validators
Native BadgerDB Snapshot Fix (2026-01-22)
Problem
Snapshot creation was using 75GB directory copies instead of efficient native BadgerDB incremental backups.
Root Cause
- Node backup service not initialized:
DataDirwasn't passed to admin service config innode/node.go - CLI stop command order wrong: Tried to snapshot databases directly while nodes had exclusive locks
Files Modified
/Users/z/work/lux/node/node/node.go:
Added DataDir to admin service config to enable backup service:
service := admin.New(admin.Config{
// ... other fields ...
DataDir: n.Config.DatabaseConfig.Path, // ADDED
})
/Users/z/work/lux/netrunner/local/snapshot.go:
Cleaned up to single unified approach using native BadgerDB via admin.snapshot API.
- Removed legacy
copyDirfunction - Removed
hotSnapshotManifesttypes and duplicate functions - Reduced from 984 lines to 629 lines (36% reduction)
/Users/z/work/lux/cli/cmd/networkcmd/stop.go:
Fixed to use gRPC method (admin.snapshot API) for hot snapshots:
// Before (wrong - tried direct file access while nodes running)
if err := saveNetworkNative(stopNetworkType, snapshotName, useIncremental); err != nil {
if err := saveNetworkForType(stopNetworkType); err != nil { ... }
}
// After (correct - uses admin.snapshot API via gRPC)
if err := saveNetworkForType(stopNetworkType); err != nil {
ux.Logger.PrintToUser("Warning: failed to save snapshot: %v", err)
}
Results
- Before: 75GB snapshots (directory copy)
- After: 132KB snapshots (native BadgerDB incremental)
- Reduction: 99.9%+
Verified Functionality (2026-01-22)
| Feature | Status | Notes |
|---|---|---|
| 5-node testnet | ✅ | Ports 9640-9648 |
| 5-node mainnet | ✅ | Ports 9630-9638 |
| Hot snapshots | ✅ | Via admin.snapshot API |
| Incremental backups | ✅ | 5KB per node compressed |
| Resume from data | ✅ | Auto-detects existing run |
| Track all chains | ✅ | track-chains="all" |
| All 11 chains | ✅ | P,C,X,Q,A,B,T,Z,G,K,D |
Snapshot Format (v2)
{
"version": 2,
"network": "testnet",
"timestamp": 1769140260,
"created_at": "2026-01-23T03:51:00Z",
"nodes": {
"node1": {
"db_version": 11,
"incremental_from": 0,
"backup_file": "node1.backup.zst",
"compressed_size": 5362
}
// ... node2-node5
}
}
Commands Reference
# Start 5-node testnet
lux network start --testnet
# Stop with snapshot
lux network stop --testnet --force --snapshot-name my-snapshot
# Resume from snapshot (uses existing data)
lux network start --testnet
# Check snapshot
ls -la ~/.lux/snapshots/lux-snapshot-<name>/
cat ~/.lux/snapshots/lux-snapshot-<name>/manifest.json