Skip to content

Commit

Permalink
Merge pull request #349 from ava-labs/support-subnet-config
Browse files Browse the repository at this point in the history
Support subnet config
  • Loading branch information
felipemadero authored Nov 15, 2022
2 parents 3330b17 + b881894 commit a70fbda
Show file tree
Hide file tree
Showing 15 changed files with 683 additions and 394 deletions.
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,13 +356,13 @@ curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginD
avalanche-network-runner 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 both chain config and network upgrade file paths (requires network restart):
To create a blockchain with a subnet id, and chain config, network upgrade and subnet config file paths (requires network restart):
```bash
curl -X POST -k http://localhost:8081/v1/control/createblockchains -d '{"pluginDir":"'$PLUGIN_DIR'","blockchainSpecs":[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_id": "'$SUBNET_ID'", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'"}]}'
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'"}]}'
# or
avalanche-network-runner control create-blockchains '[{"vm_name":"'$VM_NAME'","genesis":"'$GENESIS_PATH'", "subnet_id": "'$SUBNET_ID'", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'"}]' --plugin-dir $PLUGIN_DIR
avalanche-network-runner 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 remove (stop) a node:
Expand Down Expand Up @@ -586,18 +586,18 @@ avalanche-network-runner control start \
curl -X POST -k http://localhost:8081/v1/control/status -d ''
```
Blockchain config file and network upgrade file paths can be optionally specified at network start, eg:
Blockchain config file, network upgrade file, and subnet config file paths can be optionally specified at network start, eg:
```bash
curl -X POST -k http://localhost:8081/v1/control/start -d '{"execPath":"'${AVALANCHEGO_EXEC_PATH}'","numNodes":5,"logLevel":"INFO","pluginDir":"'${AVALANCHEGO_PLUGIN_PATH}'","blockchainSpecs":[{"vm_name":"subnetevm","genesis":"/tmp/subnet-evm.genesis.json","chain_config":"'$CHAIN_CONFIG_PATH'","network_upgrade":"'$NETWORK_UPGRADE_PATH'"}]}'
curl -X POST -k http://localhost:8081/v1/control/start -d '{"execPath":"'${AVALANCHEGO_EXEC_PATH}'","numNodes":5,"logLevel":"INFO","pluginDir":"'${AVALANCHEGO_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'"}]}'
# or
avalanche-network-runner control start \
--log-level debug \
--endpoint="0.0.0.0:8080" \
--avalanchego-path ${AVALANCHEGO_EXEC_PATH} \
--plugin-dir ${AVALANCHEGO_PLUGIN_PATH} \
--blockchain-specs '[{"vm_name": "subnetevm", "genesis": "/tmp/subnet-evm.genesis.json", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'"}]'
--blockchain-specs '[{"vm_name": "subnetevm", "genesis": "/tmp/subnet-evm.genesis.json", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "subnet_config": "'$SUBNET_CONFIG_PATH'"}]'
```
## `network-runner` RPC server: `blobvm` example
Expand Down Expand Up @@ -675,15 +675,15 @@ curl -X POST -k http://localhost:8081/v1/control/status -d ''
Blockchain config file and network upgrade file paths can be optionally specified at network start, eg:
```bash
curl -X POST -k http://localhost:8081/v1/control/start -d '{"execPath":"'${AVALANCHEGO_EXEC_PATH}'","numNodes":5,"logLevel":"INFO","pluginDir":"'${AVALANCHEGO_PLUGIN_PATH}'","blockchainSpecs":[{"vm_name":"blobvm","genesis":"/tmp/blobvm.json","chain_config":"'$CHAIN_CONFIG_PATH'","network_upgrade":"'$NETWORK_UPGRADE_PATH'"}]}'
curl -X POST -k http://localhost:8081/v1/control/start -d '{"execPath":"'${AVALANCHEGO_EXEC_PATH}'","numNodes":5,"logLevel":"INFO","pluginDir":"'${AVALANCHEGO_PLUGIN_PATH}'","blockchainSpecs":[{"vm_name":"blobvm","genesis":"/tmp/blobvm.json","chain_config":"'$CHAIN_CONFIG_PATH'","network_upgrade":"'$NETWORK_UPGRADE_PATH'","subnet_config":"'$SUBNET_CONFIG_PATH'"}]}'
# or
avalanche-network-runner control start \
--log-level debug \
--endpoint="0.0.0.0:8080" \
--avalanchego-path ${AVALANCHEGO_EXEC_PATH} \
--plugin-dir ${AVALANCHEGO_PLUGIN_PATH} \
--blockchain-specs '[{"vm_name": "blobvm", "genesis": "/tmp/blobvm.genesis.json", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'"}]'
--blockchain-specs '[{"vm_name": "blobvm", "genesis": "/tmp/blobvm.genesis.json", "chain_config": "'$CHAIN_CONFIG_PATH'", "network_upgrade": "'$NETWORK_UPGRADE_PATH'", "subnet_config": "'$SUBNET_CONFIG_PATH'"}]'
```
## `network-runner` RPC server: `timestampvm` example
Expand Down Expand Up @@ -817,6 +817,10 @@ type Config struct {
ConfigFile string `json:"configFile"`
// May be nil.
ChainConfigFiles map[string]string `json:"chainConfigFiles"`
// May be nil.
UpgradeConfigFiles map[string]string `json:"upgradeConfigFiles"`
// May be nil.
SubnetConfigFiles map[string]string `json:"subnetConfigFiles"`
// Flags can hold additional flags for the node.
// It can be empty.
// The precedence of flags handling is:
Expand Down
19 changes: 16 additions & 3 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,11 @@ func (c *client) Start(ctx context.Context, execPath string, opts ...OpOption) (
ret.applyOpts(opts)

req := &rpcpb.StartRequest{
ExecPath: execPath,
NumNodes: &ret.numNodes,
ChainConfigs: ret.chainConfigs,
ExecPath: execPath,
NumNodes: &ret.numNodes,
ChainConfigs: ret.chainConfigs,
UpgradeConfigs: ret.upgradeConfigs,
SubnetConfigs: ret.subnetConfigs,
}
if ret.whitelistedSubnets != "" {
req.WhitelistedSubnets = &ret.whitelistedSubnets
Expand Down Expand Up @@ -233,6 +235,7 @@ func (c *client) AddNode(ctx context.Context, name string, execPath string, opts
NodeConfig: &ret.globalNodeConfig,
ChainConfigs: ret.chainConfigs,
UpgradeConfigs: ret.upgradeConfigs,
SubnetConfigs: ret.subnetConfigs,
}

c.log.Info("add node", zap.String("name", name))
Expand All @@ -257,6 +260,7 @@ func (c *client) RestartNode(ctx context.Context, name string, opts ...OpOption)
}
req.ChainConfigs = ret.chainConfigs
req.UpgradeConfigs = ret.upgradeConfigs
req.SubnetConfigs = ret.subnetConfigs

c.log.Info("restart node", zap.String("name", name))
return c.controlc.RestartNode(ctx, req)
Expand Down Expand Up @@ -290,6 +294,7 @@ func (c *client) LoadSnapshot(ctx context.Context, snapshotName string, opts ...
SnapshotName: snapshotName,
ChainConfigs: ret.chainConfigs,
UpgradeConfigs: ret.upgradeConfigs,
SubnetConfigs: ret.subnetConfigs,
}
if ret.execPath != "" {
req.ExecPath = &ret.execPath
Expand Down Expand Up @@ -340,6 +345,7 @@ type Op struct {
numSubnets uint32
chainConfigs map[string]string
upgradeConfigs map[string]string
subnetConfigs map[string]string
reassignPortsIfUsed bool
dynamicPorts bool
}
Expand Down Expand Up @@ -409,6 +415,13 @@ func WithUpgradeConfigs(upgradeConfigs map[string]string) OpOption {
}
}

// Map from subnet id to its configuration json contents.
func WithSubnetConfigs(subnetConfigs map[string]string) OpOption {
return func(op *Op) {
op.subnetConfigs = subnetConfigs
}
}

// Map from node name to its custom node config
func WithCustomNodeConfigs(customNodeConfigs map[string]string) OpOption {
return func(op *Op) {
Expand Down
53 changes: 53 additions & 0 deletions cmd/control/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ var (
numSubnets uint32
chainConfigs string
upgradeConfigs string
subnetConfigs string
reassignPortsIfUsed bool
dynamicPorts bool
)
Expand Down Expand Up @@ -172,6 +173,12 @@ func newStartCommand() *cobra.Command {
"",
"[optional] JSON string of map from chain id to its upgrade file contents",
)
cmd.PersistentFlags().StringVar(
&subnetConfigs,
"subnet-configs",
"",
"[optional] JSON string of map from subnet id to its config file contents",
)
cmd.PersistentFlags().BoolVar(
&reassignPortsIfUsed,
"reassign-ports-if-used",
Expand Down Expand Up @@ -246,6 +253,13 @@ func startFunc(cmd *cobra.Command, args []string) error {
}
opts = append(opts, client.WithUpgradeConfigs(upgradeConfigsMap))
}
if subnetConfigs != "" {
subnetConfigsMap := make(map[string]string)
if err := json.Unmarshal([]byte(subnetConfigs), &subnetConfigsMap); err != nil {
return err
}
opts = append(opts, client.WithSubnetConfigs(subnetConfigsMap))
}

ctx := getAsyncContext()

Expand Down Expand Up @@ -539,6 +553,12 @@ func newAddNodeCommand() *cobra.Command {
"",
"[optional] JSON string of map from chain id to its upgrade file contents",
)
cmd.PersistentFlags().StringVar(
&subnetConfigs,
"subnet-configs",
"",
"[optional] JSON string of map from subnet id to its config file contents",
)
return cmd
}

Expand Down Expand Up @@ -577,6 +597,13 @@ func addNodeFunc(cmd *cobra.Command, args []string) error {
}
opts = append(opts, client.WithUpgradeConfigs(upgradeConfigsMap))
}
if subnetConfigs != "" {
subnetConfigsMap := make(map[string]string)
if err := json.Unmarshal([]byte(subnetConfigs), &subnetConfigsMap); err != nil {
return err
}
opts = append(opts, client.WithSubnetConfigs(subnetConfigsMap))
}

ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
info, err := cli.AddNode(
Expand Down Expand Up @@ -625,6 +652,12 @@ func newRestartNodeCommand() *cobra.Command {
"",
"[optional] JSON string of map from chain id to its upgrade file contents",
)
cmd.PersistentFlags().StringVar(
&subnetConfigs,
"subnet-configs",
"",
"[optional] JSON string of map from subnet id to its config file contents",
)
return cmd
}

Expand Down Expand Up @@ -656,6 +689,13 @@ func restartNodeFunc(cmd *cobra.Command, args []string) error {
}
opts = append(opts, client.WithUpgradeConfigs(upgradeConfigsMap))
}
if subnetConfigs != "" {
subnetConfigsMap := make(map[string]string)
if err := json.Unmarshal([]byte(subnetConfigs), &subnetConfigsMap); err != nil {
return err
}
opts = append(opts, client.WithSubnetConfigs(subnetConfigsMap))
}

ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
info, err := cli.RestartNode(
Expand Down Expand Up @@ -864,6 +904,12 @@ func newLoadSnapshotCommand() *cobra.Command {
"",
"[optional] JSON string of map from chain id to its upgrade file contents",
)
cmd.PersistentFlags().StringVar(
&subnetConfigs,
"subnet-configs",
"",
"[optional] JSON string of map from subnet id to its config file contents",
)
cmd.PersistentFlags().StringVar(
&globalNodeConfig,
"global-node-config",
Expand Down Expand Up @@ -907,6 +953,13 @@ func loadSnapshotFunc(cmd *cobra.Command, args []string) error {
}
opts = append(opts, client.WithUpgradeConfigs(upgradeConfigsMap))
}
if subnetConfigs != "" {
subnetConfigsMap := make(map[string]string)
if err := json.Unmarshal([]byte(subnetConfigs), &subnetConfigsMap); err != nil {
return err
}
opts = append(opts, client.WithSubnetConfigs(subnetConfigsMap))
}

if globalNodeConfig != "" {
ux.Print(log, logging.Yellow.Wrap("global node config provided, will be applied to all nodes: %s"), globalNodeConfig)
Expand Down
21 changes: 19 additions & 2 deletions local/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ func (ln *localNetwork) restartNodesWithWhitelistedSubnets(
delete(nodeConfig.Flags, config.WhitelistedSubnetsKey)

ln.log.Info("removing and adding back the node for whitelisted subnets", zap.String("node-name", nodeName))
if err := ln.restartNode(ctx, nodeName, "", "", nil, nil); err != nil {
if err := ln.restartNode(ctx, nodeName, "", "", nil, nil, nil); err != nil {
return err
}

Expand Down Expand Up @@ -751,7 +751,7 @@ func (ln *localNetwork) createBlockchainConfigFiles(
for i, chainSpec := range chainSpecs {
chainAlias := blockchainTxs[i].ID().String()

// create config and network upgrade files
// create config, network upgrade and subnet config files
if chainSpec.ChainConfig != nil {
created = true
for nodeName := range ln.nodes {
Expand All @@ -774,6 +774,17 @@ func (ln *localNetwork) createBlockchainConfigFiles(
}
}
}
if chainSpec.SubnetConfig != nil {
created = true
for nodeName := range ln.nodes {
nodeRootDir := getNodeDir(ln.rootDir, nodeName)
subnetConfigDir := filepath.Join(nodeRootDir, subnetConfigSubDir)
subnetConfigPath := filepath.Join(subnetConfigDir, *chainSpec.SubnetId+".json")
if err := createFileAndWrite(subnetConfigPath, chainSpec.SubnetConfig); err != nil {
return false, fmt.Errorf("couldn't write chain config file at %q: %w", subnetConfigPath, err)
}
}
}
// update config info for snapshopt/restart purposes
// put into defaults and reset node specifics
if chainSpec.ChainConfig != nil {
Expand All @@ -788,6 +799,12 @@ func (ln *localNetwork) createBlockchainConfigFiles(
delete(ln.nodes[nodeName].config.UpgradeConfigFiles, chainAlias)
}
}
if chainSpec.SubnetConfig != nil {
ln.subnetConfigFiles[*chainSpec.SubnetId] = string(chainSpec.SubnetConfig)
for nodeName := range ln.nodes {
delete(ln.nodes[nodeName].config.SubnetConfigFiles, *chainSpec.SubnetId)
}
}
}
return created, nil
}
Expand Down
44 changes: 30 additions & 14 deletions local/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,37 @@ func writeFiles(genesis []byte, nodeRootDir string, nodeConfig *node.Config) ([]
return nil, fmt.Errorf("couldn't write file at %q: %w", f.path, err)
}
}
if nodeConfig.ChainConfigFiles != nil || nodeConfig.UpgradeConfigFiles != nil {
// only one flag and multiple files
chainConfigDir := filepath.Join(nodeRootDir, chainConfigSubDir)
flags = append(flags, fmt.Sprintf("--%s=%s", config.ChainConfigDirKey, chainConfigDir))
for chainAlias, chainConfigFile := range nodeConfig.ChainConfigFiles {
chainConfigPath := filepath.Join(chainConfigDir, chainAlias, configFileName)
if err := createFileAndWrite(chainConfigPath, []byte(chainConfigFile)); err != nil {
return nil, fmt.Errorf("couldn't write file at %q: %w", chainConfigPath, err)
}
// chain configs dir
chainConfigDir := filepath.Join(nodeRootDir, chainConfigSubDir)
if err := os.MkdirAll(chainConfigDir, 0o750); err != nil {
return nil, err
}
flags = append(flags, fmt.Sprintf("--%s=%s", config.ChainConfigDirKey, chainConfigDir))
// subnet configs dir
subnetConfigDir := filepath.Join(nodeRootDir, subnetConfigSubDir)
if err := os.MkdirAll(subnetConfigDir, 0o750); err != nil {
return nil, err
}
flags = append(flags, fmt.Sprintf("--%s=%s", config.SubnetConfigDirKey, subnetConfigDir))
// chain configs
for chainAlias, chainConfigFile := range nodeConfig.ChainConfigFiles {
chainConfigPath := filepath.Join(chainConfigDir, chainAlias, configFileName)
if err := createFileAndWrite(chainConfigPath, []byte(chainConfigFile)); err != nil {
return nil, fmt.Errorf("couldn't write file at %q: %w", chainConfigPath, err)
}
for chainAlias, chainUpgradeFile := range nodeConfig.UpgradeConfigFiles {
chainUpgradePath := filepath.Join(chainConfigDir, chainAlias, upgradeConfigFileName)
if err := createFileAndWrite(chainUpgradePath, []byte(chainUpgradeFile)); err != nil {
return nil, fmt.Errorf("couldn't write file at %q: %w", chainUpgradePath, err)
}
}
// network upgrades
for chainAlias, chainUpgradeFile := range nodeConfig.UpgradeConfigFiles {
chainUpgradePath := filepath.Join(chainConfigDir, chainAlias, upgradeConfigFileName)
if err := createFileAndWrite(chainUpgradePath, []byte(chainUpgradeFile)); err != nil {
return nil, fmt.Errorf("couldn't write file at %q: %w", chainUpgradePath, err)
}
}
// subnet configs
for subnetID, subnetConfigFile := range nodeConfig.SubnetConfigFiles {
subnetConfigPath := filepath.Join(subnetConfigDir, subnetID+".json")
if err := createFileAndWrite(subnetConfigPath, []byte(subnetConfigFile)); err != nil {
return nil, fmt.Errorf("couldn't write file at %q: %w", subnetConfigPath, err)
}
}
return flags, nil
Expand Down
Loading

0 comments on commit a70fbda

Please sign in to comment.