Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate local devnet #2254

Merged
merged 7 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 108 additions & 42 deletions cmd/blockchaincmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
"encoding/json"
"errors"
"fmt"
"github.com/ava-labs/avalanchego/api/info"
"os"
"path/filepath"
"strings"
"time"

"github.com/ava-labs/avalanchego/api/info"
"github.com/ava-labs/avalanche-cli/pkg/node"
"github.com/ava-labs/avalanche-cli/pkg/evm"

"github.com/ava-labs/avalanche-cli/pkg/node"
"github.com/ava-labs/avalanchego/vms/platformvm/warp/message"
"github.com/ethereum/go-ethereum/common"

Expand Down Expand Up @@ -51,6 +52,7 @@
var deploySupportedNetworkOptions = []networkoptions.NetworkOption{
networkoptions.Local,
networkoptions.Devnet,
networkoptions.EtnaDevnet,
networkoptions.Fuji,
networkoptions.Mainnet,
}
Expand All @@ -64,6 +66,8 @@
userProvidedAvagoVersion string
outputTxPath string
useLedger bool
useLocalMachine bool
localMachineCluster string
useEwoq bool
ledgerAddresses []string
sovereign bool
Expand Down Expand Up @@ -131,7 +135,9 @@
cmd.Flags().StringVar(&icmSpec.RegistryBydecodePath, "teleporter-registry-bytecode-path", "", "path to an interchain messenger registry bytecode file")
cmd.Flags().StringVar(&bootstrapValidatorsJSONFilePath, "bootstrap-filepath", "", "JSON file path that provides details about bootstrap validators, leave Node-ID and BLS values empty if using --generate-node-id=true")
cmd.Flags().BoolVar(&generateNodeID, "generate-node-id", false, "whether to create new node id for bootstrap validators (Node-ID and BLS values in bootstrap JSON file will be overridden if --bootstrap-filepath flag is used)")
cmd.Flags().StringSliceVar(&bootstrapEndpoints, "bootstrap-endpoints", nil, "take validator node info from the given endpoints")
cmd.Flags().StringSliceVar(&bootstrapEndpoints, "bootstrap-enu dpoints", nil, "take validator node info from the given endpoints")
cmd.Flags().BoolVar(&useLocalMachine, "use-local-machine", false, "use local machine as a blockchain validator")
sukantoraymond marked this conversation as resolved.
Show resolved Hide resolved
cmd.Flags().StringVar(&localMachineCluster, "local-machine-cluster", "", "existing local machine to be used as a blockchain validator")
return cmd
}

Expand Down Expand Up @@ -466,37 +472,85 @@
return PrintSubnetInfo(blockchainName, true)
}

