Files

198 lines
5.1 KiB
Go

// Copyright (C) 2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package localnet
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"github.com/luxfi/cli/v2/pkg/application"
"github.com/luxfi/cli/v2/pkg/models"
"github.com/luxfi/cli/v2/pkg/utils"
"github.com/luxfi/cli/v2/pkg/ux"
"github.com/luxfi/ids"
"github.com/luxfi/node/v2/v2/wallet/subnet/primary"
)
// Update network given by [networkDir], with all blockchain config of [blockchainName]
func UpdateBlockchainConfig(
app *application.Lux,
networkDir string,
blockchainName string,
) error {
networkModel, err := GetNetworkModel(networkDir)
if err != nil {
return err
}
sc, err := app.LoadSidecar(blockchainName)
if err != nil {
return err
}
if sc.Networks[networkModel.Name()].BlockchainID == ids.Empty {
return fmt.Errorf("blockchain %s has not been deployed to %s", blockchainName, networkModel.Name())
}
blockchainID := sc.Networks[networkModel.Name()].BlockchainID
subnetID := sc.Networks[networkModel.Name()].SubnetID
var (
blockchainConfig []byte
blockchainUpgrades []byte
subnetConfig []byte
nodeConfig map[string]interface{}
)
vmID, err := utils.VMID(blockchainName)
if err != nil {
return err
}
vmBinaryPath, err := SetupVMBinary(app, blockchainName)
if err != nil {
return fmt.Errorf("failed to setup VM binary: %w", err)
}
if app.ChainConfigExists(blockchainName) {
blockchainConfig, err = os.ReadFile(app.GetChainConfigPath(blockchainName))
if err != nil {
return err
}
}
if app.NetworkUpgradeExists(blockchainName) {
blockchainUpgrades, err = os.ReadFile(app.GetUpgradeBytesFilepath(blockchainName))
if err != nil {
return err
}
}
if app.LuxdSubnetConfigExists(blockchainName) {
subnetConfig, err = os.ReadFile(app.GetLuxdSubnetConfigPath(blockchainName))
if err != nil {
return err
}
}
perNodeBlockchainConfig, err := app.GetPerNodeBlockchainConfig(blockchainName)
if err != nil {
return err
}
// general node config
nodeConfigStr, err := app.Conf.LoadNodeConfig()
if err != nil {
return err
}
if err := json.Unmarshal([]byte(nodeConfigStr), &nodeConfig); err != nil {
return fmt.Errorf("invalid common node config JSON: %w", err)
}
// blockchain node config
if app.LuxdNodeConfigExists(blockchainName) {
blockchainNodeConfig, err := utils.ReadJSON(app.GetLuxdNodeConfigPath(blockchainName))
if err != nil {
return err
}
for k, v := range blockchainNodeConfig {
nodeConfig[k] = v
}
}
return TmpNetUpdateBlockchainConfig(
app.Log,
networkDir,
subnetID,
blockchainID,
vmID,
vmBinaryPath,
blockchainConfig,
perNodeBlockchainConfig,
blockchainUpgrades,
subnetConfig,
nodeConfig,
)
}
// Tracks the given [blockchainName] at network given on [networkDir]
// After P-Chain is bootstrapped, set alias [blockchainName]->blockchainID
// for the network, and persists RPC into sidecar
// Use both for local networks and local clusters
func TrackSubnet(
app *application.Lux,
printFunc func(msg string, args ...interface{}),
blockchainName string,
networkDir string,
wallet *primary.Wallet,
) error {
if err := UpdateBlockchainConfig(
app,
networkDir,
blockchainName,
); err != nil {
return err
}
networkModel, err := GetNetworkModel(networkDir)
if err != nil {
return err
}
sc, err := app.LoadSidecar(blockchainName)
if err != nil {
return err
}
if sc.Networks[networkModel.Name()].BlockchainID == ids.Empty {
return fmt.Errorf("blockchain %s has not been deployed to %s", blockchainName, networkModel.Name())
}
blockchainID := sc.Networks[networkModel.Name()].BlockchainID
subnetID := sc.Networks[networkModel.Name()].SubnetID
ctx, cancel := networkModel.BootstrappingContext()
defer cancel()
if err := TmpNetTrackSubnet(
ctx,
app.Log,
printFunc,
networkDir,
sc.Sovereign,
blockchainID,
subnetID,
wallet,
); err != nil {
if errors.Is(err, context.DeadlineExceeded) {
printFunc("")
printFunc("A context timeout has occurred while trying to bootstrap the blockchain.")
printFunc("")
logPaths, _ := GetTmpNetAvailableLogs(networkDir, blockchainID, false)
if len(logPaths) != 0 {
printFunc("Please check this log files for more information on the error cause:")
for _, logPath := range logPaths {
printFunc(" " + logPath)
}
printFunc("")
}
}
return err
}
ux.Logger.GreenCheckmarkToUser("%s successfully tracking %s", networkModel.Name(), blockchainName)
if networkModel.Kind == models.Local {
if err := TmpNetSetDefaultAliases(ctx, networkDir); err != nil {
return err
}
}
nodeURIs, err := GetTmpNetNodeURIsWithFix(networkDir)
if err != nil {
return err
}
_, err = app.AddDefaultBlockchainRPCsToSidecar(
blockchainName,
networkModel,
nodeURIs,
)
return err
}
// Returns the network model for the network at [networkDir]
func GetNetworkModel(
networkDir string,
) (models.Network, error) {
network, err := GetTmpNetNetwork(networkDir)
if err != nil {
return models.UndefinedNetwork, err
}
networkID, err := GetTmpNetNetworkID(network)
if err != nil {
return models.UndefinedNetwork, err
}
return models.NetworkFromNetworkID(networkID), nil
}