fix build

This commit is contained in:
Zach Kelling
2026-01-14 19:56:11 -08:00
parent deae88ca44
commit 160e25c144
49 changed files with 410 additions and 382 deletions
+1 -1
View File
@@ -7,7 +7,7 @@
## Project Overview ## 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, subnets, 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, chains (L2 blockchains), and complex network topologies.
## Essential Commands ## Essential Commands
+12 -12
View File
@@ -155,8 +155,8 @@ netrunner control start \
--global-node-config '{"http-host":"0.0.0.0"}' --global-node-config '{"http-host":"0.0.0.0"}'
``` ```
`--plugin-dir` and `--blockchain-specs` are parameters relevant to subnet operation. `--plugin-dir` and `--blockchain-specs` are parameters relevant to chain (L2 blockchain) operation.
See the [subnet](#network-runner-rpc-server-subnet-evm-example) section for details about how to run subnets. See the [chain deployment](#network-runner-rpc-server-subnet-evm-example) section for details about how to run chains.
The network-runner supports node node configuration at different levels. The network-runner supports node node configuration at different levels.
@@ -299,7 +299,7 @@ curl -X POST -k http://localhost:8081/v1/control/removesnapshot -d '{"snapshot_n
netrunner control remove-snapshot snapshotName netrunner control remove-snapshot snapshotName
``` ```
To create 1 validated subnet, with all existing nodes as participants (requires network restart): To create 1 validated network (validator set), with all existing nodes as participants (requires network restart):
```bash ```bash
curl -X POST -k http://localhost:8081/v1/control/createsubnets -d '[{}]' curl -X POST -k http://localhost:8081/v1/control/createsubnets -d '[{}]'
@@ -308,7 +308,7 @@ curl -X POST -k http://localhost:8081/v1/control/createsubnets -d '[{}]'
netrunner control create-subnets '[{}]' netrunner control create-subnets '[{}]'
``` ```
To create 1 validated subnet, with some of existing nodes as participants (requires network restart): To create 1 validated network (validator set), with some of existing nodes as participants (requires network restart):
```bash ```bash
curl -X POST -k http://localhost:8081/v1/control/createsubnets -d '[{"participants": ["node1", "node2"]}]' curl -X POST -k http://localhost:8081/v1/control/createsubnets -d '[{"participants": ["node1", "node2"]}]'
@@ -317,7 +317,7 @@ curl -X POST -k http://localhost:8081/v1/control/createsubnets -d '[{"participan
netrunner control create-subnets '[{"participants": ["node1", "node2"]}]' netrunner control create-subnets '[{"participants": ["node1", "node2"]}]'
``` ```
To create 1 validated subnet, with some of existing nodes and another new node as participants (requires network restart): To create 1 validated network (validator set), with some of existing nodes and another new node as participants (requires network restart):
```bash ```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/createsubnets -d '[{"participants": ["node1", "node2", "testNode"]}]'
@@ -327,7 +327,7 @@ netrunner control create-subnets '[{"participants": ["node1", "node2", "testNode
``` ```
To create N validated subnets (requires network restart): To create N validated networks (validator sets) (requires network restart):
```bash ```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/createsubnets -d '[{}, {"participants": ["node1", "node2", "node3"]}, {"participants": ["node1", "node2", "testNode"]}]'
@@ -337,7 +337,7 @@ netrunner control create-subnets '[{}, {"participants": ["node1", "node2", "node
``` ```
To create a blockchain without a subnet id (requires network restart): To create a blockchain without a network id (requires network restart):
```bash ```bash
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'"}]}' curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'"}]}'
@@ -355,7 +355,7 @@ curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginD
netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_CONTENTS'"}]' --plugin-dir $PLUGIN_DIR netrunner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_CONTENTS'"}]' --plugin-dir $PLUGIN_DIR
``` ```
To create a blockchain with a subnet id (does not require restart): To create a blockchain with a network id (does not require restart):
```bash ```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'", "subnet_id": "'$SUBNET_ID'"}]}'
@@ -364,7 +364,7 @@ curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginD
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'", "subnet_id": "'$SUBNET_ID'"}]' --plugin-dir $PLUGIN_DIR
``` ```
To create a blockchain with a subnet id, and chain config, network upgrade and subnet config file paths (requires network restart): To create a blockchain with a network id, and chain config, network upgrade and network config file paths (requires network restart):
```bash ```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'", "subnet_id": "'$SUBNET_ID'", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "subnet_config": "'$SUBNET_CONFIG_PATH'"}]}'
@@ -373,7 +373,7 @@ curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginD
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'", "subnet_id": "'$SUBNET_ID'", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "subnet_config": "'$SUBNET_CONFIG_PATH'"}]' --plugin-dir $PLUGIN_DIR
``` ```
To create a blockchain with a new subnet id with select nodes as participants (requires network restart): To create a blockchain with a new network id 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-subnets`)
```bash ```bash
@@ -383,7 +383,7 @@ curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginD
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'", "subnet_spec": "{"participants": ["node1", "node2", "testNode"]}]' --plugin-dir $PLUGIN_DIR
``` ```
To create two blockchains in two disjoint subnets (not shared validators), and where all validators have bls keys (parcipants new to the network): To create two blockchains in two disjoint networks (not shared validators), and where all validators have bls keys (participants new to the network):
```bash ```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'", "subnet_spec": {"participants": ["new_node1", "new_node2"]}},{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_spec": {"participants": ["new_node3", "new_node4"]}}]'
@@ -666,7 +666,7 @@ netrunner control start \
curl -X POST -k http://localhost:8081/v1/control/status -d '' curl -X POST -k http://localhost:8081/v1/control/status -d ''
``` ```
Blockchain config file, network upgrade file, and subnet config file paths can be optionally specified at network start, eg: Blockchain config file, network upgrade file, and network config file paths can be optionally specified at network start, eg:
```bash ```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":"subnetevm","genesis":"/tmp/subnet-evm.genesis.json","chain_config":"'$CHAIN_CONFIG_PATH'","network_upgrade":"'$NETWORK_UPGRADE_PATH'","subnet_config":"'$SUBNET_CONFIG_PATH'"}]}'
+2 -2
View File
@@ -3,8 +3,8 @@ package api
import ( import (
"fmt" "fmt"
"github.com/luxfi/vm/vms/exchangevm" "github.com/luxfi/sdk/api/exchangevm"
"github.com/luxfi/vm/vms/platformvm" "github.com/luxfi/sdk/api/platformvm"
"github.com/luxfi/sdk/api/admin" "github.com/luxfi/sdk/api/admin"
"github.com/luxfi/sdk/api/health" "github.com/luxfi/sdk/api/health"
"github.com/luxfi/sdk/api/indexer" "github.com/luxfi/sdk/api/indexer"
+2 -2
View File
@@ -7,8 +7,8 @@ import (
ethereum "github.com/luxfi/geth" ethereum "github.com/luxfi/geth"
"github.com/luxfi/geth/common" "github.com/luxfi/geth/common"
"github.com/luxfi/geth/core/types" "github.com/luxfi/geth/core/types"
"github.com/luxfi/vm/vms/exchangevm" "github.com/luxfi/sdk/api/exchangevm"
"github.com/luxfi/vm/vms/platformvm" "github.com/luxfi/sdk/api/platformvm"
"github.com/luxfi/rpc" "github.com/luxfi/rpc"
"github.com/luxfi/sdk/api/admin" "github.com/luxfi/sdk/api/admin"
"github.com/luxfi/sdk/api/health" "github.com/luxfi/sdk/api/health"
+2 -2
View File
@@ -6,7 +6,7 @@ import (
api "github.com/luxfi/netrunner/api" api "github.com/luxfi/netrunner/api"
admin "github.com/luxfi/sdk/api/admin" admin "github.com/luxfi/sdk/api/admin"
exchangevm "github.com/luxfi/vm/vms/exchangevm" exchangevm "github.com/luxfi/sdk/api/exchangevm"
indexer "github.com/luxfi/sdk/api/indexer" indexer "github.com/luxfi/sdk/api/indexer"
@@ -14,7 +14,7 @@ import (
mock "github.com/stretchr/testify/mock" mock "github.com/stretchr/testify/mock"
platformvm "github.com/luxfi/vm/vms/platformvm" platformvm "github.com/luxfi/sdk/api/platformvm"
) )
// Client is an autogenerated mock type for the Client type // Client is an autogenerated mock type for the Client type
+1 -1
View File
@@ -12,7 +12,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/local" "github.com/luxfi/netrunner/local"
"github.com/luxfi/netrunner/rpcpb" "github.com/luxfi/netrunner/rpcpb"
"google.golang.org/grpc" "google.golang.org/grpc"
+2 -3
View File
@@ -14,8 +14,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/log/level"
"github.com/luxfi/netrunner/client" "github.com/luxfi/netrunner/client"
"github.com/luxfi/netrunner/local" "github.com/luxfi/netrunner/local"
"github.com/luxfi/netrunner/rpcpb" "github.com/luxfi/netrunner/rpcpb"
@@ -49,7 +48,7 @@ func NewCommand() *cobra.Command {
Short: "Start a network runner controller.", Short: "Start a network runner controller.",
} }
cmd.PersistentFlags().StringVar(&logLevel, "log-level", level.Info.String(), "log level") cmd.PersistentFlags().StringVar(&logLevel, "log-level", log.InfoLevel.String(), "log level")
cmd.PersistentFlags().StringVar(&logDir, "log-dir", "", "log directory") cmd.PersistentFlags().StringVar(&logDir, "log-dir", "", "log directory")
cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "0.0.0.0:9000", "server endpoint") cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "0.0.0.0:9000", "server endpoint")
cmd.PersistentFlags().DurationVar(&dialTimeout, "dial-timeout", 10*time.Second, "server dial timeout") cmd.PersistentFlags().DurationVar(&dialTimeout, "dial-timeout", 10*time.Second, "server dial timeout")
+1 -1
View File
@@ -6,7 +6,7 @@ package commands
import ( import (
"fmt" "fmt"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
+1 -1
View File
@@ -11,7 +11,7 @@ import (
"text/tabwriter" "text/tabwriter"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/engines" "github.com/luxfi/netrunner/engines"
_ "github.com/luxfi/netrunner/engines/geth" _ "github.com/luxfi/netrunner/engines/geth"
+1 -1
View File
@@ -6,7 +6,7 @@ package commands
import ( import (
"fmt" "fmt"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"text/tabwriter" "text/tabwriter"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/orchestrator" "github.com/luxfi/netrunner/orchestrator"
"github.com/spf13/cobra" "github.com/spf13/cobra"
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"os" "os"
"text/tabwriter" "text/tabwriter"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/engines" "github.com/luxfi/netrunner/engines"
"github.com/spf13/cobra" "github.com/spf13/cobra"
+2 -3
View File
@@ -10,8 +10,7 @@ import (
"os/signal" "os/signal"
"syscall" "syscall"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/log/level"
"github.com/luxfi/netrunner/cmd/netrunner/commands" "github.com/luxfi/netrunner/cmd/netrunner/commands"
"github.com/luxfi/netrunner/cmd/server" "github.com/luxfi/netrunner/cmd/server"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@@ -25,7 +24,7 @@ var (
func main() { func main() {
// Setup logger - use development logger for console output // Setup logger - use development logger for console output
logger := log.NewTestLogger(level.Info) logger := log.NewTestLogger(log.InfoLevel)
// Setup root command // Setup root command
rootCmd := &cobra.Command{ rootCmd := &cobra.Command{
+3 -4
View File
@@ -7,8 +7,7 @@ import (
"context" "context"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/log/level"
"github.com/luxfi/netrunner/client" "github.com/luxfi/netrunner/client"
"github.com/luxfi/netrunner/utils/constants" "github.com/luxfi/netrunner/utils/constants"
"github.com/luxfi/netrunner/ux" "github.com/luxfi/netrunner/ux"
@@ -29,7 +28,7 @@ func NewCommand() *cobra.Command {
RunE: pingFunc, RunE: pingFunc,
} }
cmd.PersistentFlags().StringVar(&logLevel, "log-level", level.Info.String(), "log level") cmd.PersistentFlags().StringVar(&logLevel, "log-level", log.InfoLevel.String(), "log level")
cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "0.0.0.0:9000", "server endpoint") cmd.PersistentFlags().StringVar(&endpoint, "endpoint", "0.0.0.0:9000", "server endpoint")
cmd.PersistentFlags().DurationVar(&dialTimeout, "dial-timeout", 10*time.Second, "server dial timeout") cmd.PersistentFlags().DurationVar(&dialTimeout, "dial-timeout", 10*time.Second, "server dial timeout")
cmd.PersistentFlags().DurationVar(&requestTimeout, "request-timeout", 10*time.Second, "client request timeout") cmd.PersistentFlags().DurationVar(&requestTimeout, "request-timeout", 10*time.Second, "client request timeout")
@@ -44,7 +43,7 @@ func pingFunc(*cobra.Command, []string) error {
} }
lcfg := log.Config{ lcfg := log.Config{
DisplayLevel: lvl, DisplayLevel: lvl,
LogLevel: level.Off, LogLevel: log.Disabled,
} }
logFactory := log.NewFactoryWithConfig(lcfg) logFactory := log.NewFactoryWithConfig(lcfg)
logger, err := logFactory.Make(constants.LogNameControl) logger, err := logFactory.Make(constants.LogNameControl)
+2 -3
View File
@@ -11,8 +11,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/log/level"
"github.com/luxfi/netrunner/server" "github.com/luxfi/netrunner/server"
"github.com/luxfi/netrunner/utils" "github.com/luxfi/netrunner/utils"
"github.com/luxfi/netrunner/utils/constants" "github.com/luxfi/netrunner/utils/constants"
@@ -44,7 +43,7 @@ func NewCommand() *cobra.Command {
Args: cobra.ExactArgs(0), Args: cobra.ExactArgs(0),
} }
cmd.PersistentFlags().StringVar(&logLevel, "log-level", level.Info.String(), "log level for server logs") cmd.PersistentFlags().StringVar(&logLevel, "log-level", log.InfoLevel.String(), "log level for server logs")
cmd.PersistentFlags().StringVar(&logDir, "log-dir", "", "log directory") cmd.PersistentFlags().StringVar(&logDir, "log-dir", "", "log directory")
cmd.PersistentFlags().StringVar(&port, "port", ":9000", "server port") cmd.PersistentFlags().StringVar(&port, "port", ":9000", "server port")
cmd.PersistentFlags().StringVar(&gwPort, "grpc-gateway-port", ":9001", "grpc-gateway server port") cmd.PersistentFlags().StringVar(&gwPort, "grpc-gateway-port", ":9001", "grpc-gateway server port")
+7 -7
View File
@@ -40,7 +40,7 @@ type Config struct {
// Upgrade configuration files // Upgrade configuration files
UpgradeConfigFiles map[string]string `json:"upgradeConfigFiles"` UpgradeConfigFiles map[string]string `json:"upgradeConfigFiles"`
// Subnet configuration files // Network (validator set) configuration files
SubnetConfigFiles map[string]string `json:"subnetConfigFiles"` SubnetConfigFiles map[string]string `json:"subnetConfigFiles"`
} }
``` ```
@@ -187,10 +187,10 @@ type BlockchainSpec struct {
// Genesis data (file path or JSON string) // Genesis data (file path or JSON string)
Genesis []byte `json:"genesis"` Genesis []byte `json:"genesis"`
// Subnet ID (optional) // Network ID (optional) - identifies the validator set
SubnetID *string `json:"subnet_id"` SubnetID *string `json:"subnet_id"`
// Subnet specification // Network specification (validator set configuration)
SubnetSpec *SubnetSpec `json:"subnet_spec"` SubnetSpec *SubnetSpec `json:"subnet_spec"`
// Chain configuration // Chain configuration
@@ -304,21 +304,21 @@ type BlockchainSpec struct {
} }
``` ```
## Subnet Configuration ## Network Configuration (Validator Sets)
### Subnet Spec Structure ### Network Spec Structure
```go ```go
type SubnetSpec struct { type SubnetSpec struct {
// Validator participants // Validator participants
Participants []string `json:"participants"` Participants []string `json:"participants"`
// Subnet configuration // Network configuration
SubnetConfig []byte `json:"subnet_config"` SubnetConfig []byte `json:"subnet_config"`
} }
``` ```
### Elastic Subnet Configuration ### Elastic Network Configuration
```go ```go
type ElasticSubnetSpec struct { type ElasticSubnetSpec struct {
+9 -9
View File
@@ -5,14 +5,14 @@ description: Lux Netrunner - Network orchestration and testing framework for Lux
# Lux Netrunner # 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, subnets, 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, chains (L2 blockchains), and complex network topologies.
## Overview ## Overview
Netrunner simplifies blockchain network testing by providing: Netrunner simplifies blockchain network testing by providing:
- **Dynamic network management** - Create, modify, and control networks on the fly - **Dynamic network management** - Create, modify, and control networks on the fly
- **Multi-chain support** - Deploy and test multiple blockchains simultaneously - **Multi-chain support** - Deploy and test multiple blockchains simultaneously
- **Subnet orchestration** - Easily create and manage subnets with custom validators - **Network orchestration** - Easily create and manage networks (validator sets) with custom validators
- **Testing automation** - Built-in support for various testing scenarios - **Testing automation** - Built-in support for various testing scenarios
- **Network snapshots** - Save and restore complete network states - **Network snapshots** - Save and restore complete network states
- **Chaos engineering** - Simulate failures and network partitions - **Chaos engineering** - Simulate failures and network partitions
@@ -106,14 +106,14 @@ netrunner control health --endpoint="0.0.0.0:8080"
netrunner control uris --endpoint="0.0.0.0:8080" netrunner control uris --endpoint="0.0.0.0:8080"
``` ```
### Deploy a Subnet ### Deploy a Chain
```bash ```bash
# Create subnet with specific validators # Create network (validator set) with specific validators
netrunner control create-subnets \ netrunner control create-subnets \
'[{"participants": ["node1", "node2", "node3"]}]' '[{"participants": ["node1", "node2", "node3"]}]'
# Deploy a blockchain on the subnet # Deploy a blockchain on the network
netrunner control create-blockchains \ netrunner control create-blockchains \
'[{ '[{
"vm_name": "subnetevm", "vm_name": "subnetevm",
@@ -132,7 +132,7 @@ netrunner control create-blockchains \
### Integration Testing ### Integration Testing
- Multi-chain interaction testing - Multi-chain interaction testing
- Cross-subnet communication - Cross-chain communication
- API endpoint validation - API endpoint validation
- Transaction throughput testing - Transaction throughput testing
@@ -227,9 +227,9 @@ curl -X POST -k http://localhost:8081/v1/control/savesnapshot -d '{
- `netrunner control resume-node` - Resume a node - `netrunner control resume-node` - Resume a node
- `netrunner control restart-node` - Restart a node - `netrunner control restart-node` - Restart a node
### Subnet Commands ### Network Commands
- `netrunner control create-subnets` - Create subnets - `netrunner control create-subnets` - Create networks (validator sets)
- `netrunner control create-blockchains` - Deploy blockchains - `netrunner control create-blockchains` - Deploy blockchains (chains)
### Snapshot Commands ### Snapshot Commands
- `netrunner control save-snapshot` - Save network state (stops network) - `netrunner control save-snapshot` - Save network state (stops network)
+12 -12
View File
@@ -13,7 +13,7 @@ Network orchestration in Netrunner allows you to:
- Dynamically create and manage multi-node networks - Dynamically create and manage multi-node networks
- Configure node topologies and relationships - Configure node topologies and relationships
- Manage node lifecycle (start, stop, pause, resume) - Manage node lifecycle (start, stop, pause, resume)
- Coordinate subnet and blockchain deployments - Coordinate network (validator set) and blockchain deployments
- Simulate network conditions and failures - Simulate network conditions and failures
## Core Components ## Core Components
@@ -154,21 +154,21 @@ netrunner control pause-node node1
netrunner control resume-node node1 netrunner control resume-node node1
``` ```
## Subnet Orchestration ## Network Orchestration (Validator Sets)
### Creating Subnets ### Creating Networks
Create subnets with specific validators: Create networks (validator sets) with specific validators:
```bash ```bash
# Create subnet with all nodes as validators # Create network with all nodes as validators
netrunner control create-subnets '[{}]' netrunner control create-subnets '[{}]'
# Create subnet with specific validators # Create network with specific validators
netrunner control create-subnets \ netrunner control create-subnets \
'[{"participants": ["node1", "node2", "node3"]}]' '[{"participants": ["node1", "node2", "node3"]}]'
# Create multiple subnets # Create multiple networks
netrunner control create-subnets \ netrunner control create-subnets \
'[ '[
{"participants": ["node1", "node2"]}, {"participants": ["node1", "node2"]},
@@ -176,9 +176,9 @@ netrunner control create-subnets \
]' ]'
``` ```
### Elastic Subnets ### Elastic Networks
Configure elastic subnets with custom parameters: Configure elastic networks with custom parameters:
```go ```go
type ElasticSubnetSpec struct { type ElasticSubnetSpec struct {
@@ -204,7 +204,7 @@ type ElasticSubnetSpec struct {
### Deploying Custom VMs ### Deploying Custom VMs
Deploy custom virtual machines on subnets: Deploy custom virtual machines on networks:
```bash ```bash
# Deploy a single blockchain # Deploy a single blockchain
@@ -371,7 +371,7 @@ netrunner control start \
# Wait for network health # Wait for network health
netrunner control health --endpoint="0.0.0.0:8080" netrunner control health --endpoint="0.0.0.0:8080"
# Create a subnet # Create a network (validator set)
netrunner control create-subnets \ netrunner control create-subnets \
'[{"participants": ["node1", "node2", "node3"]}]' '[{"participants": ["node1", "node2", "node3"]}]'
@@ -398,7 +398,7 @@ netrunner control stop --endpoint="0.0.0.0:8080"
1. **Nodes fail to start**: Check binary path and permissions 1. **Nodes fail to start**: Check binary path and permissions
2. **Network unhealthy**: Verify port availability and firewall rules 2. **Network unhealthy**: Verify port availability and firewall rules
3. **Subnet creation fails**: Ensure sufficient validators 3. **Network creation fails**: Ensure sufficient validators
4. **Snapshot restore fails**: Check disk space and file permissions 4. **Snapshot restore fails**: Check disk space and file permissions
### Debug Commands ### Debug Commands
+15 -15
View File
@@ -5,7 +5,7 @@ description: Complete guide to setting up test networks with Lux Netrunner
# Test Network Setup # Test Network Setup
This guide walks through setting up various test network configurations using Lux Netrunner, from simple single-node setups to complex multi-subnet deployments. This guide walks through setting up various test network configurations using Lux Netrunner, from simple single-node setups to complex multi-chain deployments.
## Prerequisites ## Prerequisites
@@ -146,9 +146,9 @@ netrunner control start \
}' }'
``` ```
## Subnet Networks ## Validator Networks
### Create a Permissioned Subnet ### Create a Permissioned Network
```bash ```bash
# Start the network # Start the network
@@ -160,7 +160,7 @@ netrunner control start \
# Wait for health # Wait for health
netrunner control health netrunner control health
# Create subnet with all nodes # Create network with all nodes
netrunner control create-subnets '[{}]' netrunner control create-subnets '[{}]'
# Or create with specific validators # Or create with specific validators
@@ -168,13 +168,13 @@ netrunner control create-subnets \
'[{"participants": ["node1", "node2", "node3"]}]' '[{"participants": ["node1", "node2", "node3"]}]'
``` ```
### Create an Elastic Subnet ### Create an Elastic Network
Elastic subnets allow dynamic validator sets: Elastic networks allow dynamic validator sets:
```bash ```bash
# Create elastic subnet configuration # Create elastic network configuration
cat > elastic-subnet.json <<EOF cat > elastic-network.json <<EOF
{ {
"AssetName": "TestToken", "AssetName": "TestToken",
"AssetSymbol": "TEST", "AssetSymbol": "TEST",
@@ -193,8 +193,8 @@ cat > elastic-subnet.json <<EOF
} }
EOF EOF
# Create elastic subnet # Create elastic network
netrunner control create-elastic-subnet elastic-subnet.json netrunner control create-elastic-subnet elastic-network.json
``` ```
## Custom Blockchain Deployment ## Custom Blockchain Deployment
@@ -325,12 +325,12 @@ netrunner control start \
# Wait for bootstrap # Wait for bootstrap
netrunner control health netrunner control health
# Create subnet with validators # Create network (validator set) with validators
netrunner control create-subnets '[{ netrunner control create-subnets '[{
"participants": ["node1", "node2", "node3"] "participants": ["node1", "node2", "node3"]
}]' }]'
# Get subnet info # Get network info
netrunner control status netrunner control status
``` ```
@@ -426,7 +426,7 @@ netrunner control start \
--number-of-nodes=5 \ --number-of-nodes=5 \
--node-path ${LUXD_EXEC_PATH} --node-path ${LUXD_EXEC_PATH}
# Create subnets and blockchains # Create networks (validator sets) and blockchains
netrunner control create-subnets '[{"participants": ["node1", "node2"]}]' netrunner control create-subnets '[{"participants": ["node1", "node2"]}]'
# Save snapshot # Save snapshot
@@ -478,8 +478,8 @@ netrunner control health --endpoint=${ENDPOINT}
netrunner control save-snapshot test1-complete netrunner control save-snapshot test1-complete
netrunner control stop --endpoint=${ENDPOINT} netrunner control stop --endpoint=${ENDPOINT}
# Test 2: Subnet network # Test 2: Network (validator set) deployment
echo "Test 2: Subnet deployment" echo "Test 2: Network deployment"
netrunner control load-snapshot test1-complete \ netrunner control load-snapshot test1-complete \
--endpoint=${ENDPOINT} --endpoint=${ENDPOINT}
+10 -10
View File
@@ -193,12 +193,12 @@ IMPORT_TX=$(curl -X POST --data '{
echo "Import TX: ${IMPORT_TX}" echo "Import TX: ${IMPORT_TX}"
``` ```
### Subnet Testing ### Network Testing
#### Subnet Creation and Validation #### Network Creation and Validation
```go ```go
func TestSubnetCreation(t *testing.T) { func TestNetworkCreation(t *testing.T) {
ctx := context.Background() ctx := context.Background()
// Start network // Start network
@@ -208,16 +208,16 @@ func TestSubnetCreation(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
defer network.Stop(ctx) defer network.Stop(ctx)
// Create subnet with 3 validators // Create network (validator set) with 3 validators
subnetSpec := &netrunner.SubnetSpec{ networkSpec := &netrunner.SubnetSpec{
Participants: []string{"node1", "node2", "node3"}, Participants: []string{"node1", "node2", "node3"},
} }
subnetID, err := network.CreateSubnet(ctx, subnetSpec) networkID, err := network.CreateSubnet(ctx, networkSpec)
require.NoError(t, err) require.NoError(t, err)
// Verify subnet validators // Verify network validators
validators, err := network.GetSubnetValidators(ctx, subnetID) validators, err := network.GetSubnetValidators(ctx, networkID)
require.NoError(t, err) require.NoError(t, err)
assert.Len(t, validators, 3) assert.Len(t, validators, 3)
} }
@@ -611,7 +611,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
test: [consensus, subnet, performance, chaos] test: [consensus, network, performance, chaos]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@@ -685,7 +685,7 @@ run_test() {
# Run all tests # Run all tests
run_test "consensus" run_test "consensus"
run_test "subnet" run_test "network"
run_test "performance" run_test "performance"
run_test "chaos" run_test "chaos"
run_test "upgrade" run_test "upgrade"
+1 -1
View File
@@ -12,7 +12,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/local" "github.com/luxfi/netrunner/local"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
) )
+3 -4
View File
@@ -9,8 +9,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/log/level"
"github.com/luxfi/netrunner/local" "github.com/luxfi/netrunner/local"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
) )
@@ -48,8 +47,8 @@ func shutdownOnSignal(
func main() { func main() {
// Create the logger // Create the logger
logFactory := log.NewFactoryWithConfig(log.Config{ logFactory := log.NewFactoryWithConfig(log.Config{
DisplayLevel: level.Info, DisplayLevel: log.InfoLevel,
LogLevel: level.Debug, LogLevel: log.DebugLevel,
}) })
logger, err := logFactory.Make("main") logger, err := logFactory.Make("main")
if err != nil { if err != nil {
+3 -4
View File
@@ -9,8 +9,7 @@ import (
"time" "time"
"github.com/luxfi/config" "github.com/luxfi/config"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/log/level"
"github.com/luxfi/netrunner/local" "github.com/luxfi/netrunner/local"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
"github.com/luxfi/netrunner/network/node" "github.com/luxfi/netrunner/network/node"
@@ -56,8 +55,8 @@ func shutdownOnSignal(
func main() { func main() {
// Create the logger // Create the logger
logFactory := log.NewFactoryWithConfig(log.Config{ logFactory := log.NewFactoryWithConfig(log.Config{
DisplayLevel: level.Info, DisplayLevel: log.InfoLevel,
LogLevel: level.Debug, LogLevel: log.DebugLevel,
}) })
logger, err := logFactory.Make("main") logger, err := logFactory.Make("main")
if err != nil { if err != nil {
+3 -4
View File
@@ -12,8 +12,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/log/level"
"github.com/luxfi/netrunner/local" "github.com/luxfi/netrunner/local"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
"github.com/luxfi/node/config" "github.com/luxfi/node/config"
@@ -107,8 +106,8 @@ func shutdownOnSignal(
func main() { func main() {
logFactory := log.NewFactoryWithConfig(log.Config{ logFactory := log.NewFactoryWithConfig(log.Config{
DisplayLevel: level.Info, DisplayLevel: log.InfoLevel,
LogLevel: level.Debug, LogLevel: log.DebugLevel,
}) })
logger, err := logFactory.Make("l2chains") logger, err := logFactory.Make("l2chains")
if err != nil { if err != nil {
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/local" "github.com/luxfi/netrunner/local"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
) )
+99 -44
View File
@@ -9,7 +9,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/local" "github.com/luxfi/netrunner/local"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
) )
@@ -35,50 +35,88 @@ func shutdownOnSignal(
close(closedOnShutdownChan) close(closedOnShutdownChan)
} }
// Zoo chain genesis for testnet (chain ID 200201)
func createZooTestnetGenesis() ([]byte, error) { func createZooTestnetGenesis() ([]byte, error) {
zooGenesis := map[string]interface{}{ data, err := os.ReadFile("/Users/z/work/lux/genesis/configs/zoo-testnet/genesis.json")
"alloc": map[string]interface{}{ if err != nil {
"0200000000000000000000000000000000000005": map[string]interface{}{ return nil, err
"balance": "0x0",
"nonce": "0x1",
"code": "0x01",
},
"9011E888251AB053B7bD1cdB598Db4f9DEd94714": map[string]interface{}{
"balance": "0x193e5939a08ce9dbd480000000",
},
},
"baseFeePerGas": "0x5d21dba00",
"config": map[string]interface{}{
"berlinBlock": 0,
"byzantiumBlock": 0,
"chainId": 200201, // Testnet chain ID
"constantinopleBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"homesteadBlock": 0,
"istanbulBlock": 0,
"londonBlock": 0,
"petersburgBlock": 0,
"subnetEVMTimestamp": 0,
"durangoTimestamp": 0,
"feeConfig": map[string]interface{}{
"gasLimit": 12000000,
"targetBlockRate": 2,
"minBaseFee": 25000000000,
"targetGas": 15000000,
"baseFeeChangeDenominator": 36,
"minBlockGasCost": 0,
"maxBlockGasCost": 1000000,
"blockGasCostStep": 200000,
},
},
"difficulty": "0x0",
"gasLimit": "0xb71b00",
"timestamp": "0x6727e9c3",
} }
return json.Marshal(zooGenesis) return activateEVMUpgrades(data)
}
func createCorethDebugConfig(importPath string) ([]byte, error) {
cfg := map[string]interface{}{
"admin-api-enabled": true,
"eth-apis": []string{
"eth",
"eth-filter",
"net",
"web3",
"debug",
"internal-eth",
"internal-blockchain",
"internal-transaction",
"internal-account",
"admin",
},
"import-chain-data": importPath,
"log-level": "debug",
}
return json.Marshal(cfg)
}
func activateEVMUpgrades(genesisJSON []byte) ([]byte, error) {
// Force all upgrade timestamps to 0 so upgrades are active at genesis.
var genesis map[string]interface{}
if err := json.Unmarshal(genesisJSON, &genesis); err != nil {
return nil, err
}
if cfg, ok := genesis["config"].(map[string]interface{}); ok {
for _, key := range []string{
"banffBlockTimestamp",
"cortinaBlockTimestamp",
"durangoTimestamp",
"durangoBlockTimestamp",
"etnaTimestamp",
"fortunaTimestamp",
"graniteTimestamp",
"cancunTime",
"shanghaiTime",
} {
if _, exists := cfg[key]; exists {
cfg[key] = 0
}
}
}
return json.Marshal(genesis)
}
func activateCChainUpgrades(genesisJSON string) (string, error) {
var top map[string]json.RawMessage
if err := json.Unmarshal([]byte(genesisJSON), &top); err != nil {
return "", err
}
raw, ok := top["cChainGenesis"]
if !ok {
return genesisJSON, nil
}
var cChainGenesis string
if err := json.Unmarshal(raw, &cChainGenesis); err != nil {
return "", err
}
updated, err := activateEVMUpgrades([]byte(cChainGenesis))
if err != nil {
return "", err
}
updatedRaw, err := json.Marshal(string(updated))
if err != nil {
return "", err
}
top["cChainGenesis"] = updatedRaw
out, err := json.Marshal(top)
if err != nil {
return "", err
}
return string(out), nil
} }
func main() { func main() {
@@ -109,6 +147,18 @@ func run(logger log.Logger, binaryPath string) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to create testnet config: %w", err) return fmt.Errorf("failed to create testnet config: %w", err)
} }
updatedGenesis, err := activateCChainUpgrades(netConfig.Genesis)
if err != nil {
return fmt.Errorf("failed to activate C-chain upgrades: %w", err)
}
netConfig.Genesis = updatedGenesis
netConfig.Flags["track-all-chains"] = true
corethConfig, err := createCorethDebugConfig("/Users/z/work/lux/state/rlp/lux-testnet/lux-testnet-96368.rlp")
if err != nil {
return fmt.Errorf("failed to create coreth debug config: %w", err)
}
netConfig.ChainConfigFiles["C"] = string(corethConfig)
// Override ports to avoid conflict with mainnet (use 9640-9649) // Override ports to avoid conflict with mainnet (use 9640-9649)
// and update bootstrap IPs/ports accordingly // and update bootstrap IPs/ports accordingly
@@ -116,6 +166,7 @@ func run(logger log.Logger, binaryPath string) error {
for i := range netConfig.NodeConfigs { for i := range netConfig.NodeConfigs {
netConfig.NodeConfigs[i].Flags["http-port"] = 9640 + (i * 2) netConfig.NodeConfigs[i].Flags["http-port"] = 9640 + (i * 2)
netConfig.NodeConfigs[i].Flags["staking-port"] = 9641 + (i * 2) netConfig.NodeConfigs[i].Flags["staking-port"] = 9641 + (i * 2)
netConfig.NodeConfigs[i].Flags["track-all-chains"] = true
// Update bootstrap ports for non-beacon nodes // Update bootstrap ports for non-beacon nodes
if !netConfig.NodeConfigs[i].IsBeacon { if !netConfig.NodeConfigs[i].IsBeacon {
@@ -168,12 +219,16 @@ func run(logger log.Logger, binaryPath string) error {
if err != nil { if err != nil {
return fmt.Errorf("failed to create zoo testnet genesis: %w", err) return fmt.Errorf("failed to create zoo testnet genesis: %w", err)
} }
zooCorethConfig, err := createCorethDebugConfig("/Users/z/work/lux/state/rlp/zoo-testnet/zoo-testnet-200201.rlp")
if err != nil {
return fmt.Errorf("failed to create zoo testnet coreth config: %w", err)
}
zooChainSpec := []network.ChainSpec{ zooChainSpec := []network.ChainSpec{
{ {
VMName: "evm", VMName: "evm",
Genesis: zooGenesis, Genesis: zooGenesis,
ChainConfig: nil, ChainConfig: zooCorethConfig,
BlockchainName: "zootest", BlockchainName: "zootest",
}, },
} }
+9 -9
View File
@@ -59,8 +59,8 @@ engines:
- eth2-settlement - eth2-settlement
wait_healthy: true wait_healthy: true
# ZOO L2 on Lux # ZOO L2 Chain on Lux
- name: zoo-subnet - name: zoo-chain
type: lux type: lux
binary: "subnet-evm" binary: "subnet-evm"
network_id: 200200 network_id: 200200
@@ -69,13 +69,13 @@ engines:
extra: extra:
chain_id: 200200 chain_id: 200200
parent_chain: lux-mainnet parent_chain: lux-mainnet
subnet_id: "2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt" network_id: "2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt"
depends_on: depends_on:
- lux-mainnet - lux-mainnet
wait_healthy: true wait_healthy: true
# SPC L2 on Lux # SPC L2 Chain on Lux
- name: spc-subnet - name: spc-chain
type: lux type: lux
binary: "subnet-evm" binary: "subnet-evm"
network_id: 36911 network_id: 36911
@@ -84,7 +84,7 @@ engines:
extra: extra:
chain_id: 36911 chain_id: 36911
parent_chain: lux-mainnet parent_chain: lux-mainnet
subnet_id: "2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt" network_id: "2ebCneCbwthjQ1rYT41nhd7M76Hc6YmosMAQrTFhBq8qeqh6tt"
depends_on: depends_on:
- lux-mainnet - lux-mainnet
wait_healthy: true wait_healthy: true
@@ -135,16 +135,16 @@ networks:
- name: zoo - name: zoo
type: l2 type: l2
engine: zoo-subnet engine: zoo-chain
parent: lux parent: lux
chain_id: 200200 chain_id: 200200
endpoints: endpoints:
- "http://localhost:9640" - "http://localhost:9640"
- "ws://localhost:9641" - "ws://localhost:9641"
- name: spc - name: spc
type: l2 type: l2
engine: spc-subnet engine: spc-chain
parent: lux parent: lux
chain_id: 36911 chain_id: 36911
endpoints: endpoints:
+8
View File
@@ -163,3 +163,11 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
) )
replace (
github.com/luxfi/atomic => ../atomic
github.com/luxfi/consensus => ../consensus
github.com/luxfi/protocol => ../protocol
github.com/luxfi/genesis => ../genesis
github.com/luxfi/log => github.com/luxfi/logger v1.3.1
)
+14 -14
View File
@@ -21,10 +21,10 @@ import (
"github.com/luxfi/keys" "github.com/luxfi/keys"
"github.com/luxfi/genesis/pkg/genesis" "github.com/luxfi/genesis/pkg/genesis"
"github.com/luxfi/vm/vms/platformvm/reward" "github.com/luxfi/protocol/p/reward"
"github.com/luxfi/sdk/wallet/chain/x" "github.com/luxfi/sdk/wallet/chain/x"
"github.com/luxfi/vm/components/lux" "github.com/luxfi/utxo"
"github.com/luxfi/vm/components/verify" "github.com/luxfi/vm/components/verify"
"maps" "maps"
@@ -36,18 +36,18 @@ import (
"github.com/luxfi/crypto/bls" "github.com/luxfi/crypto/bls"
"github.com/luxfi/crypto/secp256k1" "github.com/luxfi/crypto/secp256k1"
"github.com/luxfi/ids" "github.com/luxfi/ids"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/math/set" "github.com/luxfi/math/set"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
"github.com/luxfi/netrunner/network/node" "github.com/luxfi/netrunner/network/node"
"github.com/luxfi/netrunner/utils" "github.com/luxfi/netrunner/utils"
"github.com/luxfi/vm/vms/platformvm" "github.com/luxfi/protocol/p/txs"
"github.com/luxfi/vm/vms/platformvm/txs" "github.com/luxfi/protocol/p/signer"
"github.com/luxfi/sdk/api/admin" "github.com/luxfi/sdk/api/admin"
"github.com/luxfi/sdk/api/platformvm"
pwallet "github.com/luxfi/sdk/wallet/chain/p" pwallet "github.com/luxfi/sdk/wallet/chain/p"
pwalletwallet "github.com/luxfi/sdk/wallet/chain/p/wallet" pwalletwallet "github.com/luxfi/sdk/wallet/chain/p/wallet"
"github.com/luxfi/vm/platformvm/signer" "github.com/luxfi/utxo/secp256k1fx"
"github.com/luxfi/vm/secp256k1fx"
pbuilder "github.com/luxfi/sdk/wallet/chain/p/builder" pbuilder "github.com/luxfi/sdk/wallet/chain/p/builder"
psigner "github.com/luxfi/sdk/wallet/chain/p/signer" psigner "github.com/luxfi/sdk/wallet/chain/p/signer"
@@ -861,10 +861,10 @@ func (ln *localNetwork) installCustomChains(
return nil, fmt.Errorf("timeout waiting for primary validators: %w", err) return nil, fmt.Errorf("timeout waiting for primary validators: %w", err)
} }
// Wait for subnet creation transactions to be fully committed before adding validators // Wait for chain creation transactions to be fully committed before adding validators
// The P-Chain needs time to commit the subnet creation blocks and propagate state to all nodes // The P-Chain needs time to commit the chain creation blocks and propagate state to all nodes
// For local networks with fast consensus (K=5), 500ms is sufficient // For local networks with fast consensus (K=5), 500ms is sufficient
ln.logger.Info("waiting for subnet creation to be committed...") ln.logger.Info("waiting for chain creation to be committed...")
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
if err = ln.addChainValidators(ctx, platformCli, w, chainIDs, participantsSpecs); err != nil { if err = ln.addChainValidators(ctx, platformCli, w, chainIDs, participantsSpecs); err != nil {
@@ -938,7 +938,7 @@ func (ln *localNetwork) installCustomChains(
ln.logger.Info("blockchain created", ln.logger.Info("blockchain created",
"index", i, "index", i,
"blockchainID", blockchainID.String(), "blockchainID", blockchainID.String(),
"subnetID", *chainSpecs[i].ChainID, "chainID", *chainSpecs[i].ChainID,
) )
} }
@@ -1549,9 +1549,9 @@ func exportXChainToPChain(ctx context.Context, w *wallet, owner *secp256k1fx.Out
defer cancel() defer cancel()
_, err := w.xWallet.IssueExportTx( _, err := w.xWallet.IssueExportTx(
ids.Empty, ids.Empty,
[]*lux.TransferableOutput{ []*utxo.TransferableOutput{
{ {
Asset: lux.Asset{ Asset: utxo.Asset{
ID: chainAssetID, ID: chainAssetID,
}, },
Out: &secp256k1fx.TransferOutput{ Out: &secp256k1fx.TransferOutput{
@@ -1942,7 +1942,7 @@ func createChains(
log.Info("creating chain tx") log.Info("creating chain tx")
// Use different variable name to avoid shadowing outer context // Use different variable name to avoid shadowing outer context
txCtx, txCancel := createDefaultCtx(ctx) txCtx, txCancel := createDefaultCtx(ctx)
tx, err := w.pWallet.IssueCreateSubnetTx( tx, err := w.pWallet.IssueCreateNetworkTx(
&secp256k1fx.OutputOwners{ &secp256k1fx.OutputOwners{
Threshold: 1, Threshold: 1,
Addrs: []ids.ShortID{w.addr}, Addrs: []ids.ShortID{w.addr},
+12
View File
@@ -10,5 +10,17 @@
"old_name": "whitelisted-subnets", "old_name": "whitelisted-subnets",
"new_name": "track-chains", "new_name": "track-chains",
"value_map": "" "value_map": ""
},
{
"version": "v1.9.6",
"old_name": "track-subnets",
"new_name": "track-chains",
"value_map": ""
},
{
"version": "v1.9.6",
"old_name": "subnet-config-dir",
"new_name": "net-config-dir",
"value_map": ""
} }
] ]
+3 -3
View File
@@ -26,7 +26,7 @@ import (
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
"github.com/luxfi/netrunner/network/node" "github.com/luxfi/netrunner/network/node"
"github.com/luxfi/netrunner/utils" "github.com/luxfi/netrunner/utils"
"github.com/luxfi/vm/platformvm/signer" "github.com/luxfi/protocol/p/signer"
"github.com/luxfi/address" "github.com/luxfi/address"
luxtls "github.com/luxfi/tls" luxtls "github.com/luxfi/tls"
@@ -35,7 +35,7 @@ import (
// patchGenesisPreservingRaw patches a top-level genesis JSON document while guaranteeing that // patchGenesisPreservingRaw patches a top-level genesis JSON document while guaranteeing that
// selected keys are preserved byte-for-byte as raw JSON values (including quotes/escapes for strings). // selected keys are preserved byte-for-byte as raw JSON values (including quotes/escapes for strings).
// //
// This is the correct approach for EVM genesis fields (C-Chain + any subnet EVM genesis) because // This is the correct approach for EVM genesis fields (C-Chain + any chain EVM genesis) because
// parsing via interface{} will corrupt large numeric fields and/or change encoding. // parsing via interface{} will corrupt large numeric fields and/or change encoding.
// //
// CRITICAL: Never use map[string]interface{} for genesis - it causes float64 precision loss! // CRITICAL: Never use map[string]interface{} for genesis - it causes float64 precision loss!
@@ -101,7 +101,7 @@ func mustJSON(v any) json.RawMessage {
// These correspond to EVM chain genesis configurations. // These correspond to EVM chain genesis configurations.
var evmGenesisKeys = []string{ var evmGenesisKeys = []string{
"cChainGenesis", "cChainGenesis",
// Add subnet EVM genesis keys if embedded in main genesis: // Add chain EVM genesis keys if embedded in main genesis:
// "hanzoGenesis", "spcGenesis", "zooGenesis", // "hanzoGenesis", "spcGenesis", "zooGenesis",
} }
+1 -1
View File
@@ -13,7 +13,7 @@ import (
"github.com/luxfi/config" "github.com/luxfi/config"
"github.com/luxfi/constants" "github.com/luxfi/constants"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/network/node" "github.com/luxfi/netrunner/network/node"
"github.com/luxfi/netrunner/utils" "github.com/luxfi/netrunner/utils"
) )
+5 -6
View File
@@ -13,8 +13,7 @@ import (
"time" "time"
"github.com/luxfi/genesis/configs" "github.com/luxfi/genesis/configs"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/log/level"
"github.com/luxfi/netrunner/local" "github.com/luxfi/netrunner/local"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -109,8 +108,8 @@ func TestMainnetFiveNodeNetwork(t *testing.T) {
// Create logger // Create logger
logFactory := log.NewFactoryWithConfig(log.Config{ logFactory := log.NewFactoryWithConfig(log.Config{
DisplayLevel: level.Info, DisplayLevel: log.InfoLevel,
LogLevel: level.Debug, LogLevel: log.DebugLevel,
}) })
log, err := logFactory.Make("test") log, err := logFactory.Make("test")
require.NoError(t, err, "Failed to create logger") require.NoError(t, err, "Failed to create logger")
@@ -156,8 +155,8 @@ func TestMainnetConsensusValidation(t *testing.T) {
// Create logger // Create logger
logFactory := log.NewFactoryWithConfig(log.Config{ logFactory := log.NewFactoryWithConfig(log.Config{
DisplayLevel: level.Info, DisplayLevel: log.InfoLevel,
LogLevel: level.Debug, LogLevel: log.DebugLevel,
}) })
log, err := logFactory.Make("test") log, err := logFactory.Make("test")
require.NoError(t, err, "Failed to create logger") require.NoError(t, err, "Failed to create logger")
+3 -3
View File
@@ -28,7 +28,7 @@ import (
luxcrypto "github.com/luxfi/crypto/secp256k1" luxcrypto "github.com/luxfi/crypto/secp256k1"
"github.com/luxfi/ids" "github.com/luxfi/ids"
"github.com/luxfi/keys" "github.com/luxfi/keys"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/math/set" "github.com/luxfi/math/set"
"github.com/luxfi/netrunner/api" "github.com/luxfi/netrunner/api"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
@@ -38,10 +38,10 @@ import (
"github.com/luxfi/netrunner/utils/constants" "github.com/luxfi/netrunner/utils/constants"
"github.com/luxfi/p2p/peer" "github.com/luxfi/p2p/peer"
luxtls "github.com/luxfi/tls" luxtls "github.com/luxfi/tls"
"github.com/luxfi/vm/utils/beacon" "github.com/luxfi/node/utils/beacon"
"github.com/luxfi/address" "github.com/luxfi/address"
"github.com/luxfi/vm/utils/wrappers" "github.com/luxfi/node/utils/wrappers"
"golang.org/x/mod/semver" "golang.org/x/mod/semver"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )
+9 -6
View File
@@ -15,7 +15,7 @@ import (
"github.com/luxfi/config" "github.com/luxfi/config"
"github.com/luxfi/ids" "github.com/luxfi/ids"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/api" "github.com/luxfi/netrunner/api"
apimocks "github.com/luxfi/netrunner/api/mocks" apimocks "github.com/luxfi/netrunner/api/mocks"
"github.com/luxfi/netrunner/local/mocks" "github.com/luxfi/netrunner/local/mocks"
@@ -898,7 +898,10 @@ func TestChildCmdRedirection(t *testing.T) {
// and it should have a specific length: // and it should have a specific length:
// the actual output + the color terminal escape sequence + node name + []<space> + color terminal reset escape sequence // the actual output + the color terminal escape sequence + node name + []<space> + color terminal reset escape sequence
expectedLen := len(expectedResult) + len(utils.NewColorPicker().NextColor()) + len(mockNodeName) + 3 + len(log.Reset) // color.Wrap("") returns the color escape + reset escape sequences
color := utils.NewColorPicker().NextColor()
colorOverhead := len(color.Wrap(""))
expectedLen := len(expectedResult) + colorOverhead + len(mockNodeName) + 3
if len(result) != expectedLen { if len(result) != expectedLen {
t.Fatalf("expected string length to be %d, but it was %d", expectedLen, len(result)) t.Fatalf("expected string length to be %d, but it was %d", expectedLen, len(result))
} }
@@ -1161,7 +1164,7 @@ func TestWriteFiles(t *testing.T) {
genesisPath := filepath.Join(tmpDir, genesisFileName) genesisPath := filepath.Join(tmpDir, genesisFileName)
configFilePath := filepath.Join(tmpDir, configFileName) configFilePath := filepath.Join(tmpDir, configFileName)
chainConfigDir := filepath.Join(tmpDir, chainConfigSubDir) chainConfigDir := filepath.Join(tmpDir, chainConfigSubDir)
subnetConfigDir := filepath.Join(tmpDir, pChainConfigSubDir) networkConfigDir := filepath.Join(tmpDir, pChainConfigSubDir)
cChainConfigPath := filepath.Join(tmpDir, chainConfigSubDir, "C", configFileName) cChainConfigPath := filepath.Join(tmpDir, chainConfigSubDir, "C", configFileName)
type test struct { type test struct {
@@ -1187,7 +1190,7 @@ func TestWriteFiles(t *testing.T) {
config.StakingSignerKeyPathKey: stakingSigningKeyPath, config.StakingSignerKeyPathKey: stakingSigningKeyPath,
config.GenesisFileKey: genesisPath, config.GenesisFileKey: genesisPath,
config.ChainConfigDirKey: chainConfigDir, config.ChainConfigDirKey: chainConfigDir,
config.NetConfigDirKey: subnetConfigDir, config.NetConfigDirKey: networkConfigDir,
}, },
}, },
{ {
@@ -1205,7 +1208,7 @@ func TestWriteFiles(t *testing.T) {
config.StakingSignerKeyPathKey: stakingSigningKeyPath, config.StakingSignerKeyPathKey: stakingSigningKeyPath,
config.GenesisFileKey: genesisPath, config.GenesisFileKey: genesisPath,
config.ChainConfigDirKey: chainConfigDir, config.ChainConfigDirKey: chainConfigDir,
config.NetConfigDirKey: subnetConfigDir, config.NetConfigDirKey: networkConfigDir,
config.ConfigFileKey: configFilePath, config.ConfigFileKey: configFilePath,
}, },
}, },
@@ -1225,7 +1228,7 @@ func TestWriteFiles(t *testing.T) {
config.StakingSignerKeyPathKey: stakingSigningKeyPath, config.StakingSignerKeyPathKey: stakingSigningKeyPath,
config.GenesisFileKey: genesisPath, config.GenesisFileKey: genesisPath,
config.ChainConfigDirKey: chainConfigDir, config.ChainConfigDirKey: chainConfigDir,
config.NetConfigDirKey: subnetConfigDir, config.NetConfigDirKey: networkConfigDir,
config.ConfigFileKey: configFilePath, config.ConfigFileKey: configFilePath,
}, },
}, },
+8 -9
View File
@@ -9,11 +9,12 @@ import (
"net/netip" "net/netip"
"time" "time"
validators "github.com/luxfi/consensus/validator" // package name is validators "github.com/luxfi/atomic"
"github.com/luxfi/compress"
"github.com/luxfi/constants" "github.com/luxfi/constants"
"github.com/luxfi/crypto/bls" "github.com/luxfi/crypto/bls"
"github.com/luxfi/ids" "github.com/luxfi/ids"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/math/set" "github.com/luxfi/math/set"
"github.com/luxfi/metric" "github.com/luxfi/metric"
"github.com/luxfi/netrunner/api" "github.com/luxfi/netrunner/api"
@@ -24,10 +25,8 @@ import (
"github.com/luxfi/p2p/throttling" "github.com/luxfi/p2p/throttling"
"github.com/luxfi/p2p/tracker" "github.com/luxfi/p2p/tracker"
luxtls "github.com/luxfi/tls" luxtls "github.com/luxfi/tls"
validators "github.com/luxfi/validators" // package name is validators
"github.com/luxfi/version" "github.com/luxfi/version"
"github.com/luxfi/vm/utils"
"github.com/luxfi/vm/utils/compression"
"github.com/prometheus/client_golang/prometheus"
) )
var ( var (
@@ -102,8 +101,8 @@ func (node *localNode) AttachPeer(ctx context.Context, router peer.InboundHandle
return nil, err return nil, err
} }
mc, err := message.NewCreator( mc, err := message.NewCreator(
prometheus.NewRegistry(), metric.NewRegistry(),
compression.TypeZstd, compress.TypeZstd,
10*time.Second, 10*time.Second,
) )
if err != nil { if err != nil {
@@ -111,14 +110,14 @@ func (node *localNode) AttachPeer(ctx context.Context, router peer.InboundHandle
} }
metrics, err := peer.NewMetrics( metrics, err := peer.NewMetrics(
prometheus.NewRegistry(), metric.NewRegistry(),
) )
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Use a nil resource tracker for now - this is acceptable for netrunner testing // Use a nil resource tracker for now - this is acceptable for netrunner testing
var resourceTracker tracker.ResourceTracker = nil var resourceTracker tracker.ResourceTracker = nil
signerIP := utils.NewAtomic(netip.AddrPortFrom(netip.IPv6Unspecified(), 0)) signerIP := atomic.NewAtomic(netip.AddrPortFrom(netip.IPv6Unspecified(), 0))
tls := tlsCert.PrivateKey.(crypto.Signer) tls := tlsCert.PrivateKey.(crypto.Signer)
// Create a dummy BLS signer for now // Create a dummy BLS signer for now
blsKey, err := bls.NewSecretKey() blsKey, err := bls.NewSecretKey()
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"os/exec" "os/exec"
"sync" "sync"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/network/node" "github.com/luxfi/netrunner/network/node"
"github.com/luxfi/netrunner/network/node/status" "github.com/luxfi/netrunner/network/node/status"
"github.com/luxfi/netrunner/utils" "github.com/luxfi/netrunner/utils"
+2 -2
View File
@@ -23,8 +23,8 @@ import (
"github.com/luxfi/p2p/peer" "github.com/luxfi/p2p/peer"
luxtls "github.com/luxfi/tls" luxtls "github.com/luxfi/tls"
"github.com/luxfi/version" "github.com/luxfi/version"
"github.com/luxfi/vm/utils/ips" "github.com/luxfi/node/utils/ips"
"github.com/luxfi/vm/utils/wrappers" "github.com/luxfi/node/utils/wrappers"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
+1 -1
View File
@@ -17,7 +17,7 @@ import (
luxconfig "github.com/luxfi/config" luxconfig "github.com/luxfi/config"
"github.com/luxfi/constants" "github.com/luxfi/constants"
"github.com/luxfi/ids" "github.com/luxfi/ids"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/api" "github.com/luxfi/netrunner/api"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
"github.com/luxfi/netrunner/network/node" "github.com/luxfi/netrunner/network/node"
+2 -2
View File
@@ -6,8 +6,8 @@ package local
import ( import (
"context" "context"
"github.com/luxfi/vm/vms/platformvm" "github.com/luxfi/protocol/p/txs"
"github.com/luxfi/vm/vms/platformvm/txs" "github.com/luxfi/sdk/api/platformvm"
pwalletwallet "github.com/luxfi/sdk/wallet/chain/p/wallet" pwalletwallet "github.com/luxfi/sdk/wallet/chain/p/wallet"
"github.com/luxfi/sdk/wallet/primary/common" "github.com/luxfi/sdk/wallet/primary/common"
) )
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"github.com/dgraph-io/badger/v4" "github.com/dgraph-io/badger/v4"
"github.com/luxfi/ids" "github.com/luxfi/ids"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
) )
+8 -7
View File
@@ -26,7 +26,7 @@ import (
"github.com/luxfi/netrunner/ux" "github.com/luxfi/netrunner/ux"
"github.com/luxfi/constants" "github.com/luxfi/constants"
"github.com/luxfi/log" log "github.com/luxfi/log"
) )
const ( const (
@@ -712,10 +712,10 @@ func (lc *localNetwork) updateChainInfo(ctx context.Context) error {
info: &rpcpb.CustomChainInfo{ info: &rpcpb.CustomChainInfo{
ChainName: blockchain.Name, ChainName: blockchain.Name,
VmId: blockchain.VMID.String(), VmId: blockchain.VMID.String(),
PchainId: blockchain.NetID.String(), PchainId: blockchain.ChainID.String(),
BlockchainId: blockchain.ID.String(), BlockchainId: blockchain.ID.String(),
}, },
chainID: blockchain.NetID, chainID: blockchain.ChainID,
blockchainID: blockchain.ID, blockchainID: blockchain.ID,
} }
} }
@@ -755,10 +755,11 @@ func (lc *localNetwork) updateChainInfo(ctx context.Context) error {
isElastic := false isElastic := false
elasticChainID := ids.Empty elasticChainID := ids.Empty
if _, _, err := (*pChainClient).GetCurrentSupply(ctx, chainID); err == nil { if _, _, err := (*pChainClient).GetCurrentSupply(ctx, chainID); err == nil {
isElastic = true // Only mark as elastic if we can get the elastic chain ID
elasticChainID, err = lc.nw.GetElasticChainID(ctx, chainID) // (chain must have been transformed via IssueTransformChainTx)
if err != nil { if eid, err := lc.nw.GetElasticChainID(ctx, chainID); err == nil {
return err isElastic = true
elasticChainID = eid
} }
} }
+2 -44
View File
@@ -25,8 +25,6 @@ import (
"slices" "slices"
"github.com/luxfi/config" "github.com/luxfi/config"
"github.com/luxfi/consensus/core"
"github.com/luxfi/ids"
"github.com/luxfi/netrunner/network" "github.com/luxfi/netrunner/network"
"github.com/luxfi/netrunner/network/node" "github.com/luxfi/netrunner/network/node"
"github.com/luxfi/netrunner/rpcpb" "github.com/luxfi/netrunner/rpcpb"
@@ -36,7 +34,7 @@ import (
"github.com/luxfi/p2p/peer" "github.com/luxfi/p2p/peer"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/math/set" "github.com/luxfi/math/set"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
@@ -59,7 +57,7 @@ const (
// Subsequent restarts are faster (<10s) but initial bootstrap needs time // Subsequent restarts are faster (<10s) but initial bootstrap needs time
waitForHealthyTimeout = 60 * time.Second waitForHealthyTimeout = 60 * time.Second
// chainDeployTimeout - time for chain deploy operations including node restarts // chainDeployTimeout - time for chain deploy operations including node restarts
// Subnet creation, chain creation, node restart, and P-chain sync can take 60-90s // Chain creation, node restart, and P-chain sync can take 60-90s
chainDeployTimeout = 120 * time.Second chainDeployTimeout = 120 * time.Second
TimeParseLayout = "2006-01-02 15:04:05" TimeParseLayout = "2006-01-02 15:04:05"
@@ -1373,46 +1371,6 @@ func (lh *loggingInboundHandler) HandleInbound(_ context.Context, msg message.In
) )
} }
func (lh *loggingInboundHandler) AppRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, deadline time.Time, appRequestBytes []byte) error {
lh.logger.Debug(
"AppRequest received",
log.String("node-name", lh.nodeName),
log.Stringer("nodeID", nodeID),
log.Uint32("requestID", requestID),
)
return nil
}
func (lh *loggingInboundHandler) AppRequestFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32, appErr *core.AppError) error {
lh.logger.Debug(
"AppRequestFailed received",
log.String("node-name", lh.nodeName),
log.Stringer("nodeID", nodeID),
log.Uint32("requestID", requestID),
)
return nil
}
func (lh *loggingInboundHandler) AppResponse(ctx context.Context, nodeID ids.NodeID, requestID uint32, appResponseBytes []byte) error {
lh.logger.Debug(
"AppResponse received",
log.String("node-name", lh.nodeName),
log.Stringer("nodeID", nodeID),
log.Uint32("requestID", requestID),
)
return nil
}
func (lh *loggingInboundHandler) AppGossip(ctx context.Context, nodeID ids.NodeID, appGossipBytes []byte) error {
lh.logger.Debug(
"AppGossip received",
log.String("node-name", lh.nodeName),
log.Stringer("nodeID", nodeID),
log.Int("gossipSize", len(appGossipBytes)),
)
return nil
}
func (s *server) AttachPeer(ctx context.Context, req *rpcpb.AttachPeerRequest) (*rpcpb.AttachPeerResponse, error) { func (s *server) AttachPeer(ctx context.Context, req *rpcpb.AttachPeerRequest) (*rpcpb.AttachPeerResponse, error) {
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock() defer s.mu.Unlock()
+117 -117
View File
@@ -24,10 +24,10 @@ import (
"github.com/luxfi/p2p/message" "github.com/luxfi/p2p/message"
"github.com/luxfi/sdk/api/admin" "github.com/luxfi/sdk/api/admin"
"github.com/luxfi/vm/vms/platformvm" "github.com/luxfi/sdk/api/platformvm"
"github.com/luxfi/ids" "github.com/luxfi/ids"
"github.com/luxfi/log" log "github.com/luxfi/log"
"github.com/luxfi/metric" "github.com/luxfi/metric"
"github.com/luxfi/netrunner/client" "github.com/luxfi/netrunner/client"
"github.com/luxfi/netrunner/rpcpb" "github.com/luxfi/netrunner/rpcpb"
@@ -65,9 +65,9 @@ var (
newNode2NodeID = "" newNode2NodeID = ""
pausedNodeURI = "" pausedNodeURI = ""
pausedNodeName = "node1" pausedNodeName = "node1"
createdSubnetID = "" createdNetworkID = ""
elasticAssetID = "" elasticAssetID = ""
newSubnetID = "" newNetworkID = ""
customNodeConfigs = map[string]string{ customNodeConfigs = map[string]string{
"node1": `{"api-admin-enabled":true}`, "node1": `{"api-admin-enabled":true}`,
"node2": `{"api-admin-enabled":true}`, "node2": `{"api-admin-enabled":true}`,
@@ -78,11 +78,11 @@ var (
"node7": `{"api-admin-enabled":false}`, "node7": `{"api-admin-enabled":false}`,
} }
numNodes = uint32(5) numNodes = uint32(5)
subnetParticipants = []string{"node1", "node2", "node3"} networkParticipants = []string{"node1", "node2", "node3"}
newParticipantNode = "new_participant_node" newParticipantNode = "new_participant_node"
subnetParticipants2 = []string{"node1", "node2", newParticipantNode} networkParticipants2 = []string{"node1", "node2", newParticipantNode}
existingNodes = []string{"node1", "node2", "node3", "node4", "node5"} existingNodes = []string{"node1", "node2", "node3", "node4", "node5"}
disjointNewSubnetParticipants = [][]string{ disjointNewNetworkParticipants = [][]string{
{"new_node1", "new_node2"}, {"new_node1", "new_node2"},
{"new_node3", "new_node4"}, {"new_node3", "new_node4"},
} }
@@ -209,7 +209,7 @@ var _ = ginkgo.AfterSuite(func() {
var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() { var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
ginkgo.It("can create blockhains", func() { ginkgo.It("can create blockhains", func() {
existingSubnetID := "" existingChainID := ""
createdBlockchainID := "" createdBlockchainID := ""
createdBlockchainID2 := "" createdBlockchainID2 := ""
ginkgo.By("start with blockchain specs", func() { ginkgo.By("start with blockchain specs", func() {
@@ -231,8 +231,8 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
ux.Print(logger, log.Green.Wrap("successfully started, node-names: %s"), resp.ClusterInfo.NodeNames) ux.Print(logger, log.Green.Wrap("successfully started, node-names: %s"), resp.ClusterInfo.NodeNames)
}) })
ginkgo.By("can create a blockchain with a new subnet id", func() { ginkgo.By("can create a blockchain with a new network id", func() {
ux.Print(logger, log.Blue.Wrap("can create a blockchain in a new subnet")) ux.Print(logger, log.Blue.Wrap("can create a blockchain in a new network"))
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
resp, err := cli.CreateChains(ctx, resp, err := cli.CreateChains(ctx,
[]*rpcpb.BlockchainSpec{ []*rpcpb.BlockchainSpec{
@@ -247,7 +247,7 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
gomega.Ω(len(resp.ChainIds)).Should(gomega.Equal(1)) gomega.Ω(len(resp.ChainIds)).Should(gomega.Equal(1))
}) })
ginkgo.By("get subnet ID", func() { ginkgo.By("get network ID", func() {
cctx, ccancel := context.WithTimeout(context.Background(), 15*time.Second) cctx, ccancel := context.WithTimeout(context.Background(), 15*time.Second)
status, err := cli.Status(cctx) status, err := cli.Status(cctx)
ccancel() ccancel()
@@ -255,31 +255,31 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
customChains := status.ClusterInfo.GetCustomChains() customChains := status.ClusterInfo.GetCustomChains()
_, ok := customChains[createdBlockchainID] _, ok := customChains[createdBlockchainID]
gomega.Ω(ok).Should(gomega.Equal(true)) gomega.Ω(ok).Should(gomega.Equal(true))
existingSubnetID = customChains[createdBlockchainID].SubnetId existingNetworkID = customChains[createdBlockchainID].PchainId
gomega.Ω(existingSubnetID).Should(gomega.Not(gomega.BeNil())) gomega.Ω(existingNetworkID).Should(gomega.Not(gomega.BeNil()))
}) })
ginkgo.By("verify the subnet also has all existing nodes as participants", func() { ginkgo.By("verify the network also has all existing nodes as participants", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() defer cancel()
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
subnetIDs := slices.Collect(maps.Keys(status.ClusterInfo.Subnets)) networkIDs := slices.Collect(maps.Keys(status.ClusterInfo.Chains))
sort.Strings(subnetIDs) sort.Strings(networkIDs)
createdSubnetIDString := subnetIDs[0] createdNetworkIDString := networkIDs[0]
subnetHasCorrectParticipants := utils.VerifySubnetHasCorrectParticipants(logger, existingNodes, status.ClusterInfo, createdSubnetIDString) networkHasCorrectParticipants := utils.VerifyNetworkHasCorrectParticipants(logger, existingNodes, status.ClusterInfo, createdNetworkIDString)
gomega.Ω(subnetHasCorrectParticipants).Should(gomega.Equal(true)) gomega.Ω(networkHasCorrectParticipants).Should(gomega.Equal(true))
}) })
ginkgo.By("can create a blockchain with an existing subnet id", func() { ginkgo.By("can create a blockchain with an existing network id", func() {
ux.Print(logger, log.Blue.Wrap("can create a blockchain in an existing subnet")) ux.Print(logger, log.Blue.Wrap("can create a blockchain in an existing network"))
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
resp, err := cli.CreateChains(ctx, resp, err := cli.CreateChains(ctx,
[]*rpcpb.BlockchainSpec{ []*rpcpb.BlockchainSpec{
{ {
VmName: "evm", VmName: "evm",
Genesis: genesisContents, Genesis: genesisContents,
SubnetId: &existingSubnetID, ChainId: &existingNetworkID,
}, },
}, },
) )
@@ -311,15 +311,15 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
}) })
ginkgo.By("can create a blockchain with an existing subnet id loaded from snapshot", func() { ginkgo.By("can create a blockchain with an existing network id loaded from snapshot", func() {
ux.Print(logger, log.Blue.Wrap("can create a blockchain in an existing subnet")) ux.Print(logger, log.Blue.Wrap("can create a blockchain in an existing network"))
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
_, err := cli.CreateChains(ctx, _, err := cli.CreateChains(ctx,
[]*rpcpb.BlockchainSpec{ []*rpcpb.BlockchainSpec{
{ {
VmName: "evm", VmName: "evm",
Genesis: genesisContents, Genesis: genesisContents,
SubnetId: &existingSubnetID, ChainId: &existingNetworkID,
}, },
}, },
) )
@@ -327,15 +327,15 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
}) })
ginkgo.By("can create a blockchain with new subnet id with some of existing participating nodes", func() { ginkgo.By("can create a blockchain with new network id with some of existing participating nodes", func() {
ux.Print(logger, log.Blue.Wrap("can create a blockchain with new subnet id with some of existing participating nodes")) ux.Print(logger, log.Blue.Wrap("can create a blockchain with new network id with some of existing participating nodes"))
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
resp, err := cli.CreateChains(ctx, resp, err := cli.CreateChains(ctx,
[]*rpcpb.BlockchainSpec{ []*rpcpb.BlockchainSpec{
{ {
VmName: "evm", VmName: "evm",
Genesis: genesisContents, Genesis: genesisContents,
ParticipantsSpec: &rpcpb.ParticipantsSpec{Participants: subnetParticipants}, ParticipantsSpec: &rpcpb.ParticipantsSpec{Participants: networkParticipants},
}, },
}, },
) )
@@ -345,29 +345,29 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
createdBlockchainID = resp.ChainIds[0] createdBlockchainID = resp.ChainIds[0]
}) })
ginkgo.By("verify subnet has correct participants", func() { ginkgo.By("verify network has correct participants", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() defer cancel()
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
customChains := status.ClusterInfo.GetCustomChains() customChains := status.ClusterInfo.GetCustomChains()
createdSubnetIDString := customChains[createdBlockchainID].SubnetId createdNetworkIDString := customChains[createdBlockchainID].PchainId
subnetHasCorrectParticipants := utils.VerifySubnetHasCorrectParticipants(logger, subnetParticipants, status.ClusterInfo, createdSubnetIDString) networkHasCorrectParticipants := utils.VerifyNetworkHasCorrectParticipants(logger, networkParticipants, status.ClusterInfo, createdNetworkIDString)
gomega.Ω(subnetHasCorrectParticipants).Should(gomega.Equal(true)) gomega.Ω(networkHasCorrectParticipants).Should(gomega.Equal(true))
// verify that no new nodes is added to cluster // verify that no new nodes is added to cluster
gomega.Ω(len(status.ClusterInfo.NodeNames)).Should(gomega.Equal(5)) gomega.Ω(len(status.ClusterInfo.NodeNames)).Should(gomega.Equal(5))
}) })
ginkgo.By("can create a blockchain with new subnet id with some of existing participating nodes and a new node", func() { ginkgo.By("can create a blockchain with new network id with some of existing participating nodes and a new node", func() {
ux.Print(logger, log.Blue.Wrap("can create a blockchain new subnet id with some of existing participating nodes and a new node")) ux.Print(logger, log.Blue.Wrap("can create a blockchain with new network id with some of existing participating nodes and a new node"))
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
resp, err := cli.CreateChains(ctx, resp, err := cli.CreateChains(ctx,
[]*rpcpb.BlockchainSpec{ []*rpcpb.BlockchainSpec{
{ {
VmName: "evm", VmName: "evm",
Genesis: genesisContents, Genesis: genesisContents,
ParticipantsSpec: &rpcpb.ParticipantsSpec{Participants: subnetParticipants2}, ParticipantsSpec: &rpcpb.ParticipantsSpec{Participants: networkParticipants2},
}, },
}, },
) )
@@ -381,15 +381,15 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
createdBlockchainID = resp.ChainIds[0] createdBlockchainID = resp.ChainIds[0]
}) })
ginkgo.By("verify the newer subnet also has correct participants", func() { ginkgo.By("verify the newer network also has correct participants", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() defer cancel()
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
customChains := status.ClusterInfo.GetCustomChains() customChains := status.ClusterInfo.GetCustomChains()
createdSubnetIDString := customChains[createdBlockchainID].SubnetId createdNetworkIDString := customChains[createdBlockchainID].PchainId
subnetHasCorrectParticipants := utils.VerifySubnetHasCorrectParticipants(log, subnetParticipants2, status.ClusterInfo, createdSubnetIDString) networkHasCorrectParticipants := utils.VerifyNetworkHasCorrectParticipants(log, networkParticipants2, status.ClusterInfo, createdNetworkIDString)
gomega.Ω(subnetHasCorrectParticipants).Should(gomega.Equal(true)) gomega.Ω(networkHasCorrectParticipants).Should(gomega.Equal(true))
}) })
ginkgo.By("can create two blockchains at a time", func() { ginkgo.By("can create two blockchains at a time", func() {
@@ -399,12 +399,12 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
{ {
VmName: "evm", VmName: "evm",
Genesis: genesisContents, Genesis: genesisContents,
SubnetId: &existingSubnetID, ChainId: &existingNetworkID,
}, },
{ {
VmName: "evm", VmName: "evm",
Genesis: genesisContents, Genesis: genesisContents,
SubnetId: &existingSubnetID, ChainId: &existingNetworkID,
}, },
}, },
) )
@@ -413,7 +413,7 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
gomega.Ω(len(resp.ChainIds)).Should(gomega.Equal(2)) gomega.Ω(len(resp.ChainIds)).Should(gomega.Equal(2))
}) })
ginkgo.By("can create two blockchains in two new disjoint subnets with bls validators", func() { ginkgo.By("can create two blockchains in two new disjoint networks with bls validators", func() {
// get prev status // get prev status
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
prevStatus, err := cli.Status(ctx) prevStatus, err := cli.Status(ctx)
@@ -426,19 +426,19 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
{ {
VmName: "evm", VmName: "evm",
Genesis: genesisContents, Genesis: genesisContents,
ParticipantsSpec: &rpcpb.ParticipantsSpec{Participants: disjointNewSubnetParticipants[0]}, ParticipantsSpec: &rpcpb.ParticipantsSpec{Participants: disjointNewNetworkParticipants[0]},
}, },
{ {
VmName: "evm", VmName: "evm",
Genesis: genesisContents, Genesis: genesisContents,
ParticipantsSpec: &rpcpb.ParticipantsSpec{Participants: disjointNewSubnetParticipants[1]}, ParticipantsSpec: &rpcpb.ParticipantsSpec{Participants: disjointNewNetworkParticipants[1]},
}, },
}, },
) )
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
// check new nodes // check new nodes
allNewParticipants := append(disjointNewSubnetParticipants[0], disjointNewSubnetParticipants[1]...) allNewParticipants := append(disjointNewNetworkParticipants[0], disjointNewNetworkParticipants[1]...)
expectedLen := len(prevStatus.ClusterInfo.NodeNames) + len(allNewParticipants) expectedLen := len(prevStatus.ClusterInfo.NodeNames) + len(allNewParticipants)
gomega.Ω(len(resp.ClusterInfo.NodeNames)).Should(gomega.Equal(expectedLen)) gomega.Ω(len(resp.ClusterInfo.NodeNames)).Should(gomega.Equal(expectedLen))
for _, nodeName := range allNewParticipants { for _, nodeName := range allNewParticipants {
@@ -450,18 +450,18 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
createdBlockchainID2 = resp.ChainIds[1] createdBlockchainID2 = resp.ChainIds[1]
}) })
ginkgo.By("verify the new subnets also has correct participants", func() { ginkgo.By("verify the new networks also has correct participants", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() defer cancel()
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
customChains := status.ClusterInfo.GetCustomChains() customChains := status.ClusterInfo.GetCustomChains()
createdSubnetIDString := customChains[createdBlockchainID].SubnetId createdNetworkIDString := customChains[createdBlockchainID].PchainId
subnetHasCorrectParticipants := utils.VerifySubnetHasCorrectParticipants(log, disjointNewSubnetParticipants[0], status.ClusterInfo, createdSubnetIDString) networkHasCorrectParticipants := utils.VerifyNetworkHasCorrectParticipants(log, disjointNewNetworkParticipants[0], status.ClusterInfo, createdNetworkIDString)
gomega.Ω(subnetHasCorrectParticipants).Should(gomega.Equal(true)) gomega.Ω(networkHasCorrectParticipants).Should(gomega.Equal(true))
createdSubnetID2String := customChains[createdBlockchainID2].SubnetId createdNetworkID2String := customChains[createdBlockchainID2].PchainId
subnet2HasCorrectParticipants := utils.VerifySubnetHasCorrectParticipants(log, disjointNewSubnetParticipants[1], status.ClusterInfo, createdSubnetID2String) network2HasCorrectParticipants := utils.VerifyNetworkHasCorrectParticipants(log, disjointNewNetworkParticipants[1], status.ClusterInfo, createdNetworkID2String)
gomega.Ω(subnet2HasCorrectParticipants).Should(gomega.Equal(true)) gomega.Ω(network2HasCorrectParticipants).Should(gomega.Equal(true))
}) })
ginkgo.By("verify that new validators have BLS Keys", func() { ginkgo.By("verify that new validators have BLS Keys", func() {
@@ -478,7 +478,7 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
allNewParticipants := append(disjointNewSubnetParticipants[0], disjointNewSubnetParticipants[1]...) allNewParticipants := append(disjointNewNetworkParticipants[0], disjointNewNetworkParticipants[1]...)
for _, nodeName := range allNewParticipants { for _, nodeName := range allNewParticipants {
nodeInfo, ok := status.ClusterInfo.NodeInfos[nodeName] nodeInfo, ok := status.ClusterInfo.NodeInfos[nodeName]
gomega.Ω(ok).Should(gomega.Equal(true)) gomega.Ω(ok).Should(gomega.Equal(true))
@@ -819,12 +819,12 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
}) })
ginkgo.By("add 1 subnet", func() { ginkgo.By("add 1 network", func() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
resp, err := cli.CreateParticipantGroups(ctx, []*rpcpb.ParticipantsSpec{{}}) resp, err := cli.CreateParticipantGroups(ctx, []*rpcpb.ParticipantsSpec{{}})
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
gomega.Ω(len(resp.SubnetIds)).Should(gomega.Equal(1)) gomega.Ω(len(resp.ChainIds)).Should(gomega.Equal(1))
}) })
ginkgo.By("verify that new validator has BLS Keys", func() { ginkgo.By("verify that new validator has BLS Keys", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
@@ -849,48 +849,48 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
}) })
}) })
ginkgo.It("subnet creation", func() { ginkgo.It("network creation", func() {
ginkgo.By("add 1 subnet", func() { ginkgo.By("add 1 network", func() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
_, err := cli.CreateParticipantGroups(ctx, []*rpcpb.ParticipantsSpec{{}}) _, err := cli.CreateParticipantGroups(ctx, []*rpcpb.ParticipantsSpec{{}})
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
}) })
ginkgo.By("check subnet number is 2", func() { ginkgo.By("check network number is 2", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
numSubnets := len(status.ClusterInfo.Subnets) numNetworks := len(status.ClusterInfo.Chains)
gomega.Ω(numSubnets).Should(gomega.Equal(2)) gomega.Ω(numNetworks).Should(gomega.Equal(2))
}) })
ginkgo.By("add 1 subnet with participants", func() { ginkgo.By("add 1 network with participants", func() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
response, err := cli.CreateParticipantGroups(ctx, []*rpcpb.ParticipantsSpec{{Participants: subnetParticipants}}) response, err := cli.CreateParticipantGroups(ctx, []*rpcpb.ParticipantsSpec{{Participants: networkParticipants}})
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
gomega.Ω(len(response.SubnetIds)).Should(gomega.Equal(1)) gomega.Ω(len(response.ChainIds)).Should(gomega.Equal(1))
newSubnetID = response.SubnetIds[0] newNetworkID = response.ChainIds[0]
}) })
ginkgo.By("verify subnet has correct participants", func() { ginkgo.By("verify network has correct participants", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() defer cancel()
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
subnetHasCorrectParticipants := utils.VerifySubnetHasCorrectParticipants(log, subnetParticipants, status.ClusterInfo, newSubnetID) networkHasCorrectParticipants := utils.VerifyNetworkHasCorrectParticipants(log, networkParticipants, status.ClusterInfo, newNetworkID)
gomega.Ω(subnetHasCorrectParticipants).Should(gomega.Equal(true)) gomega.Ω(networkHasCorrectParticipants).Should(gomega.Equal(true))
}) })
ginkgo.By("add 1 subnet with node not currently added", func() { ginkgo.By("add 1 network with node not currently added", func() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
response, err := cli.CreateParticipantGroups(ctx, []*rpcpb.ParticipantsSpec{{Participants: subnetParticipants2}}) response, err := cli.CreateParticipantGroups(ctx, []*rpcpb.ParticipantsSpec{{Participants: networkParticipants2}})
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
// verify that a new node is added to cluster // verify that a new node is added to cluster
gomega.Ω(len(response.ClusterInfo.NodeNames)).Should(gomega.Equal(7)) gomega.Ω(len(response.ClusterInfo.NodeNames)).Should(gomega.Equal(7))
_, ok := response.ClusterInfo.NodeInfos[newParticipantNode] _, ok := response.ClusterInfo.NodeInfos[newParticipantNode]
gomega.Ω(ok).Should(gomega.Equal(true)) gomega.Ω(ok).Should(gomega.Equal(true))
gomega.Ω(len(response.SubnetIds)).Should(gomega.Equal(1)) gomega.Ω(len(response.ChainIds)).Should(gomega.Equal(1))
newSubnetID = response.SubnetIds[0] newNetworkID = response.ChainIds[0]
}) })
ginkgo.By("calling AddNode with existing node name, should fail", func() { ginkgo.By("calling AddNode with existing node name, should fail", func() {
ux.Print(logger, log.Green.Wrap("calling 'add-node' with the valid binary path: %s"), execPath1) ux.Print(logger, log.Green.Wrap("calling 'add-node' with the valid binary path: %s"), execPath1)
@@ -901,28 +901,28 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
gomega.Ω(resp).Should(gomega.BeNil()) gomega.Ω(resp).Should(gomega.BeNil())
ux.Print(logger, log.Green.Wrap("'add-node' failed as expected")) ux.Print(logger, log.Green.Wrap("'add-node' failed as expected"))
}) })
ginkgo.By("verify the newer subnet also has correct participants", func() { ginkgo.By("verify the newer network also has correct participants", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel() defer cancel()
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
subnetHasCorrectParticipants := utils.VerifySubnetHasCorrectParticipants(logger, subnetParticipants2, status.ClusterInfo, newSubnetID) networkHasCorrectParticipants := utils.VerifyNetworkHasCorrectParticipants(logger, networkParticipants2, status.ClusterInfo, newNetworkID)
gomega.Ω(subnetHasCorrectParticipants).Should(gomega.Equal(true)) gomega.Ω(networkHasCorrectParticipants).Should(gomega.Equal(true))
}) })
}) })
ginkgo.It("can remove subnet validator", func() { ginkgo.It("can remove network validator", func() {
ginkgo.By("removing a subnet validator", func() { ginkgo.By("removing a network validator", func() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel() defer cancel()
testRemoveSubnetValidatorConfig := rpcpb.RemoveChainValidatorSpec{ testRemoveNetworkValidatorConfig := rpcpb.RemoveChainValidatorSpec{
NodeNames: []string{"node2"}, NodeNames: []string{"node2"},
SubnetId: newSubnetID, ChainId: newNetworkID,
} }
_, err := cli.RemoveSubnetValidator(ctx, []*rpcpb.RemoveChainValidatorSpec{&testRemoveSubnetValidatorConfig}) _, err := cli.RemoveChainValidator(ctx, []*rpcpb.RemoveChainValidatorSpec{&testRemoveNetworkValidatorConfig})
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
}) })
ginkgo.By("verify there are only two validators left for subnet", func() { ginkgo.By("verify there are only two validators left for network", func() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel() defer cancel()
clientURIs, err := cli.URIs(ctx) clientURIs, err := cli.URIs(ctx)
@@ -932,40 +932,40 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
clientURI = uri clientURI = uri
break break
} }
subnetID, err := ids.FromString(newSubnetID) networkID, err := ids.FromString(newNetworkID)
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
platformCli := platformvm.NewClient(clientURI) platformCli := platformvm.NewClient(clientURI)
vdrs, err := platformCli.GetCurrentValidators(ctx, subnetID, nil) vdrs, err := platformCli.GetCurrentValidators(ctx, networkID, nil)
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
gomega.Ω(len(vdrs)).Should(gomega.Equal(2)) gomega.Ω(len(vdrs)).Should(gomega.Equal(2))
}) })
}) })
ginkgo.It("transform subnet to elastic subnets", func() { ginkgo.It("transform network to elastic networks", func() {
var elasticSubnetID string var elasticNetworkID string
ginkgo.By("add 1 subnet", func() { ginkgo.By("add 1 network", func() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
resp, err := cli.CreateParticipantGroups(ctx, []*rpcpb.ParticipantsSpec{{}}) resp, err := cli.CreateParticipantGroups(ctx, []*rpcpb.ParticipantsSpec{{}})
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
gomega.Ω(len(resp.SubnetIds)).Should(gomega.Equal(1)) gomega.Ω(len(resp.ChainIds)).Should(gomega.Equal(1))
gomega.Ω(len(resp.ClusterInfo.Subnets)).Should(gomega.Equal(5)) gomega.Ω(len(resp.ClusterInfo.Chains)).Should(gomega.Equal(5))
createdSubnetID = resp.SubnetIds[0] createdNetworkID = resp.ChainIds[0]
}) })
ginkgo.By("check expected non elastic status", func() { ginkgo.By("check expected non elastic status", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
subnetInfo := status.ClusterInfo.Subnets[createdSubnetID] networkInfo := status.ClusterInfo.Chains[createdNetworkID]
gomega.Ω(subnetInfo.IsElastic).Should(gomega.Equal(false)) gomega.Ω(networkInfo.IsElastic).Should(gomega.Equal(false))
gomega.Ω(subnetInfo.ElasticChainId).Should(gomega.Equal(ids.Empty.String())) gomega.Ω(networkInfo.ElasticChainId).Should(gomega.Equal(ids.Empty.String()))
}) })
ginkgo.By("transform 1 subnet to elastic subnet", func() { ginkgo.By("transform 1 network to elastic network", func() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel() defer cancel()
testElasticSubnetConfig.SubnetId = createdSubnetID testElasticChainConfig.ChainId = createdNetworkID
response, err := cli.TransformElasticSubnets(ctx, []*rpcpb.ElasticParticipantsSpec{&testElasticSubnetConfig}) response, err := cli.TransformElasticChains(ctx, []*rpcpb.ElasticChainSpec{&testElasticChainConfig})
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
gomega.Ω(len(response.TxIds)).Should(gomega.Equal(1)) gomega.Ω(len(response.TxIds)).Should(gomega.Equal(1))
gomega.Ω(len(response.AssetIds)).Should(gomega.Equal(1)) gomega.Ω(len(response.AssetIds)).Should(gomega.Equal(1))
@@ -976,16 +976,16 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
subnetInfo := status.ClusterInfo.Subnets[createdSubnetID] networkInfo := status.ClusterInfo.Chains[createdNetworkID]
gomega.Ω(subnetInfo.IsElastic).Should(gomega.Equal(true)) gomega.Ω(networkInfo.IsElastic).Should(gomega.Equal(true))
gomega.Ω(subnetInfo.ElasticChainId).ShouldNot(gomega.Equal(ids.Empty.String())) gomega.Ω(networkInfo.ElasticChainId).ShouldNot(gomega.Equal(ids.Empty.String()))
elasticSubnetID = subnetInfo.ElasticChainId elasticNetworkID = networkInfo.ElasticChainId
}) })
ginkgo.By("transforming a subnet with same subnetID to elastic subnet will fail", func() { ginkgo.By("transforming a network with same networkID to elastic network will fail", func() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel() defer cancel()
testElasticSubnetConfig.SubnetId = createdSubnetID testElasticChainConfig.ChainId = createdNetworkID
_, err := cli.TransformElasticSubnets(ctx, []*rpcpb.ElasticParticipantsSpec{&testElasticSubnetConfig}) _, err := cli.TransformElasticChains(ctx, []*rpcpb.ElasticChainSpec{&testElasticChainConfig})
gomega.Ω(err).Should(gomega.HaveOccurred()) gomega.Ω(err).Should(gomega.HaveOccurred())
}) })
ginkgo.By("save snapshot with elastic info", func() { ginkgo.By("save snapshot with elastic info", func() {
@@ -1005,9 +1005,9 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
subnetInfo := status.ClusterInfo.Subnets[createdSubnetID] networkInfo := status.ClusterInfo.Chains[createdNetworkID]
gomega.Ω(subnetInfo.IsElastic).Should(gomega.Equal(true)) gomega.Ω(networkInfo.IsElastic).Should(gomega.Equal(true))
gomega.Ω(subnetInfo.ElasticChainId).Should(gomega.Equal(elasticSubnetID)) gomega.Ω(networkInfo.ElasticChainId).Should(gomega.Equal(elasticNetworkID))
}) })
ginkgo.By("remove snapshot with elastic info", func() { ginkgo.By("remove snapshot with elastic info", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
@@ -1017,11 +1017,11 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
}) })
}) })
ginkgo.It("add permissionless validator to elastic subnets", func() { ginkgo.It("add permissionless validator to elastic networks", func() {
ginkgo.By("adding a permissionless validator to elastic subnet", func() { ginkgo.By("adding a permissionless validator to elastic network", func() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel() defer cancel()
testValidatorConfig.SubnetId = createdSubnetID testValidatorConfig.ChainId = createdNetworkID
testValidatorConfig.AssetId = elasticAssetID testValidatorConfig.AssetId = elasticAssetID
testValidatorConfig.NodeName = "permissionlessNode" testValidatorConfig.NodeName = "permissionlessNode"
_, err := cli.AddPermissionlessValidator(ctx, []*rpcpb.PermissionlessValidatorSpec{&testValidatorConfig}) _, err := cli.AddPermissionlessValidator(ctx, []*rpcpb.PermissionlessValidatorSpec{&testValidatorConfig})
@@ -1031,7 +1031,7 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
ginkgo.It("snapshots + blockchain creation", func() { ginkgo.It("snapshots + blockchain creation", func() {
var originalUris []string var originalUris []string
var originalSubnets []string var originalNetworks []string
ginkgo.By("get original URIs", func() { ginkgo.By("get original URIs", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
var err error var err error
@@ -1040,14 +1040,14 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
gomega.Ω(len(originalUris)).Should(gomega.Equal(8)) gomega.Ω(len(originalUris)).Should(gomega.Equal(8))
}) })
ginkgo.By("get original subnets", func() { ginkgo.By("get original networks", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
numSubnets := len(status.ClusterInfo.Subnets) numNetworks := len(status.ClusterInfo.Chains)
gomega.Ω(numSubnets).Should(gomega.Equal(5)) gomega.Ω(numNetworks).Should(gomega.Equal(5))
originalSubnets = slices.Collect(maps.Keys(status.ClusterInfo.Subnets)) originalNetworks = slices.Collect(maps.Keys(status.ClusterInfo.Chains))
}) })
ginkgo.By("check there are no snapshots", func() { ginkgo.By("check there are no snapshots", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
@@ -1088,15 +1088,15 @@ var _ = ginkgo.Describe("[Start/Remove/Restart/Add/Stop]", func() {
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
gomega.Ω(uris).Should(gomega.Equal(originalUris)) gomega.Ω(uris).Should(gomega.Equal(originalUris))
}) })
ginkgo.By("check subnets", func() { ginkgo.By("check networks", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
status, err := cli.Status(ctx) status, err := cli.Status(ctx)
cancel() cancel()
gomega.Ω(err).Should(gomega.BeNil()) gomega.Ω(err).Should(gomega.BeNil())
subnetIDs := slices.Collect(maps.Keys(status.ClusterInfo.Subnets)) networkIDs := slices.Collect(maps.Keys(status.ClusterInfo.Chains))
sort.Strings(subnetIDs) sort.Strings(networkIDs)
sort.Strings(originalSubnets) sort.Strings(originalNetworks)
gomega.Ω(subnetIDs).Should(gomega.Equal(originalSubnets)) gomega.Ω(networkIDs).Should(gomega.Equal(originalNetworks))
}) })
ginkgo.By("save fail for already saved snapshot", func() { ginkgo.By("save fail for already saved snapshot", func() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+1 -1
View File
@@ -11,7 +11,7 @@
"petersburgBlock": 0, "petersburgBlock": 0,
"istanbulBlock": 0, "istanbulBlock": 0,
"muirGlacierBlock": 0, "muirGlacierBlock": 0,
"subnetEVMTimestamp": 0, "luxEvmTimestamp": 0,
"feeConfig": { "feeConfig": {
"gasLimit": 20000000, "gasLimit": 20000000,
"minBaseFee": 1000000000, "minBaseFee": 1000000000,
+3 -3
View File
@@ -5,8 +5,6 @@ import (
"os/exec" "os/exec"
"strings" "strings"
"testing" "testing"
"github.com/luxfi/log"
) )
// TestColorAssignment tests that each color assignment is different and that it "wraps" // TestColorAssignment tests that each color assignment is different and that it "wraps"
@@ -84,7 +82,9 @@ func TestColorAndPrepend(t *testing.T) {
} }
// 4 is []<space>\n // 4 is []<space>\n
expLen := len("test") + len(color) + len(fakeNodeName) + 4 + len(log.Reset) // color.Wrap("") returns the color escape + reset escape sequences
colorOverhead := len(color.Wrap(""))
expLen := len("test") + colorOverhead + len(fakeNodeName) + 4
if len(res) != expLen { if len(res) != expLen {
t.Fatalf("expected lengh to be %d, but was %d", expLen, len(res)) t.Fatalf("expected lengh to be %d, but was %d", expLen, len(res))
} }
+1 -1
View File
@@ -9,7 +9,7 @@ import (
"time" "time"
"github.com/luxfi/ids" "github.com/luxfi/ids"
"github.com/luxfi/log" log "github.com/luxfi/log"
rpcb "github.com/luxfi/netrunner/rpcpb" rpcb "github.com/luxfi/netrunner/rpcpb"
"github.com/luxfi/netrunner/ux" "github.com/luxfi/netrunner/ux"
luxtls "github.com/luxfi/tls" luxtls "github.com/luxfi/tls"
+1 -1
View File
@@ -5,7 +5,7 @@ package ux
import ( import (
"fmt" "fmt"
"github.com/luxfi/log" log "github.com/luxfi/log"
) )
//nolint:govet // msg is intentionally a format string that may come from variables //nolint:govet // msg is intentionally a format string that may come from variables