diff --git a/local/network.go b/local/network.go index 3324b31e..c486db84 100644 --- a/local/network.go +++ b/local/network.go @@ -176,6 +176,10 @@ func NewNetwork( redirectStderr bool, walletPrivateKey string, ) (network.Network, error) { + beaconSet, err := utils.BeaconMapToSet(networkConfig.BeaconConfig) + if err != nil { + return nil, err + } net, err := newNetwork( log, api.NewAPIClient, @@ -192,7 +196,7 @@ func NewNetwork( redirectStdout, redirectStderr, walletPrivateKey, - networkConfig.BeaconConfig, + beaconSet, ) if err != nil { return net, err @@ -393,10 +397,6 @@ func NewDefaultConfigNNodes( if int(numNodes) == 1 && !utils.IsPublicNetwork(networkID) && len(beaconConfig) == 0 { flags[config.SybilProtectionEnabledKey] = false } - beaconSet, err := utils.BeaconMapToSet(beaconConfig) - if err != nil { - return network.Config{}, err - } cfg := network.Config{ NetworkID: networkID, Flags: flags, @@ -405,7 +405,7 @@ func NewDefaultConfigNNodes( ChainConfigFiles: map[string]string{}, UpgradeConfigFiles: map[string]string{}, SubnetConfigFiles: map[string]string{}, - BeaconConfig: beaconSet, + BeaconConfig: beaconConfig, } if len(upgradePath) != 0 { upgrade, err := os.ReadFile(upgradePath) @@ -485,6 +485,12 @@ func (ln *localNetwork) loadConfig(ctx context.Context, networkConfig network.Co ln.flags = networkConfig.Flags ln.binaryPath = networkConfig.BinaryPath ln.chainConfigFiles = networkConfig.ChainConfigFiles + + beaconConf, err := utils.BeaconMapToSet(networkConfig.BeaconConfig) + if err != nil { + return err + } + ln.bootstraps = beaconConf if ln.chainConfigFiles == nil { ln.chainConfigFiles = map[string]string{} } @@ -660,7 +666,7 @@ func (ln *localNetwork) addNode(nodeConfig node.Config) (node.Node, error) { if err != nil { return nil, err } - if !isPausedNode && nodeConfig.IsBeacon { + if nodeConfig.IsBeacon && ln.bootstraps.Len() == 0 && !isPausedNode { if err := ln.bootstraps.Add(beacon.New(nodeID, netip.AddrPortFrom( ip, nodeData.p2pPort, diff --git a/local/snapshot.go b/local/snapshot.go index c4c72765..17ca28d2 100644 --- a/local/snapshot.go +++ b/local/snapshot.go @@ -158,6 +158,10 @@ func (ln *localNetwork) persistNetwork() error { nodeConfigs = append(nodeConfigs, nodeConfig) } // save network conf + beaconConf, err := utils.BeaconMapFromSet(ln.bootstraps) + if err != nil { + return err + } networkConfig := network.Config{ NetworkID: ln.networkID, Genesis: string(ln.genesisData), @@ -168,7 +172,7 @@ func (ln *localNetwork) persistNetwork() error { ChainConfigFiles: ln.chainConfigFiles, UpgradeConfigFiles: ln.upgradeConfigFiles, SubnetConfigFiles: ln.subnetConfigFiles, - BeaconConfig: ln.bootstraps, + BeaconConfig: beaconConf, } networkConfigJSON, err := json.MarshalIndent(networkConfig, "", " ") if err != nil { diff --git a/network/config.go b/network/config.go index 414723c6..9164bb76 100644 --- a/network/config.go +++ b/network/config.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "math/big" + "net/netip" "strconv" "time" @@ -12,7 +13,6 @@ import ( "github.com/ava-labs/avalanche-network-runner/utils" "github.com/ava-labs/avalanchego/genesis" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/beacon" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/utils/units" @@ -57,7 +57,7 @@ type Config struct { // Subnet config files to use per default, if not specified in node config SubnetConfigFiles map[string]string `json:"subnetConfigFiles"` // Beacon config used for all nodes, can be empty - BeaconConfig beacon.Set `json:"beaconConfig"` + BeaconConfig map[ids.NodeID]netip.AddrPort `json:"beaconConfig"` // Upgrade file used for all nodes, can be empty Upgrade string `json:"upgrade"` } diff --git a/utils/utils.go b/utils/utils.go index ba32608c..679c5194 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -7,6 +7,7 @@ import ( "io/fs" "net/netip" "os" + "strings" "time" rpcb "github.com/ava-labs/avalanche-network-runner/rpcpb" @@ -184,3 +185,26 @@ func BeaconMapToSet(beaconMap map[ids.NodeID]netip.AddrPort) (beacon.Set, error) } return set, nil } + +func BeaconMapFromSet(beaconSet beacon.Set) (map[ids.NodeID]netip.AddrPort, error) { + beaconMap := make(map[ids.NodeID]netip.AddrPort) + beaconIDs := strings.Split(beaconSet.IDsArg(), ",") + beaconIPs := strings.Split(beaconSet.IPsArg(), ",") + + if len(beaconIDs) != len(beaconIPs) { + return nil, fmt.Errorf("beacon IDs and IPs do not match") + } + + for i := 0; i < len(beaconIDs); i++ { + beaconID, err := ids.NodeIDFromString(beaconIDs[i]) + if err != nil { + return nil, fmt.Errorf("failed to parse beacon ID: %w", err) + } + beaconIP, err := netip.ParseAddrPort(beaconIPs[i]) + if err != nil { + return nil, fmt.Errorf("failed to parse beacon IP: %w", err) + } + beaconMap[beaconID] = beaconIP + } + return beaconMap, nil +}