mirror of
https://github.com/luxfi/cli.git
synced 2026-10-30 17:01:20 +00:00
667 lines
19 KiB
Go
667 lines
19 KiB
Go
// Copyright (C) 2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
package localnet
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/luxfi/cli/v2/pkg/application"
|
|
"github.com/luxfi/cli/v2/pkg/models"
|
|
sdkutils "github.com/luxfi/cli/v2/sdk/utils"
|
|
"github.com/luxfi/node/v2/v2/genesis"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/node/v2/v2/tests/fixture/tmpnet"
|
|
|
|
dircopy "github.com/otiai10/copy"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// A connection setting is either the network ID for a public network,
|
|
// or the full settings for a custom network
|
|
type ConnectionSettings struct {
|
|
NetworkID uint32
|
|
Genesis []byte
|
|
Upgrade []byte
|
|
BootstrapIDs []string
|
|
BootstrapIPs []string
|
|
}
|
|
|
|
// Create a local cluster [clusterName] connected to another network,
|
|
// based on [connectionSettings].
|
|
// Set up [numNodes] nodes, either with fresh keys and ports, or based on settings given by [nodeSettings]
|
|
// If [downloadDB] is set, and network is testnet, downloads the current luxd DB -note: db download is not desired
|
|
// if migrating from a network runner cluster-
|
|
// If [bootstrap] is set, starts the nodes
|
|
func CreateLocalCluster(
|
|
app *application.Lux,
|
|
printFunc func(msg string, args ...interface{}),
|
|
clusterName string,
|
|
luxdBinPath string,
|
|
pluginDir string,
|
|
defaultFlags map[string]interface{},
|
|
connectionSettings ConnectionSettings,
|
|
numNodes uint32,
|
|
nodeSettings []NodeSetting,
|
|
trackedSubnets []ids.ID,
|
|
networkModel models.Network,
|
|
downloadDB bool,
|
|
bootstrap bool,
|
|
) (*tmpnet.Network, error) {
|
|
if len(connectionSettings.BootstrapIDs) != len(connectionSettings.BootstrapIPs) {
|
|
return nil, fmt.Errorf("number of bootstrap IDs and bootstrap IP:port pairs must be equal")
|
|
}
|
|
nodes, err := GetNewTmpNetNodes(numNodes, nodeSettings, trackedSubnets)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var unparsedGenesis *genesis.UnparsedConfig
|
|
if len(connectionSettings.Genesis) > 0 {
|
|
unparsedGenesis = &genesis.UnparsedConfig{}
|
|
if err := json.Unmarshal(connectionSettings.Genesis, unparsedGenesis); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal genesis: %w", err)
|
|
}
|
|
}
|
|
ctx, cancel := networkModel.BootstrappingContext()
|
|
defer cancel()
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
network, err := TmpNetCreate(
|
|
ctx,
|
|
app.Log,
|
|
networkDir,
|
|
luxdBinPath,
|
|
pluginDir,
|
|
connectionSettings.NetworkID,
|
|
connectionSettings.BootstrapIPs,
|
|
connectionSettings.BootstrapIDs,
|
|
unparsedGenesis,
|
|
connectionSettings.Upgrade,
|
|
defaultFlags,
|
|
nodes,
|
|
false,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// for 1-node clusters we need to overwrite tmpnet's default
|
|
if err := TmpNetEnableSybilProtection(networkDir); err != nil {
|
|
return nil, err
|
|
}
|
|
if downloadDB {
|
|
// preseed nodes db from public archive. ignore errors
|
|
nodeIDs := []string{}
|
|
for _, node := range network.Nodes {
|
|
nodeIDs = append(nodeIDs, node.NodeID.String())
|
|
}
|
|
if err := DownloadLuxdDB(networkModel, networkDir, nodeIDs, app.Log, printFunc); err != nil {
|
|
app.Log.Info("seeding public archive data finished with error: %v. Ignored if any", zap.Error(err))
|
|
}
|
|
}
|
|
if bootstrap {
|
|
if err := TmpNetBootstrap(ctx, app.Log, networkDir); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return network, nil
|
|
}
|
|
|
|
// Adds a new fresh node with given [httpPort] and [stakingPort]
|
|
// into cluster [clusterName] conf, and starts it
|
|
// Copies all node conf from the first node of the cluster,
|
|
// including connection settings, tracked subnets, blockchain config files.
|
|
// Downloads luxd DB for testnet nodes
|
|
// Finally waits for all the blockchains validated by the cluster to be bootstrapped
|
|
func AddNodeToLocalCluster(
|
|
app *application.Lux,
|
|
printFunc func(msg string, args ...interface{}),
|
|
clusterName string,
|
|
httpPort uint32,
|
|
stakingPort uint32,
|
|
) (*tmpnet.Node, error) {
|
|
network, err := GetLocalCluster(app, clusterName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
node, err := GetTmpNetFirstNode(network)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// copy network connection info + tracked subnets
|
|
// creates node dir
|
|
newNode, err := TmpNetCopyNode(node)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// copy chain config files into new dir
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
sourceDir := filepath.Join(networkDir, node.NodeID.String(), "configs", "chains")
|
|
targetDir := filepath.Join(networkDir, newNode.NodeID.String(), "configs", "chains")
|
|
if err := dircopy.Copy(sourceDir, targetDir); err != nil {
|
|
return nil, fmt.Errorf("failure migrating chain configs dir %s into %s: %w", sourceDir, targetDir, err)
|
|
}
|
|
nodeIDs := []string{newNode.NodeID.String()}
|
|
networkModel, err := GetLocalClusterNetworkModel(app, clusterName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := DownloadLuxdDB(networkModel, networkDir, nodeIDs, app.Log, printFunc); err != nil {
|
|
app.Log.Info("seeding public archive data finished with error: %v. Ignored if any", zap.Error(err))
|
|
}
|
|
printFunc("Waiting for node: %s to be bootstrapping P-Chain", newNode.NodeID)
|
|
ctx, cancel := networkModel.BootstrappingContext()
|
|
defer cancel()
|
|
if err = TmpNetAddNode(
|
|
ctx,
|
|
app.Log,
|
|
network,
|
|
newNode,
|
|
httpPort,
|
|
stakingPort,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
blockchains, err := GetLocalClusterTrackedBlockchains(app, clusterName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, blockchain := range blockchains {
|
|
printFunc("Waiting for node: %s to be bootstrapping %s", newNode.NodeID, blockchain.Name)
|
|
if err := WaitLocalClusterBlockchainBootstrapped(
|
|
ctx,
|
|
app,
|
|
clusterName,
|
|
blockchain.ID.String(),
|
|
blockchain.SubnetID,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
printFunc("")
|
|
printFunc("Node logs directory: %s/%s/logs", networkDir, newNode.NodeID)
|
|
printFunc("")
|
|
|
|
printFunc("URI: %s", newNode.URI)
|
|
printFunc("Node ID: %s", newNode.NodeID)
|
|
printFunc("")
|
|
|
|
return newNode, nil
|
|
}
|
|
|
|
// Returns the directory associated to the local cluster
|
|
func GetLocalClusterDir(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) string {
|
|
return app.GetLocalClusterDir(clusterName)
|
|
}
|
|
|
|
// Returns the tmpnet associated to the local cluster
|
|
func GetLocalCluster(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) (*tmpnet.Network, error) {
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
return GetTmpNetNetwork(networkDir)
|
|
}
|
|
|
|
// Indicates if the local cluster exists and has valid data on its directory
|
|
func LocalClusterExists(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) bool {
|
|
_, err := GetLocalCluster(app, clusterName)
|
|
return err == nil
|
|
}
|
|
|
|
// Stops local cluster [clusterName]
|
|
func LocalClusterStop(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) error {
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
return TmpNetStop(networkDir)
|
|
}
|
|
|
|
// Removes local cluster [clusterName]
|
|
// First stops it if needed
|
|
func LocalClusterRemove(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) error {
|
|
if clusterName == "" {
|
|
return fmt.Errorf("invalid cluster '%s'", clusterName)
|
|
}
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
if !sdkutils.DirExists(networkDir) {
|
|
return fmt.Errorf("cluster directory %s does not exist", networkDir)
|
|
}
|
|
_ = LocalClusterStop(app, clusterName)
|
|
return os.RemoveAll(networkDir)
|
|
}
|
|
|
|
// Indicates if local cluster is running
|
|
func LocalClusterIsRunning(app *application.Lux, clusterName string) (bool, error) {
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
status, err := GetTmpNetRunningStatus(networkDir)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return status == Running, nil
|
|
}
|
|
|
|
// Indicates if local cluster is partially running (only some nodes are executing)
|
|
// Useful for stop and destroy flows that need to accomplish the operation
|
|
// regardless the cluster is operative
|
|
func LocalClusterIsPartiallyRunning(app *application.Lux, clusterName string) (bool, error) {
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
status, err := GetTmpNetRunningStatus(networkDir)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return status != NotRunning, nil
|
|
}
|
|
|
|
// Indicates if the cluster [clusterName] is connected to a network of kind [networkModel]
|
|
func LocalClusterIsConnectedToNetwork(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
networkModel models.Network,
|
|
) (bool, error) {
|
|
network, err := GetLocalCluster(app, clusterName)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
networkID, err := GetTmpNetNetworkID(network)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return networkID == networkModel.ID, nil
|
|
}
|
|
|
|
// Returns the network model the local cluster given by [clusterName]
|
|
func GetLocalClusterNetworkModel(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) (models.Network, error) {
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
return GetNetworkModel(networkDir)
|
|
}
|
|
|
|
// Gets a list of clusters connected to local network that are also running
|
|
func GetRunningLocalClustersConnectedToLocalNetwork(app *application.Lux) ([]string, error) {
|
|
return GetFilteredLocalClusters(app, true, models.NewLocalNetwork(), "")
|
|
}
|
|
|
|
// Gets a list of clusters that are running
|
|
func GetRunningLocalClusters(app *application.Lux) ([]string, error) {
|
|
return GetFilteredLocalClusters(app, true, models.UndefinedNetwork, "")
|
|
}
|
|
|
|
// Gets a list of clusters filtered by running status, network model, and
|
|
// validated blockchains
|
|
func GetFilteredLocalClusters(
|
|
app *application.Lux,
|
|
running bool,
|
|
network models.Network,
|
|
blockchainName string,
|
|
) ([]string, error) {
|
|
clusters, err := GetLocalClusters(app)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
filteredClusters := []string{}
|
|
for _, clusterName := range clusters {
|
|
if running {
|
|
if isRunning, err := LocalClusterIsRunning(app, clusterName); err != nil {
|
|
return nil, err
|
|
} else if !isRunning {
|
|
continue
|
|
}
|
|
if blockchainName != "" {
|
|
blockchains, err := GetLocalClusterTrackedBlockchains(app, clusterName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
blockchainNames := sdkutils.Map(blockchains, func(i BlockchainInfo) string { return i.Name })
|
|
if !sdkutils.Belongs(blockchainNames, blockchainName) {
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
if network != models.UndefinedNetwork {
|
|
if isForNetwork, err := LocalClusterIsConnectedToNetwork(app, clusterName, network); err != nil {
|
|
return nil, err
|
|
} else if !isForNetwork {
|
|
continue
|
|
}
|
|
}
|
|
filteredClusters = append(filteredClusters, clusterName)
|
|
}
|
|
return filteredClusters, nil
|
|
}
|
|
|
|
// Get list of all local clusters
|
|
func GetLocalClusters(app *application.Lux) ([]string, error) {
|
|
clusters := []string{}
|
|
clustersDir := app.GetLocalClustersDir()
|
|
entries, err := os.ReadDir(clustersDir)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read local clusters dir %s: %w", clustersDir, err)
|
|
}
|
|
for _, entry := range entries {
|
|
if !entry.IsDir() {
|
|
continue
|
|
}
|
|
clusterName := entry.Name()
|
|
if _, err := GetLocalCluster(app, clusterName); err != nil {
|
|
continue
|
|
}
|
|
clusters = append(clusters, clusterName)
|
|
}
|
|
return clusters, nil
|
|
}
|
|
|
|
// Waits for cluster [clusterName] to have [blockchainID] bootstrapped
|
|
func WaitLocalClusterBlockchainBootstrapped(
|
|
ctx context.Context,
|
|
app *application.Lux,
|
|
clusterName string,
|
|
blockchainID string,
|
|
subnetID ids.ID,
|
|
) error {
|
|
network, err := GetLocalCluster(app, clusterName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return WaitTmpNetBlockchainBootstrapped(ctx, network, blockchainID, subnetID)
|
|
}
|
|
|
|
// Get connections settings needed to connect a cluster to the local network
|
|
func GetLocalNetworkConnectionInfo(
|
|
app *application.Lux,
|
|
) (ConnectionSettings, error) {
|
|
connectionSettings := ConnectionSettings{}
|
|
network, err := GetLocalNetwork(app)
|
|
if err != nil {
|
|
return ConnectionSettings{}, fmt.Errorf("failed to connect to local network: %w", err)
|
|
}
|
|
connectionSettings.NetworkID, err = GetTmpNetNetworkID(network)
|
|
if err != nil {
|
|
return ConnectionSettings{}, err
|
|
}
|
|
networkDir, err := GetLocalNetworkDir(app)
|
|
if err != nil {
|
|
return ConnectionSettings{}, fmt.Errorf("failed to connect to local network: %w", err)
|
|
}
|
|
connectionSettings.BootstrapIPs, connectionSettings.BootstrapIDs, err = GetTmpNetBootstrappers(networkDir, ids.EmptyNodeID)
|
|
if err != nil {
|
|
return ConnectionSettings{}, err
|
|
}
|
|
connectionSettings.Genesis, err = GetTmpNetGenesis(networkDir)
|
|
if err != nil {
|
|
return ConnectionSettings{}, err
|
|
}
|
|
connectionSettings.Upgrade, err = GetTmpNetUpgrade(networkDir)
|
|
if err != nil {
|
|
return ConnectionSettings{}, err
|
|
}
|
|
return connectionSettings, nil
|
|
}
|
|
|
|
// Indicates if a blockchain is bootstrapped on the local network
|
|
// If the network has no validators for the blockchain, it fails
|
|
func IsLocalClusterBlockchainBootstrapped(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
blockchainID string,
|
|
subnetID ids.ID,
|
|
) (bool, error) {
|
|
network, err := GetLocalCluster(app, clusterName)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
ctx, cancel := sdkutils.GetAPIContext()
|
|
defer cancel()
|
|
return IsTmpNetBlockchainBootstrapped(ctx, network, blockchainID, subnetID)
|
|
}
|
|
|
|
// Indicates if P-Chain is bootstrapped on the network, and also if
|
|
// all blockchain that have validators on the network, are bootstrapped
|
|
func LocalClusterHealth(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) (bool, bool, error) {
|
|
pChainBootstrapped, err := IsLocalClusterBlockchainBootstrapped(app, clusterName, "P", ids.Empty)
|
|
if err != nil {
|
|
return false, false, err
|
|
}
|
|
blockchains, err := GetLocalClusterBlockchainsInfo(app, clusterName)
|
|
if err != nil {
|
|
return pChainBootstrapped, false, err
|
|
}
|
|
for _, blockchain := range blockchains {
|
|
if isTracking, err := IsLocalClusterTrackingSubnet(app, clusterName, blockchain.SubnetID); err != nil {
|
|
return pChainBootstrapped, false, err
|
|
} else if !isTracking {
|
|
continue
|
|
}
|
|
if blockchainBootstrapped, err := IsLocalClusterBlockchainBootstrapped(app, clusterName, blockchain.ID.String(), blockchain.SubnetID); err != nil {
|
|
return pChainBootstrapped, false, err
|
|
} else if !blockchainBootstrapped {
|
|
return pChainBootstrapped, false, nil
|
|
}
|
|
}
|
|
return pChainBootstrapped, true, nil
|
|
}
|
|
|
|
// Returns blockchain info for all non standard blockchains deployed into the network
|
|
func GetLocalClusterBlockchainsInfo(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) ([]BlockchainInfo, error) {
|
|
endpoint, err := GetLocalClusterEndpoint(app, clusterName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return GetBlockchainsInfo(endpoint)
|
|
}
|
|
|
|
// Returns blockchain info for all blockchains deployed into the network, that are managed by CLI
|
|
func GetLocalClusterManagedBlockchainsInfo(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) ([]BlockchainInfo, error) {
|
|
networkModel, err := GetLocalClusterNetworkModel(app, clusterName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return GetManagedBlockchainsInfo(app, networkModel)
|
|
}
|
|
|
|
// Returns the endpoint associated to the cluster
|
|
// If the network is not running it errors
|
|
func GetLocalClusterEndpoint(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) (string, error) {
|
|
network, err := GetLocalCluster(app, clusterName)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return GetTmpNetEndpoint(network)
|
|
}
|
|
|
|
// Indicates if the cluster tracks a subnet at all
|
|
func IsLocalClusterTrackingSubnet(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
subnetID ids.ID,
|
|
) (bool, error) {
|
|
network, err := GetLocalCluster(app, clusterName)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return IsTmpNetNodeTrackingSubnet(network.Nodes, subnetID)
|
|
}
|
|
|
|
// Returns the subnets tracked by [clusterName]
|
|
func GetLocalClusterTrackedSubnets(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) ([]ids.ID, error) {
|
|
network, err := GetLocalCluster(app, clusterName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return GetTmpNetTrackedSubnets(network.Nodes)
|
|
}
|
|
|
|
// Get local cluster URIs
|
|
func GetLocalClusterURIs(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) ([]string, error) {
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
return GetTmpNetNodeURIsWithFix(networkDir)
|
|
}
|
|
|
|
// Return a list of blockchains that are tracked at least by one node in the cluster
|
|
func GetLocalClusterTrackedBlockchains(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) ([]BlockchainInfo, error) {
|
|
blockchains, err := GetLocalClusterBlockchainsInfo(app, clusterName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
trackedBlockchains := []BlockchainInfo{}
|
|
for _, blockchain := range blockchains {
|
|
if isTracking, err := IsLocalClusterTrackingSubnet(app, clusterName, blockchain.SubnetID); err != nil {
|
|
return nil, err
|
|
} else if isTracking {
|
|
trackedBlockchains = append(trackedBlockchains, blockchain)
|
|
}
|
|
}
|
|
return trackedBlockchains, nil
|
|
}
|
|
|
|
// Return a list of managed blockchains that are tracked at least by one node in the cluster
|
|
func GetLocalClusterManagedTrackedBlockchains(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) ([]BlockchainInfo, error) {
|
|
blockchains, err := GetLocalClusterManagedBlockchainsInfo(app, clusterName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
trackedBlockchains := []BlockchainInfo{}
|
|
for _, blockchain := range blockchains {
|
|
if isTracking, err := IsLocalClusterTrackingSubnet(app, clusterName, blockchain.SubnetID); err != nil {
|
|
return nil, err
|
|
} else if isTracking {
|
|
trackedBlockchains = append(trackedBlockchains, blockchain)
|
|
}
|
|
}
|
|
return trackedBlockchains, nil
|
|
}
|
|
|
|
// Tracks the subnet of [blockchainName] in the cluster given by [clusterName]
|
|
func LocalClusterTrackSubnet(
|
|
app *application.Lux,
|
|
printFunc func(msg string, args ...interface{}),
|
|
clusterName string,
|
|
blockchainName string,
|
|
) error {
|
|
if !LocalClusterExists(app, clusterName) {
|
|
return fmt.Errorf("local cluster %q is not found", clusterName)
|
|
}
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
return TrackSubnet(
|
|
app,
|
|
printFunc,
|
|
blockchainName,
|
|
networkDir,
|
|
nil,
|
|
)
|
|
}
|
|
|
|
// Loads an already existing cluster [clusterName]
|
|
// Waits for all blockchains validated by the cluster to be bootstrapped
|
|
// Sets default aliases for all blockchains validated by the cluster
|
|
// If [blockchainName] is given, updates the blockchain configuration for it
|
|
func LoadLocalCluster(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
luxdBinaryPath string,
|
|
) error {
|
|
if !LocalClusterExists(app, clusterName) {
|
|
return fmt.Errorf("local cluster %q is not found", clusterName)
|
|
}
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
blockchains, err := GetLocalClusterManagedTrackedBlockchains(app, clusterName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
blockchainNames := sdkutils.Map(blockchains, func(i BlockchainInfo) string { return i.Name })
|
|
for _, blockchainName := range blockchainNames {
|
|
if err := UpdateBlockchainConfig(
|
|
app,
|
|
networkDir,
|
|
blockchainName,
|
|
); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
networkModel, err := GetLocalClusterNetworkModel(app, clusterName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ctx, cancel := networkModel.BootstrappingContext()
|
|
defer cancel()
|
|
if _, err := TmpNetLoad(ctx, app.Log, networkDir, luxdBinaryPath); err != nil {
|
|
return err
|
|
}
|
|
blockchains, err = GetLocalClusterTrackedBlockchains(app, clusterName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, blockchain := range blockchains {
|
|
if err := WaitLocalClusterBlockchainBootstrapped(
|
|
ctx,
|
|
app,
|
|
clusterName,
|
|
blockchain.ID.String(),
|
|
blockchain.SubnetID,
|
|
); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if networkModel.Kind == models.Local {
|
|
return TmpNetSetDefaultAliases(ctx, networkDir)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Sets default aliases for all blockchains validated by the cluster
|
|
func RefreshLocalClusterAliases(
|
|
app *application.Lux,
|
|
clusterName string,
|
|
) error {
|
|
ctx, cancel := sdkutils.GetAPIContext()
|
|
defer cancel()
|
|
networkDir := GetLocalClusterDir(app, clusterName)
|
|
return TmpNetSetDefaultAliases(ctx, networkDir)
|
|
}
|
|
|
|
// Returns stardard cluster name as generated from [network] and [blockchainName]
|
|
func LocalClusterName(network models.Network, blockchainName string) string {
|
|
blockchainNameComponent := strings.ReplaceAll(blockchainName, " ", "-")
|
|
networkNameComponent := strings.ReplaceAll(strings.ToLower(network.Name()), " ", "-")
|
|
return fmt.Sprintf("%s-local-node-%s", blockchainNameComponent, networkNameComponent)
|
|
}
|