-
Notifications
You must be signed in to change notification settings - Fork 67
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 machine into subnet deploy #2235
Changes from 8 commits
7175e30
151e1a9
32ef65c
0e7067c
23a76bc
8b7f331
6614449
6217d99
54479df
3dfad06
084018f
50986b7
2c56e09
84e8ab5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,8 @@ | |
"strings" | ||
"time" | ||
|
||
"github.com/ava-labs/avalanche-cli/pkg/node" | ||
|
||
"github.com/ava-labs/avalanchego/api/info" | ||
"github.com/ava-labs/avalanchego/vms/platformvm/warp/message" | ||
"github.com/ethereum/go-ethereum/common" | ||
|
@@ -464,6 +466,18 @@ | |
return PrintSubnetInfo(blockchainName, true) | ||
} | ||
|
||
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.") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably we want to explain more here? like this is temporary bootstrap validator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its not temporary if user wants to leave it the node indefinitely as validator |
||
|
||
useLocalMachine, err := app.Prompt.CaptureYesNo("Do you want to use your local machine as a bootstrap validator?") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. flag to avoid question for this and just proceed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. addressed |
||
if err != nil { | ||
return err | ||
} | ||
|
||
if useLocalMachine { | ||
bootstrapEndpoints = []string{"http://127.0.0.1:9650"} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this might be tricky to assume this endpoint as port can be not 9650 but rather dynamic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe we should ask user for the endpoint and not yes/no for local machine. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see now. After the previous question, a Start should be made and from that, the endpoint There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably for another PR. Make an issue for this and keep current static assignment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
|
||
if len(bootstrapEndpoints) > 0 { | ||
var changeAddr string | ||
for _, endpoint := range bootstrapEndpoints { | ||
|
@@ -663,7 +677,7 @@ | |
} | ||
deployer.CleanCacheWallet() | ||
managerAddress := common.HexToAddress(validatormanager.ValidatorContractAddress) | ||
isFullySigned, ConvertL1TxID, tx, remainingSubnetAuthKeys, err := deployer.ConvertL1( | ||
controlKeys, | ||
subnetAuthKeys, | ||
subnetID, | ||
|
@@ -725,65 +739,81 @@ | |
return err | ||
} | ||
|
||
if false { | ||
chainSpec := contract.ChainSpec{ | ||
BlockchainName: blockchainName, | ||
} | ||
genesisAddress, genesisPrivateKey, err := contract.GetEVMSubnetPrefundedKey( | ||
app, | ||
network, | ||
chainSpec, | ||
) | ||
if err != nil { | ||
clusterName, err := node.GetClusterNameFromList(app) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The cluster name to be taken from the input network itself IMO There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. which should be a cluster There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. models.Networks has ClusterName There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. better to do it when integrating local node start |
||
if err != nil { | ||
return err | ||
} | ||
|
||
if !useLocalMachine { | ||
if err = node.SyncSubnet(app, clusterName, blockchainName, true, nil); err != nil { | ||
return err | ||
} | ||
privateKey, err := privateKeyFlags.GetPrivateKey(app, genesisPrivateKey) | ||
if err != nil { | ||
if err := node.WaitForHealthyCluster(app, clusterName, node.HealthCheckTimeout, node.HealthCheckPoolTime); err != nil { | ||
return err | ||
} | ||
if privateKey == "" { | ||
privateKey, err = prompts.PromptPrivateKey( | ||
app.Prompt, | ||
"Which key to you want to use to pay for initializing Validator Manager contract? (Uses Blockchain gas token)", | ||
app.GetKeyDir(), | ||
app.GetKey, | ||
genesisAddress, | ||
genesisPrivateKey, | ||
) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
rpcURL, _, err := contract.GetBlockchainEndpoints( | ||
app, | ||
network, | ||
chainSpec, | ||
true, | ||
false, | ||
) | ||
if err != nil { | ||
} else { | ||
if err := node.TrackSubnetWithLocalMachine(app, clusterName, blockchainName); err != nil { | ||
return err | ||
} | ||
aggregatorExtraPeerEndpoints, err := GetAggregatorExtraPeerEndpoints(network) | ||
} | ||
|
||
chainSpec := contract.ChainSpec{ | ||
BlockchainName: blockchainName, | ||
} | ||
genesisAddress, genesisPrivateKey, err := contract.GetEVMSubnetPrefundedKey( | ||
app, | ||
network, | ||
chainSpec, | ||
) | ||
if err != nil { | ||
return err | ||
} | ||
privateKey, err := privateKeyFlags.GetPrivateKey(app, genesisPrivateKey) | ||
if err != nil { | ||
return err | ||
} | ||
if privateKey == "" { | ||
privateKey, err = prompts.PromptPrivateKey( | ||
app.Prompt, | ||
"Which key to you want to use to pay for initializing Validator Manager contract? (Uses Blockchain gas token)", | ||
app.GetKeyDir(), | ||
app.GetKey, | ||
genesisAddress, | ||
genesisPrivateKey, | ||
) | ||
if err != nil { | ||
return err | ||
} | ||
if err := validatormanager.SetupPoA( | ||
app, | ||
network, | ||
rpcURL, | ||
contract.ChainSpec{ | ||
BlockchainName: blockchainName, | ||
}, | ||
privateKey, | ||
common.HexToAddress(sidecar.PoAValidatorManagerOwner), | ||
avaGoBootstrapValidators, | ||
aggregatorExtraPeerEndpoints, | ||
); err != nil { | ||
return err | ||
} | ||
ux.Logger.GreenCheckmarkToUser("Subnet is successfully converted into Subnet Only Validator") | ||
} | ||
rpcURL, _, err := contract.GetBlockchainEndpoints( | ||
app, | ||
network, | ||
chainSpec, | ||
true, | ||
false, | ||
) | ||
if err != nil { | ||
return err | ||
} | ||
aggregatorExtraPeerEndpoints, err := GetAggregatorExtraPeerEndpoints(network) | ||
if err != nil { | ||
return err | ||
} | ||
if err := validatormanager.SetupPoA( | ||
app, | ||
network, | ||
rpcURL, | ||
contract.ChainSpec{ | ||
BlockchainName: blockchainName, | ||
}, | ||
privateKey, | ||
common.HexToAddress(sidecar.PoAValidatorManagerOwner), | ||
avaGoBootstrapValidators, | ||
aggregatorExtraPeerEndpoints, | ||
); err != nil { | ||
return err | ||
} | ||
ux.Logger.GreenCheckmarkToUser("Subnet is successfully converted into Subnet Only Validator") | ||
} | ||
|
||
flags := make(map[string]string) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,8 @@ | |
"os" | ||
"path/filepath" | ||
|
||
"github.com/ava-labs/avalanche-cli/pkg/node" | ||
|
||
"github.com/ava-labs/avalanche-cli/pkg/binutils" | ||
"github.com/ava-labs/avalanche-cli/pkg/cobrautils" | ||
"github.com/ava-labs/avalanche-cli/pkg/constants" | ||
|
@@ -17,10 +19,7 @@ | |
"github.com/ava-labs/avalanche-cli/pkg/utils" | ||
"github.com/ava-labs/avalanche-cli/pkg/ux" | ||
"github.com/ava-labs/avalanche-network-runner/client" | ||
anrutils "github.com/ava-labs/avalanche-network-runner/utils" | ||
"github.com/ava-labs/avalanchego/ids" | ||
"github.com/ava-labs/avalanchego/utils/logging" | ||
"github.com/ava-labs/avalanchego/utils/set" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
|
@@ -351,7 +350,9 @@ | |
spinner := spinSession.SpinToUser("Booting Network. Wait until healthy...") | ||
if _, err := cli.Start(ctx, avalancheGoBinPath, anrOpts...); err != nil { | ||
ux.SpinFailWithError(spinner, "", err) | ||
localDestroyNode(nil, []string{clusterName}) | ||
if destroyErr := localDestroyNode(nil, []string{clusterName}); destroyErr != nil { | ||
return fmt.Errorf("failed to start local avalanchego: %w, and failed to destroy the local node %s due to %w", err, clusterName, destroyErr) | ||
} | ||
return fmt.Errorf("failed to start local avalanchego: %w", err) | ||
} | ||
ux.SpinComplete(spinner) | ||
|
@@ -415,14 +416,17 @@ | |
func localDestroyNode(_ *cobra.Command, args []string) error { | ||
clusterName := args[0] | ||
|
||
localStopNode(nil, nil) | ||
if err := localStopNode(nil, nil); err != nil { | ||
return fmt.Errorf("failed to destroy local node: %w", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. node can be already stopped. for the moment on ignore the error or verify is the node is already stopped, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just need to make sure this passes lint. removed err There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. addressed |
||
|
||
} | ||
|
||
rootDir := app.GetLocalDir(clusterName) | ||
if err := os.RemoveAll(rootDir); err != nil { | ||
return err | ||
} | ||
|
||
if ok, err := checkClusterIsLocal(clusterName); err != nil || !ok { | ||
if ok, err := node.CheckClusterIsLocal(app, clusterName); err != nil || !ok { | ||
return fmt.Errorf("local cluster %q not found", clusterName) | ||
} | ||
|
||
|
@@ -452,107 +456,10 @@ | |
return app.WriteClustersConfigFile(&clustersConfig) | ||
} | ||
|
||
func checkClusterIsLocal(clusterName string) (bool, error) { | ||
clustersConfig, err := app.GetClustersConfig() | ||
if err != nil { | ||
return false, err | ||
} | ||
clusterConf, ok := clustersConfig.Clusters[clusterName] | ||
return ok && clusterConf.Local, nil | ||
} | ||
|
||
func localTrack(_ *cobra.Command, args []string) error { | ||
clusterName := args[0] | ||
blockchainName := args[1] | ||
if ok, err := checkClusterIsLocal(clusterName); err != nil || !ok { | ||
return fmt.Errorf("local node %q is not found", clusterName) | ||
} | ||
sc, err := app.LoadSidecar(blockchainName) | ||
if err != nil { | ||
return err | ||
} | ||
clustersConfig, err := app.LoadClustersConfig() | ||
if err != nil { | ||
return err | ||
} | ||
clusterConfig := clustersConfig.Clusters[clusterName] | ||
network := clusterConfig.Network | ||
if sc.Networks[network.Name()].BlockchainID == ids.Empty { | ||
return fmt.Errorf("blockchain %s has not been deployed to %s", blockchainName, network.Name()) | ||
} | ||
subnetID := sc.Networks[network.Name()].SubnetID | ||
blockchainID := sc.Networks[network.Name()].BlockchainID | ||
vmID, err := anrutils.VMID(blockchainName) | ||
if err != nil { | ||
return fmt.Errorf("failed to create VM ID from %s: %w", blockchainName, err) | ||
} | ||
var vmBin string | ||
switch sc.VM { | ||
case models.SubnetEvm: | ||
_, vmBin, err = binutils.SetupSubnetEVM(app, sc.VMVersion) | ||
if err != nil { | ||
return fmt.Errorf("failed to install subnet-evm: %w", err) | ||
} | ||
case models.CustomVM: | ||
vmBin = binutils.SetupCustomBin(app, blockchainName) | ||
default: | ||
return fmt.Errorf("unknown vm: %s", sc.VM) | ||
} | ||
rootDir := app.GetLocalDir(clusterName) | ||
pluginPath := filepath.Join(rootDir, "node1", "plugins", vmID.String()) | ||
if err := utils.FileCopy(vmBin, pluginPath); err != nil { | ||
return err | ||
} | ||
if err := os.Chmod(pluginPath, constants.DefaultPerms755); err != nil { | ||
return err | ||
} | ||
if app.ChainConfigExists(blockchainName) { | ||
inputChainConfigPath := app.GetChainConfigPath(blockchainName) | ||
outputChainConfigPath := filepath.Join(rootDir, "node1", "configs", "chains", blockchainID.String(), "config.json") | ||
if err := os.MkdirAll(filepath.Dir(outputChainConfigPath), 0o700); err != nil { | ||
return fmt.Errorf("could not create chain conf directory %s: %w", filepath.Dir(outputChainConfigPath), err) | ||
} | ||
if err := utils.FileCopy(inputChainConfigPath, outputChainConfigPath); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
cli, err := binutils.NewGRPCClientWithEndpoint( | ||
binutils.LocalClusterGRPCServerEndpoint, | ||
binutils.WithAvoidRPCVersionCheck(true), | ||
binutils.WithDialTimeout(constants.FastGRPCDialTimeout), | ||
) | ||
if err != nil { | ||
return err | ||
} | ||
ctx, cancel := utils.GetANRContext() | ||
defer cancel() | ||
status, err := cli.Status(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
publicEndpoints := []string{} | ||
for _, nodeInfo := range status.ClusterInfo.NodeInfos { | ||
if _, err := cli.RestartNode(ctx, nodeInfo.Name, client.WithWhitelistedSubnets(subnetID.String())); err != nil { | ||
return err | ||
} | ||
publicEndpoints = append(publicEndpoints, nodeInfo.Uri) | ||
} | ||
networkInfo := sc.Networks[network.Name()] | ||
rpcEndpoints := set.Of(networkInfo.RPCEndpoints...) | ||
wsEndpoints := set.Of(networkInfo.WSEndpoints...) | ||
for _, publicEndpoint := range publicEndpoints { | ||
rpcEndpoints.Add(getRPCEndpoint(publicEndpoint, networkInfo.BlockchainID.String())) | ||
wsEndpoints.Add(getWSEndpoint(publicEndpoint, networkInfo.BlockchainID.String())) | ||
} | ||
networkInfo.RPCEndpoints = rpcEndpoints.List() | ||
networkInfo.WSEndpoints = wsEndpoints.List() | ||
sc.Networks[clusterConfig.Network.Name()] = networkInfo | ||
if err := app.UpdateSidecar(&sc); err != nil { | ||
return err | ||
} | ||
ux.Logger.GreenCheckmarkToUser("%s successfully tracking %s", clusterName, blockchainName) | ||
return nil | ||
return node.TrackSubnetWithLocalMachine(app, clusterName, blockchainName) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure it is the moment to move this to node pgk. we keep a part of logic here and a part in node. |
||
} | ||
|
||
func notImplementedForLocal(what string) error { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also this to be guarded by a flag
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addressed