Lux Docs
Lux Skills Reference

Lux Netrunner

Multi-Engine Network Orchestrator

Overview

Lux Netrunner is a multi-engine network orchestration and testing tool for the Lux blockchain. It manages local multi-node validator networks via a gRPC/REST control plane, supports heterogeneous consensus engines (Lux, Geth, OP Stack, Eth2), and provides snapshot-based state management with incremental BadgerDB backups.

Not just a test runner -- Netrunner orchestrates full L1/L2/L3 stacks with cross-chain bridging, multi-network management with shared BadgerDB for cross-chain ACID transactions, and YAML-based stack manifests for reproducible environments.

Quick Reference

ItemValue
Modulegithub.com/luxfi/netrunner
Go1.26.1
Version1.15.0
RPC Version42
gRPC Port8080
HTTP Gateway8081
Default Nodes5
LicenseBSD-3-Clause

Architecture

                    ┌──────────────────────────────────┐
                    │        CLI / Client SDK           │
                    └──────────┬───────────────────────┘
                               │ gRPC / REST
                    ┌──────────▼───────────────────────┐
                    │      Control Server (server/)     │
                    │  PingService + ControlService     │
                    └──┬───────────┬───────────────────┘
                       │           │
          ┌────────────▼──┐  ┌─────▼──────────────────┐
          │  Local Network │  │  Multi-Engine Host     │
          │  (local/)      │  │  (orchestrator/)       │
          │  Lux nodes     │  │  Lux/Geth/OP/Eth2     │
          └────────┬───────┘  └──────┬─────────────────┘
                   │                 │
          ┌────────▼───────┐  ┌──────▼─────────────────┐
          │  Snapshot Mgr  │  │  MultiNet Manager      │
          │  BadgerDB/zstd │  │  (multinet/)           │
          └────────────────┘  │  Cross-chain ACID txs  │
                              └────────────────────────┘

gRPC API (rpcpb/rpc.proto)

PingService

RPCHTTPDescription
PingPOST /v1/pingHealth check, returns server PID

ControlService

RPCHTTPDescription
RPCVersionPOST /v1/control/rpcversionReturns RPC protocol version (42)
StartPOST /v1/control/startStart a network with config
StopPOST /v1/control/stopStop all nodes
HealthPOST /v1/control/healthCheck cluster health
WaitForHealthyPOST /v1/control/waitforhealthyBlock until healthy
StatusPOST /v1/control/statusGet cluster status
StreamStatusPOST /v1/control/streamstatusServer-streaming status updates
URIsPOST /v1/control/urisGet all node URIs
AddNodePOST /v1/control/addnodeAdd node to running network
RemoveNodePOST /v1/control/removenodeRemove node from network
RestartNodePOST /v1/control/restartnodeRestart node with new config
PauseNodePOST /v1/control/pausenodePause node (preserves state)
ResumeNodePOST /v1/control/resumenodeResume paused node
CreateBlockchainsPOST /v1/control/createblockchainsDeploy custom VM chains
CreateChainsPOST /v1/control/createchainsCreate participant groups
TransformElasticChainsPOST /v1/control/transformelasticchainsTransform to elastic chains
AddPermissionlessValidatorPOST /v1/control/addpermissionlessvalidatorAdd elastic chain validator
RemoveChainValidatorPOST /v1/control/removechainvalidatorRemove chain validator
AttachPeerPOST /v1/control/attachpeerAttach test peer to node
SendOutboundMessagePOST /v1/control/sendoutboundmessageSend P2P message via peer
SaveSnapshotPOST /v1/control/savesnapshotSave network snapshot
SaveHotSnapshotPOST /v1/control/savehotsnapshotHot snapshot (no stop)
LoadSnapshotPOST /v1/control/loadsnapshotRestore from snapshot
RemoveSnapshotPOST /v1/control/removesnapshotDelete snapshot
GetSnapshotNamesPOST /v1/control/getsnapshotnamesList all snapshots

StartRequest Fields

message StartRequest {
  string network_name = 1;    // "mainnet", "testnet", "devnet", "custom"
  string node_type = 2;       // "luxd", "luxgo", "geth", "op-node", "custom"
  string exec_path = 4;
  optional uint32 num_nodes = 5;
  optional string global_node_config = 7;
  optional string root_data_dir = 8;
  string plugin_dir = 9;
  repeated BlockchainSpec blockchain_specs = 10;
  map<string, string> custom_node_configs = 11;
  map<string, string> chain_configs = 12;
  map<string, string> upgrade_configs = 13;
  optional bool reassign_ports_if_used = 14;
  optional bool dynamic_ports = 15;
}

