mirror of
https://github.com/luxfi/netrunner.git
synced 2026-07-27 00:04:23 +00:00
scrub: subnet/l2 → chain (canonical vocabulary, forward-only)
Wire-format codec IDs unchanged. CLI aliases deleted; chain is the command. No backwards-compat shims, no deprecation comments.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
|
||||
## 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.
|
||||
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, application chains, and complex network topologies.
|
||||
|
||||
## Essential Commands
|
||||
|
||||
@@ -1091,7 +1091,7 @@ After fixes, successfully deployed Zoo chain on mainnet:
|
||||
|
||||
### 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.
|
||||
**Discovery**: The EVM plugin doesn't support `admin_importChain` RPC method. Blocks in EVM chains come through Lux consensus, not direct import.
|
||||
|
||||
**Available RPC modules on Zoo chain**: eth, net, rpc, web3 (no admin or debug)
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ Additional optional parameters which can be passed to the start command:
|
||||
|
||||
```bash
|
||||
--plugin-dir ${LUXD_PLUGIN_PATH} \
|
||||
--blockchain-specs '[{"vm_name": "subnetevm", "genesis": "/tmp/subnet-evm.genesis.json"}]'
|
||||
--blockchain-specs '[{"vm_name": "evm", "genesis": "/tmp/evm.genesis.json"}]'
|
||||
--global-node-config '{"index-enabled":false, "api-admin-enabled":true,"network-peer-list-gossip-frequency":"300ms"}'
|
||||
--custom-node-configs" '{"node1":{"log-level":"debug","api-admin-enabled":false},"node2":{...},...}'
|
||||
```
|
||||
@@ -155,8 +155,8 @@ netrunner control start \
|
||||
--global-node-config '{"http-host":"0.0.0.0"}'
|
||||
```
|
||||
|
||||
`--plugin-dir` and `--blockchain-specs` are parameters relevant to chain (L2 blockchain) operation.
|
||||
See the [chain deployment](#network-runner-rpc-server-l2-evm-example) section for details about how to run chains.
|
||||
`--plugin-dir` and `--blockchain-specs` are parameters relevant to chain operation.
|
||||
See the [chain deployment](#network-runner-rpc-server-evm-example) section for details about how to run chains.
|
||||
|
||||
The network-runner supports node node configuration at different levels.
|
||||
|
||||
@@ -302,38 +302,38 @@ netrunner control remove-snapshot snapshotName
|
||||
To create 1 chain (validator set), with all existing nodes as participants (requires network restart):
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/createsubnets -d '[{}]'
|
||||
curl -X POST -k http://localhost:8081/v1/control/createchains -d '[{}]'
|
||||
|
||||
# or
|
||||
netrunner control create-subnets '[{}]'
|
||||
netrunner control create-chains '[{}]'
|
||||
```
|
||||
|
||||
To create 1 chain (validator set), with some of existing nodes as participants (requires network restart):
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/createsubnets -d '[{"participants": ["node1", "node2"]}]'
|
||||
curl -X POST -k http://localhost:8081/v1/control/createchains -d '[{"participants": ["node1", "node2"]}]'
|
||||
|
||||
# or
|
||||
netrunner control create-subnets '[{"participants": ["node1", "node2"]}]'
|
||||
netrunner control create-chains '[{"participants": ["node1", "node2"]}]'
|
||||
```
|
||||
|
||||
To create 1 chain (validator set), with some of existing nodes and another new node as participants (requires network restart):
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/createsubnets -d '[{"participants": ["node1", "node2", "testNode"]}]'
|
||||
curl -X POST -k http://localhost:8081/v1/control/createchains -d '[{"participants": ["node1", "node2", "testNode"]}]'
|
||||
|
||||
# or
|
||||
netrunner control create-subnets '[{"participants": ["node1", "node2", "testNode"]}]'
|
||||
netrunner control create-chains '[{"participants": ["node1", "node2", "testNode"]}]'
|
||||
|
||||
```
|
||||
|
||||
To create N chains (validator sets) (requires network restart):
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/createsubnets -d '[{}, {"participants": ["node1", "node2", "node3"]}, {"participants": ["node1", "node2", "testNode"]}]'
|
||||
curl -X POST -k http://localhost:8081/v1/control/createchains -d '[{}, {"participants": ["node1", "node2", "node3"]}, {"participants": ["node1", "node2", "testNode"]}]'
|
||||
|
||||
# or
|
||||
netrunner control create-subnets '[{}, {"participants": ["node1", "node2", "node3"]}, {"participants": ["node1", "node2", "testNode"]}]'
|
||||
netrunner control create-chains '[{}, {"participants": ["node1", "node2", "node3"]}, {"participants": ["node1", "node2", "testNode"]}]'
|
||||
|
||||
```
|
||||
|
||||
@@ -358,38 +358,38 @@ netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENE
|
||||
To create a blockchain with a chain ID (does not require restart):
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_id": "'$SUBNET_ID'"}]}'
|
||||
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "blockchain_id": "'$BLOCKCHAIN_ID'"}]}'
|
||||
|
||||
# or
|
||||
netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_id": "'$SUBNET_ID'"}]' --plugin-dir $PLUGIN_DIR
|
||||
netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "blockchain_id": "'$BLOCKCHAIN_ID'"}]' --plugin-dir $PLUGIN_DIR
|
||||
```
|
||||
|
||||
To create a blockchain with a chain ID, and chain config, network upgrade and chain config file paths (requires network restart):
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_id": "'$SUBNET_ID'", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "subnet_config": "'$SUBNET_CONFIG_PATH'"}]}'
|
||||
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "blockchain_id": "'$BLOCKCHAIN_ID'", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "chain_config_per_chain": "'$CHAIN_CONFIG_PER_CHAIN_PATH'"}]}'
|
||||
|
||||
# or
|
||||
netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_id": "'$SUBNET_ID'", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "subnet_config": "'$SUBNET_CONFIG_PATH'"}]' --plugin-dir $PLUGIN_DIR
|
||||
netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "blockchain_id": "'$BLOCKCHAIN_ID'", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "chain_config_per_chain": "'$CHAIN_CONFIG_PER_CHAIN_PATH'"}]' --plugin-dir $PLUGIN_DIR
|
||||
```
|
||||
|
||||
To create a blockchain with a new chain with select nodes as participants (requires network restart):
|
||||
(New nodes will first be added as primary validators similar to the process in `create-subnets`)
|
||||
(New nodes will first be added as primary validators similar to the process in `create-chains`)
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_spec": "{"participants": ["node1", "node2", "testNode"]}"]}'
|
||||
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "chain_spec": "{"participants": ["node1", "node2", "testNode"]}"]}'
|
||||
|
||||
# or
|
||||
netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_spec": "{"participants": ["node1", "node2", "testNode"]}]' --plugin-dir $PLUGIN_DIR
|
||||
netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "chain_spec": "{"participants": ["node1", "node2", "testNode"]}]' --plugin-dir $PLUGIN_DIR
|
||||
```
|
||||
|
||||
To create two blockchains in two disjoint chains (not shared validators), and where all validators have bls keys (participants new to the network):
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_spec": {"participants": ["new_node1", "new_node2"]}},{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_spec": {"participants": ["new_node3", "new_node4"]}}]'
|
||||
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "chain_spec": {"participants": ["new_node1", "new_node2"]}},{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "chain_spec": {"participants": ["new_node3", "new_node4"]}}]'
|
||||
|
||||
# or
|
||||
go run main.go control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_spec": {"participants": ["new_node1", "new_node2"]}},{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_spec": {"participants": ["new_node3", "new_node4"]}}]'
|
||||
go run main.go control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "chain_spec": {"participants": ["new_node1", "new_node2"]}},{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "chain_spec": {"participants": ["new_node3", "new_node4"]}}]'
|
||||
```
|
||||
|
||||
Chain config can also be defined on a per node basis. For that, a per node chain config file is needed, which is a JSON that specifies the chain config per node. For example, given the following as the contents of the file with path `$PER_NODE_CHAIN_CONFIG`:
|
||||
@@ -407,10 +407,10 @@ Chain config can also be defined on a per node basis. For that, a per node chain
|
||||
Then a blockchain with different chain configs per node can be created with this command:
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_id": "'$SUBNET_ID'", "per_node_chain_config": "'$PER_NODE_CHAIN_CONFIG'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "subnet_config": "'$SUBNET_CONFIG_PATH'"}]}'
|
||||
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "blockchain_id": "'$BLOCKCHAIN_ID'", "per_node_chain_config": "'$PER_NODE_CHAIN_CONFIG'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "chain_config_per_chain": "'$CHAIN_CONFIG_PER_CHAIN_PATH'"}]}'
|
||||
|
||||
# or
|
||||
netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_id": "'$SUBNET_ID'", "per_node_chain_config": "'$PER_NODE_CHAIN_CONFIG'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "subnet_config": "'$SUBNET_CONFIG_PATH'"}]' --plugin-dir $PLUGIN_DIR
|
||||
netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "blockchain_id": "'$BLOCKCHAIN_ID'", "per_node_chain_config": "'$PER_NODE_CHAIN_CONFIG'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "chain_config_per_chain": "'$CHAIN_CONFIG_PER_CHAIN_PATH'"}]' --plugin-dir $PLUGIN_DIR
|
||||
```
|
||||
|
||||
To remove (stop) a node:
|
||||
@@ -552,7 +552,7 @@ netrunner control stop \
|
||||
--endpoint="0.0.0.0:8080"
|
||||
```
|
||||
|
||||
## `network-runner` RPC server: L2 EVM example
|
||||
## `network-runner` RPC server: EVM chain example
|
||||
|
||||
To start the server:
|
||||
|
||||
@@ -569,10 +569,10 @@ curl -X POST -k http://localhost:8081/v1/ping -d ''
|
||||
To start the cluster with custom chains:
|
||||
|
||||
```bash
|
||||
# or download from https://github.com/luxfi/subnet-cli/releases
|
||||
cd ${HOME}/go/src/github.com/luxfi/subnet-cli
|
||||
# or download from https://github.com/luxfi/cli/releases
|
||||
cd ${HOME}/go/src/github.com/luxfi/cli
|
||||
go install -v .
|
||||
subnet-cli create VMID subnetevm
|
||||
lux chain create VMID evm
|
||||
# srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy
|
||||
|
||||
# download from https://github.com/luxfi/sdk/node/releases
|
||||
@@ -581,8 +581,8 @@ rm -rf ${HOME}/go/src/github.com/luxfi/sdk/node/build
|
||||
cd ${HOME}/go/src/github.com/luxfi/node
|
||||
./scripts/build.sh
|
||||
|
||||
# ref. https://github.com/luxfi/subnet-evm/blob/b69e47e0398b5237cda0422f6a32969e64bde346/scripts/run.sh
|
||||
cd ${HOME}/go/src/github.com/luxfi/subnet-evm
|
||||
# ref. https://github.com/luxfi/evm/blob/b69e47e0398b5237cda0422f6a32969e64bde346/scripts/run.sh
|
||||
cd ${HOME}/go/src/github.com/luxfi/evm
|
||||
go build -v \
|
||||
-o ${HOME}/go/src/github.com/luxfi/sdk/node/build/plugins/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy \
|
||||
./plugin
|
||||
@@ -599,7 +599,7 @@ find ${HOME}/go/src/github.com/luxfi/sdk/node/build
|
||||
# generate the genesis for the custom chain
|
||||
export CHAIN_ID=99999
|
||||
export GENESIS_ADDRESS="0x9011E888251AB053B7bD1cdB598Db4f9DEd94714"
|
||||
cat <<EOF > /tmp/subnet-evm.genesis.json
|
||||
cat <<EOF > /tmp/evm.genesis.json
|
||||
{
|
||||
"config": {
|
||||
"chainId": $CHAIN_ID,
|
||||
@@ -642,7 +642,7 @@ cat <<EOF > /tmp/subnet-evm.genesis.json
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
EOF
|
||||
cat /tmp/subnet-evm.genesis.json
|
||||
cat /tmp/evm.genesis.json
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -650,7 +650,7 @@ cat /tmp/subnet-evm.genesis.json
|
||||
LUXD_EXEC_PATH="${HOME}/go/src/github.com/luxfi/sdk/node/build/node"
|
||||
LUXD_PLUGIN_PATH="${HOME}/go/src/github.com/luxfi/sdk/node/build/plugins"
|
||||
|
||||
curl -X POST -k http://localhost:8081/v1/control/start -d '{"execPath":"'${LUXD_EXEC_PATH}'","numNodes":5,"logLevel":"INFO","pluginDir":"'${LUXD_PLUGIN_PATH}'","blockchainSpecs":[{"vm_name":"subnetevm","genesis":"/tmp/subnet-evm.genesis.json"}]}'
|
||||
curl -X POST -k http://localhost:8081/v1/control/start -d '{"execPath":"'${LUXD_EXEC_PATH}'","numNodes":5,"logLevel":"INFO","pluginDir":"'${LUXD_PLUGIN_PATH}'","blockchainSpecs":[{"vm_name":"evm","genesis":"/tmp/evm.genesis.json"}]}'
|
||||
|
||||
# or
|
||||
netrunner control start \
|
||||
@@ -658,7 +658,7 @@ netrunner control start \
|
||||
--endpoint="0.0.0.0:8080" \
|
||||
--node-path ${LUXD_EXEC_PATH} \
|
||||
--plugin-dir ${LUXD_PLUGIN_PATH} \
|
||||
--blockchain-specs '[{"vm_name": "subnetevm", "genesis": "/tmp/subnet-evm.genesis.json"}]'
|
||||
--blockchain-specs '[{"vm_name": "evm", "genesis": "/tmp/evm.genesis.json"}]'
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -669,7 +669,7 @@ curl -X POST -k http://localhost:8081/v1/control/status -d ''
|
||||
Blockchain config file, network upgrade file, and network config file paths can be optionally specified at network start, eg:
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/start -d '{"execPath":"'${LUXD_EXEC_PATH}'","numNodes":5,"logLevel":"INFO","pluginDir":"'${LUXD_PLUGIN_PATH}'","blockchainSpecs":[{"vm_name":"subnetevm","genesis":"/tmp/subnet-evm.genesis.json","chain_config":"'$CHAIN_CONFIG_PATH'","network_upgrade":"'$NETWORK_UPGRADE_PATH'","subnet_config":"'$SUBNET_CONFIG_PATH'"}]}'
|
||||
curl -X POST -k http://localhost:8081/v1/control/start -d '{"execPath":"'${LUXD_EXEC_PATH}'","numNodes":5,"logLevel":"INFO","pluginDir":"'${LUXD_PLUGIN_PATH}'","blockchainSpecs":[{"vm_name":"evm","genesis":"/tmp/evm.genesis.json","chain_config":"'$CHAIN_CONFIG_PATH'","network_upgrade":"'$NETWORK_UPGRADE_PATH'","chain_config_per_chain":"'$CHAIN_CONFIG_PER_CHAIN_PATH'"}]}'
|
||||
|
||||
# or
|
||||
netrunner control start \
|
||||
@@ -677,7 +677,7 @@ netrunner control start \
|
||||
--endpoint="0.0.0.0:8080" \
|
||||
--node-path ${LUXD_EXEC_PATH} \
|
||||
--plugin-dir ${LUXD_PLUGIN_PATH} \
|
||||
--blockchain-specs '[{"vm_name": "subnetevm", "genesis": "/tmp/subnet-evm.genesis.json", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "subnet_config": "'$SUBNET_CONFIG_PATH'"}]'
|
||||
--blockchain-specs '[{"vm_name": "evm", "genesis": "/tmp/evm.genesis.json", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "chain_config_per_chain": "'$CHAIN_CONFIG_PER_CHAIN_PATH'"}]'
|
||||
```
|
||||
|
||||
## `network-runner` RPC server: `blobvm` example
|
||||
@@ -697,10 +697,10 @@ curl -X POST -k http://localhost:8081/v1/ping -d ''
|
||||
To start the cluster with custom chains:
|
||||
|
||||
```bash
|
||||
# or download from https://github.com/luxfi/subnet-cli/releases
|
||||
cd ${HOME}/go/src/github.com/luxfi/subnet-cli
|
||||
# or download from https://github.com/luxfi/cli/releases
|
||||
cd ${HOME}/go/src/github.com/luxfi/cli
|
||||
go install -v .
|
||||
subnet-cli create VMID blobvm
|
||||
lux chain create VMID blobvm
|
||||
# kM6h4LYe3AcEU1MB2UNg6ubzAiDAALZzpVrbX8zn3hXF6Avd8
|
||||
|
||||
# download from https://github.com/luxfi/sdk/node/releases
|
||||
@@ -755,7 +755,7 @@ curl -X POST -k http://localhost:8081/v1/control/status -d ''
|
||||
Blockchain config file and network upgrade file paths can be optionally specified at network start, eg:
|
||||
|
||||
```bash
|
||||
curl -X POST -k http://localhost:8081/v1/control/start -d '{"execPath":"'${LUXD_EXEC_PATH}'","numNodes":5,"logLevel":"INFO","pluginDir":"'${LUXD_PLUGIN_PATH}'","blockchainSpecs":[{"vm_name":"blobvm","genesis":"/tmp/blobvm.json","chain_config":"'$CHAIN_CONFIG_PATH'","network_upgrade":"'$NETWORK_UPGRADE_PATH'","subnet_config":"'$SUBNET_CONFIG_PATH'"}]}'
|
||||
curl -X POST -k http://localhost:8081/v1/control/start -d '{"execPath":"'${LUXD_EXEC_PATH}'","numNodes":5,"logLevel":"INFO","pluginDir":"'${LUXD_PLUGIN_PATH}'","blockchainSpecs":[{"vm_name":"blobvm","genesis":"/tmp/blobvm.json","chain_config":"'$CHAIN_CONFIG_PATH'","network_upgrade":"'$NETWORK_UPGRADE_PATH'","chain_config_per_chain":"'$CHAIN_CONFIG_PER_CHAIN_PATH'"}]}'
|
||||
|
||||
# or
|
||||
netrunner control start \
|
||||
@@ -763,7 +763,7 @@ netrunner control start \
|
||||
--endpoint="0.0.0.0:8080" \
|
||||
--node-path ${LUXD_EXEC_PATH} \
|
||||
--plugin-dir ${LUXD_PLUGIN_PATH} \
|
||||
--blockchain-specs '[{"vm_name": "blobvm", "genesis": "/tmp/blobvm.genesis.json", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "subnet_config": "'$SUBNET_CONFIG_PATH'"}]'
|
||||
--blockchain-specs '[{"vm_name": "blobvm", "genesis": "/tmp/blobvm.genesis.json", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "chain_config_per_chain": "'$CHAIN_CONFIG_PER_CHAIN_PATH'"}]'
|
||||
```
|
||||
|
||||
## `network-runner` RPC server: `timestampvm` example
|
||||
@@ -783,10 +783,10 @@ curl -X POST -k http://localhost:8081/v1/ping -d ''
|
||||
To start the cluster with custom chains:
|
||||
|
||||
```bash
|
||||
# or download from https://github.com/luxfi/subnet-cli/releases
|
||||
cd ${HOME}/go/src/github.com/luxfi/subnet-cli
|
||||
# or download from https://github.com/luxfi/cli/releases
|
||||
cd ${HOME}/go/src/github.com/luxfi/cli
|
||||
go install -v .
|
||||
subnet-cli create VMID timestampvm
|
||||
lux chain create VMID timestampvm
|
||||
# tGas3T58KzdjcJ2iKSyiYsWiqYctRXaPTqBCA11BqEkNg8kPc
|
||||
|
||||
# download from https://github.com/luxfi/sdk/node/releases
|
||||
@@ -904,7 +904,7 @@ type Config struct {
|
||||
// May be nil.
|
||||
UpgradeConfigFiles map[string]string `json:"upgradeConfigFiles"`
|
||||
// May be nil.
|
||||
SubnetConfigFiles map[string]string `json:"subnetConfigFiles"`
|
||||
ChainConfigPerChainFiles map[string]string `json:"chainConfigPerChainFiles"`
|
||||
// Flags can hold additional flags for the node.
|
||||
// It can be empty.
|
||||
// The precedence of flags handling is:
|
||||
|
||||
@@ -5,7 +5,7 @@ description: Lux Netrunner - Network orchestration and testing framework for Lux
|
||||
|
||||
# Lux Netrunner
|
||||
|
||||
Lux Netrunner is a powerful network orchestration and testing framework designed 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.
|
||||
Lux Netrunner is a powerful network orchestration and testing framework designed for blockchain development. It provides comprehensive tools for creating, managing, and testing multi-node blockchain networks with support for custom VMs, application chains, and complex network topologies.
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -194,26 +194,26 @@ cat > elastic-network.json <<EOF
|
||||
EOF
|
||||
|
||||
# Create elastic network
|
||||
netrunner control create-elastic-subnet elastic-network.json
|
||||
netrunner control create-elastic-chain elastic-network.json
|
||||
```
|
||||
|
||||
## Custom Blockchain Deployment
|
||||
|
||||
### Deploy Subnet-EVM
|
||||
### Deploy EVM Chain
|
||||
|
||||
```bash
|
||||
# Generate VM ID
|
||||
subnet-cli create VMID subnetevm
|
||||
lux chain create VMID evm
|
||||
# Output: srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy
|
||||
|
||||
# Build the plugin
|
||||
cd ${HOME}/go/src/github.com/luxfi/subnet-evm
|
||||
cd ${HOME}/go/src/github.com/luxfi/evm
|
||||
go build -v \
|
||||
-o ${LUXD_PLUGIN_PATH}/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy \
|
||||
./plugin
|
||||
|
||||
# Create genesis
|
||||
cat > /tmp/subnet-evm.genesis.json <<EOF
|
||||
cat > /tmp/evm.genesis.json <<EOF
|
||||
{
|
||||
"config": {
|
||||
"chainId": 99999,
|
||||
@@ -250,15 +250,15 @@ cat > /tmp/subnet-evm.genesis.json <<EOF
|
||||
}
|
||||
EOF
|
||||
|
||||
# Start network with subnet-evm
|
||||
# Start network with EVM
|
||||
netrunner control start \
|
||||
--endpoint="0.0.0.0:8080" \
|
||||
--number-of-nodes=3 \
|
||||
--node-path ${LUXD_EXEC_PATH} \
|
||||
--plugin-dir ${LUXD_PLUGIN_PATH} \
|
||||
--blockchain-specs '[{
|
||||
"vm_name": "subnetevm",
|
||||
"genesis": "/tmp/subnet-evm.genesis.json"
|
||||
"vm_name": "evm",
|
||||
"genesis": "/tmp/evm.genesis.json"
|
||||
}]'
|
||||
```
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ type NetworkType string
|
||||
|
||||
const (
|
||||
NetworkTypePrimary NetworkType = "primary" // Mainnet or Testnet
|
||||
NetworkTypeChain NetworkType = "chain" // L1/L2 chains
|
||||
NetworkTypeChain NetworkType = "chain" // Application chains
|
||||
)
|
||||
|
||||
// NetworkConfig defines configuration for a single network
|
||||
|
||||
@@ -1,225 +0,0 @@
|
||||
// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package orchestrator_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/luxfi/netrunner/engines"
|
||||
"github.com/luxfi/netrunner/orchestrator"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMultiEngineOrchestration(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
host := orchestrator.NewHost()
|
||||
|
||||
// Test starting Lux engine
|
||||
t.Run("StartLuxEngine", func(t *testing.T) {
|
||||
config := &engines.NodeConfig{
|
||||
NetworkID: 96369,
|
||||
HTTPPort: 19630,
|
||||
StakingPort: 19631,
|
||||
LogLevel: "info",
|
||||
Extra: map[string]interface{}{
|
||||
"staking-enabled": false,
|
||||
"sybil-protection-enabled": false,
|
||||
"health-check-frequency": "2s",
|
||||
},
|
||||
}
|
||||
|
||||
err := host.StartEngine(ctx, "test-lux", engines.EngineLux, config)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Wait for health
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// Check engine is listed
|
||||
engines := host.ListEngines()
|
||||
require.Len(t, engines, 1)
|
||||
require.Equal(t, "test-lux", engines[0].Name)
|
||||
require.Equal(t, "lux", engines[0].Type)
|
||||
|
||||
// Stop engine
|
||||
err = host.StopEngine(ctx, "test-lux")
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
// Test starting multiple engines
|
||||
t.Run("MultipleEngines", func(t *testing.T) {
|
||||
// Start Lux
|
||||
luxConfig := &engines.NodeConfig{
|
||||
NetworkID: 96369,
|
||||
HTTPPort: 19630,
|
||||
StakingPort: 19631,
|
||||
LogLevel: "info",
|
||||
}
|
||||
err := host.StartEngine(ctx, "lux-1", engines.EngineLux, luxConfig)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Start Lux
|
||||
avaConfig := &engines.NodeConfig{
|
||||
NetworkID: 43114,
|
||||
HTTPPort: 19640,
|
||||
StakingPort: 19641,
|
||||
LogLevel: "info",
|
||||
}
|
||||
err = host.StartEngine(ctx, "ava-1", engines.EngineLux, avaConfig)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Check both are running
|
||||
engines := host.ListEngines()
|
||||
require.Len(t, engines, 2)
|
||||
|
||||
// Clean up
|
||||
host.StopEngine(ctx, "lux-1")
|
||||
host.StopEngine(ctx, "ava-1")
|
||||
})
|
||||
}
|
||||
|
||||
func TestStackManifest(t *testing.T) {
|
||||
manifest := &orchestrator.StackManifest{
|
||||
Name: "test-stack",
|
||||
Version: "1.0.0",
|
||||
Description: "Test stack",
|
||||
Engines: []orchestrator.EngineConfig{
|
||||
{
|
||||
Name: "lux-l1",
|
||||
Type: "lux",
|
||||
NetworkID: 96369,
|
||||
HTTPPort: 9630,
|
||||
StakingPort: 9631,
|
||||
WaitHealthy: true,
|
||||
},
|
||||
{
|
||||
Name: "lux-l2",
|
||||
Type: "op",
|
||||
NetworkID: 200200,
|
||||
HTTPPort: 8545,
|
||||
DependsOn: []string{"lux-l1"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("Validate", func(t *testing.T) {
|
||||
err := manifest.Validate()
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("SaveAndLoad", func(t *testing.T) {
|
||||
// Save as YAML
|
||||
yamlPath := "/tmp/test-stack.yaml"
|
||||
err := manifest.Save(yamlPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Load back
|
||||
loaded, err := orchestrator.LoadManifest(yamlPath)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, manifest.Name, loaded.Name)
|
||||
require.Len(t, loaded.Engines, 2)
|
||||
|
||||
// Save as JSON
|
||||
jsonPath := "/tmp/test-stack.json"
|
||||
err = manifest.Save(jsonPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Load JSON
|
||||
loaded, err = orchestrator.LoadManifest(jsonPath)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, manifest.Name, loaded.Name)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPortManager(t *testing.T) {
|
||||
pm := orchestrator.NewPortManager()
|
||||
|
||||
t.Run("AllocatePorts", func(t *testing.T) {
|
||||
// Allocate HTTP ports
|
||||
port1 := pm.AllocateHTTP()
|
||||
port2 := pm.AllocateHTTP()
|
||||
require.NotEqual(t, port1, port2)
|
||||
|
||||
// Allocate P2P ports
|
||||
p2p1 := pm.AllocateP2P()
|
||||
p2p2 := pm.AllocateP2P()
|
||||
require.NotEqual(t, p2p1, p2p2)
|
||||
|
||||
// Release and reallocate
|
||||
pm.Release(port1)
|
||||
port3 := pm.AllocateHTTP()
|
||||
// May or may not reuse port1 depending on system state
|
||||
require.NotEqual(t, port3, port2)
|
||||
})
|
||||
|
||||
t.Run("ReservePorts", func(t *testing.T) {
|
||||
pm := orchestrator.NewPortManager()
|
||||
|
||||
// Reserve specific ports
|
||||
err := pm.Reserve(20000, 20001, 20002)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Try to reserve again - should fail
|
||||
err = pm.Reserve(20001)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMetricsCollector(t *testing.T) {
|
||||
mc := orchestrator.NewMetricsCollector()
|
||||
|
||||
t.Run("RecordAndRetrieve", func(t *testing.T) {
|
||||
// Record metrics
|
||||
mc.Record("engine1", map[string]interface{}{
|
||||
"uptime_seconds": 100.0,
|
||||
"running": true,
|
||||
"peers": 5,
|
||||
})
|
||||
|
||||
// Retrieve metrics
|
||||
metrics := mc.Get("engine1")
|
||||
require.NotNil(t, metrics)
|
||||
require.Equal(t, "engine1", metrics.Name)
|
||||
require.Equal(t, 100.0, metrics.Values["uptime_seconds"])
|
||||
|
||||
// Record more for history
|
||||
for i := 0; i < 5; i++ {
|
||||
mc.Record("engine1", map[string]interface{}{
|
||||
"uptime_seconds": float64(100 + i*10),
|
||||
"running": true,
|
||||
})
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
|
||||
metrics = mc.Get("engine1")
|
||||
require.Len(t, metrics.History, 6) // Initial + 5 more
|
||||
})
|
||||
|
||||
t.Run("Summary", func(t *testing.T) {
|
||||
mc := orchestrator.NewMetricsCollector()
|
||||
|
||||
mc.Record("engine1", map[string]interface{}{
|
||||
"uptime_seconds": 100.0,
|
||||
"running": true,
|
||||
})
|
||||
mc.Record("engine2", map[string]interface{}{
|
||||
"uptime_seconds": 200.0,
|
||||
"running": true,
|
||||
})
|
||||
mc.Record("engine3", map[string]interface{}{
|
||||
"uptime_seconds": 50.0,
|
||||
"running": false,
|
||||
})
|
||||
|
||||
summary := mc.Summary()
|
||||
require.Equal(t, 3, summary["engines"])
|
||||
require.Equal(t, 350.0, summary["total_uptime_seconds"])
|
||||
require.Equal(t, 2, summary["healthy_engines"])
|
||||
})
|
||||
}
|
||||
+20
-20
@@ -3,7 +3,7 @@ set -e
|
||||
|
||||
export RUN_E2E="true"
|
||||
# e.g.,
|
||||
# ./scripts/tests.e2e.sh $DEFAULT_VERSION1 $DEFAULT_VERSION2 $DEFAULT_SUBNET_EVM_VERSION
|
||||
# ./scripts/tests.e2e.sh $DEFAULT_VERSION1 $DEFAULT_VERSION2 $DEFAULT_EVM_VERSION
|
||||
if ! [[ "$0" =~ scripts/tests.e2e.sh ]]; then
|
||||
echo "must be run from repository root"
|
||||
exit 255
|
||||
@@ -11,29 +11,29 @@ fi
|
||||
|
||||
DEFAULT_VERSION_1=1.22.80
|
||||
DEFAULT_VERSION_2=1.22.79
|
||||
DEFAULT_SUBNET_EVM_VERSION=0.8.35
|
||||
DEFAULT_EVM_VERSION=0.8.35
|
||||
|
||||
if [ $# == 0 ]; then
|
||||
VERSION_1=$DEFAULT_VERSION_1
|
||||
VERSION_2=$DEFAULT_VERSION_2
|
||||
SUBNET_EVM_VERSION=$DEFAULT_SUBNET_EVM_VERSION
|
||||
EVM_VERSION=$DEFAULT_EVM_VERSION
|
||||
else
|
||||
VERSION_1=$1
|
||||
if [[ -z "${VERSION_1}" ]]; then
|
||||
echo "Missing version argument!"
|
||||
echo "Usage: ${0} [VERSION_1] [VERSION_2] [SUBNET_EVM_VERSION]" >> /dev/stderr
|
||||
echo "Usage: ${0} [VERSION_1] [VERSION_2] [EVM_VERSION]" >> /dev/stderr
|
||||
exit 255
|
||||
fi
|
||||
VERSION_2=$2
|
||||
if [[ -z "${VERSION_2}" ]]; then
|
||||
echo "Missing version argument!"
|
||||
echo "Usage: ${0} [VERSION_1] [VERSION_2] [SUBNET_EVM_VERSION]" >> /dev/stderr
|
||||
echo "Usage: ${0} [VERSION_1] [VERSION_2] [EVM_VERSION]" >> /dev/stderr
|
||||
exit 255
|
||||
fi
|
||||
SUBNET_EVM_VERSION=$3
|
||||
if [[ -z "${SUBNET_EVM_VERSION}" ]]; then
|
||||
EVM_VERSION=$3
|
||||
if [[ -z "${EVM_VERSION}" ]]; then
|
||||
echo "Missing version argument!"
|
||||
echo "Usage: ${0} [VERSION_1] [VERSION_2] [SUBNET_EVM_VERSION]" >> /dev/stderr
|
||||
echo "Usage: ${0} [VERSION_1] [VERSION_2] [EVM_VERSION]" >> /dev/stderr
|
||||
exit 255
|
||||
fi
|
||||
fi
|
||||
@@ -41,7 +41,7 @@ fi
|
||||
echo "Running e2e tests with:"
|
||||
echo VERSION_1: ${VERSION_1}
|
||||
echo VERSION_2: ${VERSION_2}
|
||||
echo SUBNET_EVM_VERSION: ${SUBNET_EVM_VERSION}
|
||||
echo EVM_VERSION: ${EVM_VERSION}
|
||||
|
||||
if [ ! -f /tmp/node-v${VERSION_1}/node ]
|
||||
then
|
||||
@@ -115,7 +115,7 @@ then
|
||||
find /tmp/node-v${VERSION_2}
|
||||
fi
|
||||
|
||||
if [ ! -f /tmp/evm-v${SUBNET_EVM_VERSION}/evm ]
|
||||
if [ ! -f /tmp/evm-v${EVM_VERSION}/evm ]
|
||||
then
|
||||
############################
|
||||
# download evm plugin
|
||||
@@ -123,22 +123,22 @@ then
|
||||
GOARCH=$(go env GOARCH)
|
||||
GOOS=$(go env GOOS)
|
||||
# evm releases are raw binaries named evm-plugin-{os}-{arch}
|
||||
DOWNLOAD_URL=https://github.com/luxfi/evm/releases/download/v${SUBNET_EVM_VERSION}/evm-plugin-linux-${GOARCH}
|
||||
DOWNLOAD_URL=https://github.com/luxfi/evm/releases/download/v${EVM_VERSION}/evm-plugin-linux-${GOARCH}
|
||||
if [[ ${GOOS} == "darwin" ]]; then
|
||||
DOWNLOAD_URL=https://github.com/luxfi/evm/releases/download/v${SUBNET_EVM_VERSION}/evm-plugin-darwin-${GOARCH}
|
||||
DOWNLOAD_URL=https://github.com/luxfi/evm/releases/download/v${EVM_VERSION}/evm-plugin-darwin-${GOARCH}
|
||||
fi
|
||||
|
||||
rm -rf /tmp/evm-v${SUBNET_EVM_VERSION}
|
||||
mkdir -p /tmp/evm-v${SUBNET_EVM_VERSION}
|
||||
rm -rf /tmp/evm-v${EVM_VERSION}
|
||||
mkdir -p /tmp/evm-v${EVM_VERSION}
|
||||
|
||||
echo "downloading evm ${SUBNET_EVM_VERSION} at ${DOWNLOAD_URL}"
|
||||
curl -L ${DOWNLOAD_URL} -o /tmp/evm-v${SUBNET_EVM_VERSION}/evm
|
||||
chmod +x /tmp/evm-v${SUBNET_EVM_VERSION}/evm
|
||||
echo "downloading evm ${EVM_VERSION} at ${DOWNLOAD_URL}"
|
||||
curl -L ${DOWNLOAD_URL} -o /tmp/evm-v${EVM_VERSION}/evm
|
||||
chmod +x /tmp/evm-v${EVM_VERSION}/evm
|
||||
|
||||
# NOTE: We are copying the evm binary here to a plugin hardcoded as srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy which corresponds to the VM name `subnetevm` used as such in the test
|
||||
mkdir -p /tmp/node-v${VERSION_1}/plugins/
|
||||
cp /tmp/evm-v${SUBNET_EVM_VERSION}/evm /tmp/node-v${VERSION_1}/plugins/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy
|
||||
find /tmp/evm-v${SUBNET_EVM_VERSION}/evm
|
||||
cp /tmp/evm-v${EVM_VERSION}/evm /tmp/node-v${VERSION_1}/plugins/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy
|
||||
find /tmp/evm-v${EVM_VERSION}/evm
|
||||
fi
|
||||
############################
|
||||
echo "building runner"
|
||||
@@ -187,4 +187,4 @@ echo "running e2e tests"
|
||||
--grpc-gateway-endpoint="0.0.0.0:8081" \
|
||||
--node-path-1=/tmp/node-v${VERSION_1}/node \
|
||||
--node-path-2=/tmp/node-v${VERSION_2}/node \
|
||||
--subnet-evm-path=/tmp/evm-v${SUBNET_EVM_VERSION}/evm
|
||||
--evm-path=/tmp/evm-v${EVM_VERSION}/evm
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user