if len(bootstrapEndpoints) > 0 {
var changeAddr string
for _, endpoint := range bootstrapEndpoints {
infoClient := info.NewClient(endpoint)
ctx, cancel := utils.GetAPILargeContext()
defer cancel()
nodeID, proofOfPossession, err := infoClient.GetNodeID(ctx)
if sidecar.Sovereign {
if !useLocalMachine {
ux.Logger.PrintToUser("You can use your local machine as a bootstrap validator on the blockchain")
ux.Logger.PrintToUser("This means that you don't have to to set up a remote server on a cloud service (e.g. AWS / GCP) to be a validator on the blockchain.")

useLocalMachine, err = app.Prompt.CaptureYesNo("Do you want to use your local machine as a bootstrap validator?")
if err != nil {
return err
}
publicKey = "0x" + hex.EncodeToString(proofOfPossession.PublicKey[:])
pop = "0x" + hex.EncodeToString(proofOfPossession.ProofOfPossession[:])
changeAddr, err = getKeyForChangeOwner(nodeID.String(), changeAddr, network)
if err != nil {
}
if useLocalMachine {
sukantoraymond marked this conversation as resolved.
Show resolved Hide resolved
// stop any local avalanche go process running before we start local node
_ = node.StopLocalNode(app)
clusterName := fmt.Sprintf("%s-local-node", blockchainName)
if localMachineCluster != "" {
// don't destroy cluster if local cluster name is provided
clusterName = localMachineCluster
} else {

Check failure on line 492 in cmd/blockchaincmd/deploy.go

View workflow job for this annotation

GitHub Actions / Lint

elseif: can replace 'else {if cond {}}' with 'else if cond {}' (gocritic)
// destroy any cluster with same name before we start local node
// we don't want to reuse snapshots from previous sessions
if utils.DirectoryExists(app.GetLocalDir(clusterName)) {
_ = node.DestroyLocalNode(app, clusterName)
}
}
// TODO: replace bootstrapEndpoints with dynamic port number
bootstrapEndpoints = []string{"http://127.0.0.1:9650"}
anrSettings := node.ANRSettings{}
avagoVersionSettings := node.AvalancheGoVersionSettings{}
useEtnaDevnet := false
if network.Kind == models.EtnaDevnet {
useEtnaDevnet = true
}
if avagoBinaryPath == "" {
ux.Logger.PrintToUser("Local build of Avalanche Go is required to create an Avalanche node using local machine")
ux.Logger.PrintToUser("Please download Avalanche Go repo at https://github.com/ava-labs/avalanchego and build from source through ./scripts/build.sh")
ux.Logger.PrintToUser("Please provide the full path to Avalanche Go binary in the build directory (e.g, xxx/build/avalanchego)")
avagoBinaryPath, err = app.Prompt.CaptureString("Path to Avalanche Go build")
if err != nil {
return err
}
}
network = models.NewNetworkFromCluster(network, clusterName)
// anrSettings, avagoVersionSettings, globalNetworkFlags are empty
if err = node.StartLocalNode(app, clusterName, useEtnaDevnet, avagoBinaryPath, anrSettings, avagoVersionSettings, globalNetworkFlags, nil); err != nil {
return err
}
bootstrapValidators = append(bootstrapValidators, models.SubnetValidator{
NodeID: nodeID.String(),
Weight: constants.BootstrapValidatorWeight,
Balance: constants.BootstrapValidatorBalance,
BLSPublicKey: publicKey,
BLSProofOfPossession: pop,
ChangeOwnerAddr: changeAddr,
})
}
}

if sidecar.Sovereign && len(bootstrapValidators) == 0 {
bootstrapValidators, err = promptBootstrapValidators(network)
if err != nil {
return err
if len(bootstrapEndpoints) > 0 {
var changeAddr string
for _, endpoint := range bootstrapEndpoints {
infoClient := info.NewClient(endpoint)
ctx, cancel := utils.GetAPILargeContext()
defer cancel()
nodeID, proofOfPossession, err := infoClient.GetNodeID(ctx)
if err != nil {
return err
}
publicKey = "0x" + hex.EncodeToString(proofOfPossession.PublicKey[:])
pop = "0x" + hex.EncodeToString(proofOfPossession.ProofOfPossession[:])
changeAddr, err = getKeyForChangeOwner(nodeID.String(), changeAddr, network)
if err != nil {
return err
}
bootstrapValidators = append(bootstrapValidators, models.SubnetValidator{
NodeID: nodeID.String(),
Weight: constants.BootstrapValidatorWeight,
Balance: constants.BootstrapValidatorBalance,
BLSPublicKey: publicKey,
BLSProofOfPossession: pop,
ChangeOwnerAddr: changeAddr,
})
}
}
if len(bootstrapValidators) == 0 {
bootstrapValidators, err = promptBootstrapValidators(network)
if err != nil {
return err
}
}
}

Expand Down Expand Up @@ -728,19 +782,27 @@
}

if !generateNodeID {
clusterName, err := node.GetClusterNameFromList(app)
if err != nil {
return err
clusterName := network.ClusterName
if clusterName == "" {
clusterName, err = node.GetClusterNameFromList(app)
if err != nil {
return err
}
}

if err = node.SyncSubnet(app, clusterName, blockchainName, true, nil); err != nil {
return err
}
if !useLocalMachine {
if err = node.SyncSubnet(app, clusterName, blockchainName, true, nil); err != nil {
return err
}

if err := node.WaitForHealthyCluster(app, clusterName, node.HealthCheckTimeout, node.HealthCheckPoolTime); err != nil {
return err
if err := node.WaitForHealthyCluster(app, clusterName, node.HealthCheckTimeout, node.HealthCheckPoolTime); err != nil {
return err
}
} else {
if err := node.TrackSubnetWithLocalMachine(app, clusterName, blockchainName); err != nil {
return err
}
}

chainSpec := contract.ChainSpec{
BlockchainName: blockchainName,
}
Expand All @@ -762,25 +824,29 @@
if err != nil {
return err
}
aggregatorExtraPeerEndpoints, err := GetAggregatorExtraPeerEndpoints(network)
client, err := evm.GetClient(rpcURL)
if err != nil {
return err
}
evm.WaitForChainID(client)
sukantoraymond marked this conversation as resolved.
Show resolved Hide resolved
privateAggregatorEndpoints, err := GetAggregatorExtraPeerEndpoints(network)
if err != nil {
return err
}
ux.Logger.PrintToUser("Initializing Proof of Authority Validator Manager contract on blockchain %s ...", blockchainName)
if err := validatormanager.SetupPoA(
app,
network,
rpcURL,
contract.ChainSpec{
BlockchainName: blockchainName,
},
chainSpec,
genesisPrivateKey,
common.HexToAddress(sidecar.PoAValidatorManagerOwner),
avaGoBootstrapValidators,
aggregatorExtraPeerEndpoints,
privateAggregatorEndpoints,
); err != nil {
return err
}
ux.Logger.GreenCheckmarkToUser("L1 is successfully converted to sovereign blockchain")
ux.Logger.GreenCheckmarkToUser("Proof of Authority Validator Manager contract successfully initialized on blockchain %s", blockchainName)
} else {
ux.Logger.GreenCheckmarkToUser("Generated Node ID and BLS info for bootstrap validator(s)")
ux.Logger.PrintToUser("To convert L1 to sovereign blockchain, create the corresponding Avalanche node(s) with the provided Node ID and BLS Info")
Expand Down
108 changes: 8 additions & 100 deletions cmd/nodecmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ import (

"github.com/ava-labs/avalanche-cli/pkg/metrics"

"github.com/ava-labs/avalanche-cli/cmd/blockchaincmd"
"github.com/ava-labs/avalanche-cli/cmd/flags"
"github.com/ava-labs/avalanche-cli/pkg/ansible"
"github.com/ava-labs/avalanche-cli/pkg/binutils"
"github.com/ava-labs/avalanche-cli/pkg/cobrautils"
"github.com/ava-labs/avalanche-cli/pkg/constants"
"github.com/ava-labs/avalanche-cli/pkg/models"
Expand Down Expand Up @@ -267,7 +265,13 @@ func createNodes(cmd *cobra.Command, args []string) error {
}
network = models.NewNetworkFromCluster(network, clusterName)
globalNetworkFlags.UseDevnet = network.Kind == models.Devnet // set globalNetworkFlags.UseDevnet to true if network is devnet for further use
avalancheGoVersion, err := getAvalancheGoVersion()
avaGoVersionSetting := node.AvalancheGoVersionSettings{
UseAvalanchegoVersionFromSubnet: useAvalanchegoVersionFromSubnet,
UseLatestAvalanchegoReleaseVersion: useLatestAvalanchegoReleaseVersion,
UseLatestAvalanchegoPreReleaseVersion: useLatestAvalanchegoPreReleaseVersion,
UseCustomAvalanchegoVersion: useCustomAvalanchegoVersion,
}
avalancheGoVersion, err := node.GetAvalancheGoVersion(app, avaGoVersionSetting)
if err != nil {
return err
}
Expand Down Expand Up @@ -898,7 +902,7 @@ func addNodeToClustersConfig(network models.Network, nodeID, clusterName string,
}
clusterConfig := clustersConfig.Clusters[clusterName]
// if supplied network in argument is empty, don't change current cluster network in cluster_config.json
if !network.IsUndefined() {
if network != models.UndefinedNetwork {
clusterConfig.Network = network
}
clusterConfig.HTTPAccess = constants.HTTPAccess(publicHTTPPortAccess)
Expand Down Expand Up @@ -985,57 +989,6 @@ func provideStakingCertAndKey(host *models.Host) error {
return ssh.RunSSHUploadStakingFiles(host, keyPath)
}

// getAvalancheGoVersion asks users whether they want to install the newest Avalanche Go version
// or if they want to use the newest Avalanche Go Version that is still compatible with Subnet EVM
// version of their choice
func getAvalancheGoVersion() (string, error) {
// skip this logic if custom-avalanchego-version flag is set
if useCustomAvalanchegoVersion != "" {
return useCustomAvalanchegoVersion, nil
}
latestReleaseVersion, err := app.Downloader.GetLatestReleaseVersion(binutils.GetGithubLatestReleaseURL(
constants.AvaLabsOrg,
constants.AvalancheGoRepoName,
))
if err != nil {
return "", err
}
latestPreReleaseVersion, err := app.Downloader.GetLatestPreReleaseVersion(
constants.AvaLabsOrg,
constants.AvalancheGoRepoName,
)
if err != nil {
return "", err
}

if !useLatestAvalanchegoReleaseVersion && !useLatestAvalanchegoPreReleaseVersion && useCustomAvalanchegoVersion == "" && useAvalanchegoVersionFromSubnet == "" {
err := promptAvalancheGoVersionChoice(latestReleaseVersion, latestPreReleaseVersion)
if err != nil {
return "", err
}
}

var version string
switch {
case useLatestAvalanchegoReleaseVersion:
version = latestReleaseVersion
case useLatestAvalanchegoPreReleaseVersion:
version = latestPreReleaseVersion
case useCustomAvalanchegoVersion != "":
version = useCustomAvalanchegoVersion
case useAvalanchegoVersionFromSubnet != "":
sc, err := app.LoadSidecar(useAvalanchegoVersionFromSubnet)
if err != nil {
return "", err
}
version, err = GetLatestAvagoVersionForRPC(sc.RPCVersion, latestPreReleaseVersion)
if err != nil {
return "", err
}
}
return version, nil
}

func GetLatestAvagoVersionForRPC(configuredRPCVersion int, latestPreReleaseVersion string) (string, error) {
desiredAvagoVersion, err := vm.GetLatestAvalancheGoByProtocolVersion(
app, configuredRPCVersion, constants.AvalancheGoCompatibilityURL)
Expand All @@ -1049,51 +1002,6 @@ func GetLatestAvagoVersionForRPC(configuredRPCVersion int, latestPreReleaseVersi
return desiredAvagoVersion, nil
}

// promptAvalancheGoVersionChoice sets flags for either using the latest Avalanche Go
// version or using the latest Avalanche Go version that is still compatible with the subnet that user
// wants the cloud server to track
func promptAvalancheGoVersionChoice(latestReleaseVersion string, latestPreReleaseVersion string) error {
latestReleaseVersionOption := "Use latest Avalanche Go Release Version" + versionComments[latestReleaseVersion]
latestPreReleaseVersionOption := "Use latest Avalanche Go Pre-release Version" + versionComments[latestPreReleaseVersion]
subnetBasedVersionOption := "Use the deployed Subnet's VM version that the node will be validating"
customOption := "Custom"

txt := "What version of Avalanche Go would you like to install in the node?"
versionOptions := []string{latestReleaseVersionOption, subnetBasedVersionOption, customOption}
if latestPreReleaseVersion != latestReleaseVersion {
versionOptions = []string{latestPreReleaseVersionOption, latestReleaseVersionOption, subnetBasedVersionOption, customOption}
}
versionOption, err := app.Prompt.CaptureList(txt, versionOptions)
if err != nil {
return err
}

switch versionOption {
case latestReleaseVersionOption:
useLatestAvalanchegoReleaseVersion = true
case latestPreReleaseVersionOption:
useLatestAvalanchegoPreReleaseVersion = true
case customOption:
useCustomAvalanchegoVersion, err = app.Prompt.CaptureVersion("Which version of AvalancheGo would you like to install? (Use format v1.10.13)")
if err != nil {
return err
}
default:
for {
useAvalanchegoVersionFromSubnet, err = app.Prompt.CaptureString("Which Subnet would you like to use to choose the avalanche go version?")
if err != nil {
return err
}
_, err = blockchaincmd.ValidateSubnetNameAndGetChains([]string{useAvalanchegoVersionFromSubnet})
if err == nil {
break
}
ux.Logger.PrintToUser(fmt.Sprintf("no subnet named %s found", useAvalanchegoVersionFromSubnet))
}
}
return nil
}

func setCloudService() (string, error) {
if utils.IsE2E() {
if !utils.E2EDocker() {
Expand Down
Loading
Loading