Client SDK


cli, _ := client.New(client.Config{
    Endpoint:    "localhost:8080",
    DialTimeout: 10 * time.Second,
}, logger)
defer cli.Close()

// Start 5-node local network
resp, _ := cli.Start(ctx, "/usr/local/bin/luxd",
    client.WithNumNodes(5),
    client.WithDynamicPorts(true),
    client.WithPluginDir("/path/to/plugins"),
    client.WithChainSpecs([]*rpcpb.BlockchainSpec{{
        VmName:  "chainevm",
        Genesis: "/path/to/genesis.json",
    }}),
)

// Wait for health
cli.WaitForHealthy(ctx)

// Get node URIs
uris, _ := cli.URIs(ctx)

// Manage nodes
cli.PauseNode(ctx, "node3")
cli.ResumeNode(ctx, "node3")
cli.RestartNode(ctx, "node1", client.WithExecPath("/new/luxd"))
cli.AddNode(ctx, "node6", "/usr/local/bin/luxd")
cli.RemoveNode(ctx, "node6")

// Snapshots (incremental BadgerDB + zstd compression)
cli.SaveSnapshot(ctx, "pre-upgrade")
cli.SaveHotSnapshot(ctx, "live-backup")  // No network stop
cli.LoadSnapshot(ctx, "pre-upgrade")

// P2P testing
attachResp, _ := cli.AttachPeer(ctx, "node1")
cli.SendOutboundMessage(ctx, "node1", attachResp.AttachedPeerInfo.Id, 0, msgBytes)

// Elastic chains
cli.TransformElasticChains(ctx, []*rpcpb.ElasticChainSpec{{
    ChainId:          "chain-id",
    AssetName:        "TEST",
    AssetSymbol:      "TST",
    MinValidatorStake: 1000,
}})
cli.AddPermissionlessValidator(ctx, []*rpcpb.PermissionlessValidatorSpec{{
    ChainId:           "chain-id",
    NodeName:          "node1",
    StakedTokenAmount: 5000,
}})

cli.Stop(ctx)

Multi-Engine Orchestrator (orchestrator/)

The orchestrator runs heterogeneous consensus engines in a single host.

Supported Engines

EngineTypeDescription
LuxluxLux Snow consensus (luxd)
GethgethGo-Ethereum execution client
OP StackopOptimism OP node (L2)
Eth2eth2Ethereum 2.0 beacon + execution

Engine Interface

type Engine interface {
    Name() string
    Type() EngineType
    Start(ctx context.Context, config *NodeConfig) error
    Stop(ctx context.Context) error
    Restart(ctx context.Context) error
    Health(ctx context.Context) (*HealthStatus, error)
    IsRunning() bool
    Uptime() time.Duration
    NetworkID() uint32
    ChainID() ids.ID
    RPCEndpoint() string
    WSEndpoint() string
    P2PEndpoint() string
    ParentChain() *ChainInfo  // nil for L1s
    Metrics() map[string]interface{}
}

Stack Manifests (stacks/)

YAML-based definitions for multi-engine stacks:

# stacks/lux-local.yaml
name: lux-local
version: 1.0.0
description: Local Lux L1 for testing

engines:
  - name: lux-node-1
    type: lux
    network_id: 96369
    http_port: 9650
    staking_port: 9651
    log_level: info
    wait_healthy: true
    extra:
      dev-mode: true

networks:
  - name: lux-local
    type: l1
    engine: lux-node-1
    chain_id: 96369

Predefined stacks: lux-local, lux-mainnet-5node, lux-testnet-5node, lux-mainnet-alt, lux-l1-l2-local, lux-lux-bridge.

Bridge config supports types: awm, ibc, ccip.

Multi-Network Manager (multinet/)

Runs multiple heterogeneous networks in parallel with shared BadgerDB for cross-chain ACID transactions.

mgr, _ := multinet.NewMultiNetworkManager(logger, "/tmp/shared-db")
defer mgr.Shutdown()

mgr.AddNetwork(multinet.NetworkConfig{
    NetworkID: 1, Name: "mainnet", Type: multinet.NetworkTypePrimary,
    Validators: 5,
})
mgr.AddNetwork(multinet.NetworkConfig{
    NetworkID: 2, Name: "chain-a", Type: multinet.NetworkTypeChain,
    ParentID: 1,
})
mgr.StartAll()

// Cross-chain ACID transaction
mgr.SubmitCrossChainTx(&multinet.CrossChainTx{
    ID: "tx-1", SourceNet: 1, DestNet: 2,
    Amount: 1000, Asset: "LUX",
})

Consensus params are configurable per network (K, Alpha, BetaVirtuous, BetaRogue, ConcurrentPolls).

Snapshot System

Snapshots use native BadgerDB incremental backup with zstd compression.

FeatureDetail
FormatBadgerDB native backup + zstd
Manifestmanifest.json (version 2)
IncrementalYes, tracks db_version per node
Hot snapshotSupported (no network stop)
Admin APIadmin.snapshot / admin.load
Storage~/.netrunner/snapshots/lux-snapshot-\{name\}/

Snapshot contents: network.json (full config), state.json (elastic chain mapping), \{nodeName\}.backup.zst (per-node compressed backup), manifest.json.

Local Network (local/)

Core local network implementation managing luxd processes:

ConstantValue
Default nodes5
Health check interval100ms
Stop timeout30s
Peer start timeout30s
Staking key fileluxtls.key
Staking cert fileluxtls.crt
Signer key filesigner.key

The network.Network interface provides:

  • Node lifecycle: AddNode, RemoveNode, PauseNode, ResumeNode, RestartNode
  • Chain management: CreateChains, CreateParticipantGroups, TransformChain
  • Elastic chains: AddPermissionlessValidators, RemoveChainValidators
  • Snapshots: SaveSnapshot, SaveHotSnapshot, LoadSnapshot

Key Dependencies (from go.mod)

PackageVersionPurpose
github.com/luxfi/nodev1.23.21Lux node types
github.com/luxfi/sdkv1.16.46Client SDK (admin API)
github.com/luxfi/p2pv1.19.2-zapP2P networking
github.com/luxfi/consensusv1.22.69Consensus engine
github.com/luxfi/cryptov1.17.42BLS/secp256k1 keys
github.com/luxfi/genesisv1.6.1Genesis generation
github.com/luxfi/idsv1.2.9ID types (NodeID, etc)
github.com/luxfi/evmv0.8.30EVM plugin
github.com/luxfi/vmv1.0.38VM interface
github.com/luxfi/configv1.1.1Node configuration
github.com/luxfi/tlsv1.0.3TLS certificate handling
github.com/luxfi/rpcv1.0.0RPC layer
github.com/dgraph-io/badger/v4v4.9.0Database (shared DB)
google.golang.org/grpcv1.79.1gRPC framework
k8s.io/client-gov0.35.1K8s engine support
github.com/klauspost/compressv1.18.4zstd compression
github.com/spf13/cobrav1.10.2CLI commands

CLI Commands

CommandDescription
netrunner serverStart gRPC + HTTP gateway server
netrunner control startStart network via RPC
netrunner control stopStop network via RPC
netrunner pingPing server
netrunner genkeysGenerate staking keys
netrunner testkeysGenerate test keys

Build

make build        # Build netrunner binary
make test         # Run tests
make test-race    # Tests with race detector
make bench        # Run benchmarks
make build-all    # Cross-compile (linux/darwin/windows, amd64/arm64)
make install      # Install to /usr/local/bin
make lint         # golangci-lint
make release      # Generate release artifacts

Directory Structure

netrunner/
  main.go              # Entry point
  cmd/                  # CLI commands (server, control, ping, genkeys)
  server/               # gRPC + HTTP gateway server
  client/               # Go client SDK
  rpcpb/                # Protobuf definitions
  local/                # Local network implementation (process management)
  network/              # Network interface + config + genesis generation
  orchestrator/         # Multi-engine host (Lux/Geth/OP/Eth2)
  engines/              # Engine interface + implementations (lux, geth, k8s, opstack, eth2)
  multinet/             # Multi-network manager with shared BadgerDB
  stacks/               # YAML stack manifests
  api/                  # API client wrapper
  utils/                # Utilities (color picker, JSON helpers)
  tests/                # Integration tests
  examples/             # Usage examples
  build/                # Build output

On this page