Skip to content

Commit

Permalink
Use local machine to join as validator on any L1 (#2548)
Browse files Browse the repository at this point in the history
* use local machine to join as validator

* fix lint

* update validate function

* local machine validate l1

* update command description

* lint

* lint

* address comments

* fix merge

* address comments

* enable more than 1 node in a cluster to validate

* address comments

* fix lint

* fix lint

---------

Signed-off-by: sukantoraymond <rsukanto@umich.edu>
  • Loading branch information
sukantoraymond authored and owenwahlgren committed Jan 23, 2025
1 parent 54813cd commit a6c81b8
Show file tree
Hide file tree
Showing 16 changed files with 663 additions and 245 deletions.
22 changes: 8 additions & 14 deletions cmd/blockchaincmd/add_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"strings"
"time"

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

"github.com/ava-labs/avalanchego/config"
"github.com/ava-labs/avalanchego/utils/units"

Expand All @@ -32,7 +34,6 @@ import (
avagoconstants "github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/avalanchego/utils/formatting/address"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/vms/platformvm"
warpMessage "github.com/ava-labs/avalanchego/vms/platformvm/warp/message"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -343,12 +344,12 @@ func CallAddValidator(
if err != nil {
return err
}
blsInfo, err := getBLSInfo(publicKey, pop)
blsInfo, err := blockchain.ConvertToBLSProofOfPossession(publicKey, pop)
if err != nil {
return fmt.Errorf("failure parsing BLS info: %w", err)
}

blockchainTimestamp, err := getBlockchainTimestamp(network)
blockchainTimestamp, err := blockchain.GetBlockchainTimestamp(network)
if err != nil {
return fmt.Errorf("failed to get blockchain timestamp: %w", err)
}
Expand Down Expand Up @@ -441,7 +442,7 @@ func CallAddValidator(
balance := uint64(balanceAVAX * float64(units.Avax))

if remainingBalanceOwnerAddr == "" {
remainingBalanceOwnerAddr, err = getKeyForChangeOwner(network)
remainingBalanceOwnerAddr, err = blockchain.GetKeyForChangeOwner(app, network)
if err != nil {
return err
}
Expand Down Expand Up @@ -479,12 +480,12 @@ func CallAddValidator(
Addresses: disableOwnerAddrID,
}

extraAggregatorPeers, err := GetAggregatorExtraPeers(clusterNameFlagValue, aggregatorExtraEndpoints)
extraAggregatorPeers, err := blockchain.GetAggregatorExtraPeers(app, clusterNameFlagValue, aggregatorExtraEndpoints)
if err != nil {
return err
}
aggregatorLogger, err := utils.NewLogger(
"signature-aggregator",
constants.SignatureAggregatorLogName,
aggregatorLogLevel,
constants.DefaultAggregatorLogLevel,
app.GetAggregatorLogDir(clusterNameFlagValue),
Expand Down Expand Up @@ -527,7 +528,7 @@ func CallAddValidator(
ux.Logger.PrintToUser(logging.LightBlue.Wrap("The Validation ID was already registered on the P-Chain. Proceeding to the next step"))
} else {
ux.Logger.PrintToUser("RegisterL1ValidatorTx ID: %s", txID)
if err := UpdatePChainHeight(
if err := blockchain.UpdatePChainHeight(
"Waiting for P-Chain to update validator information ...",
); err != nil {
return err
Expand Down Expand Up @@ -722,13 +723,6 @@ func PromptDuration(start time.Time, network models.Network, isPos bool) (time.D
}
}

func getBlockchainTimestamp(network models.Network) (time.Time, error) {
ctx, cancel := utils.GetAPIContext()
defer cancel()
platformCli := platformvm.NewClient(network.Endpoint)
return platformCli.GetTimestamp(ctx)
}

func getTimeParameters(network models.Network, nodeID ids.NodeID, isValidator bool) (time.Time, time.Duration, error) {
defaultStakingStartLeadTime := constants.StakingStartLeadTime
if network.Kind == models.Devnet {
Expand Down
116 changes: 9 additions & 107 deletions cmd/blockchaincmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"strings"
"time"

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

"github.com/ava-labs/avalanche-cli/cmd/interchaincmd/messengercmd"
"github.com/ava-labs/avalanche-cli/cmd/interchaincmd/relayercmd"
"github.com/ava-labs/avalanche-cli/cmd/networkcmd"
Expand All @@ -39,7 +41,6 @@ import (
"github.com/ava-labs/avalanchego/api/info"
"github.com/ava-labs/avalanchego/config"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/network/peer"
avagoutils "github.com/ava-labs/avalanchego/utils"
"github.com/ava-labs/avalanchego/utils/formatting/address"
"github.com/ava-labs/avalanchego/utils/logging"
Expand Down Expand Up @@ -205,7 +206,7 @@ so you can take your locally tested Blockchain and deploy it on Fuji or Mainnet.

cmd.Flags().Uint64Var(&poSMinimumStakeAmount, "pos-minimum-stake-amount", 1, "minimum stake amount")
cmd.Flags().Uint64Var(&poSMaximumStakeAmount, "pos-maximum-stake-amount", 1000, "maximum stake amount")
cmd.Flags().Uint64Var(&poSMinimumStakeDuration, "pos-minimum-stake-duration", 100, "minimum stake duration")
cmd.Flags().Uint64Var(&poSMinimumStakeDuration, "pos-minimum-stake-duration", constants.PoSL1MinimumStakeDurationSeconds, "minimum stake duration (in seconds)")
cmd.Flags().Uint16Var(&poSMinimumDelegationFee, "pos-minimum-delegation-fee", 1, "minimum delegation fee")
cmd.Flags().Uint8Var(&poSMaximumStakeMultiplier, "pos-maximum-stake-multiplier", 1, "maximum stake multiplier")
cmd.Flags().Uint64Var(&poSWeightToValueFactor, "pos-weight-to-value-factor", 1, "weight to value factor")
Expand Down Expand Up @@ -742,7 +743,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
switch {
case len(bootstrapEndpoints) > 0:
if changeOwnerAddress == "" {
changeOwnerAddress, err = getKeyForChangeOwner(network)
changeOwnerAddress, err = blockchain.GetKeyForChangeOwner(app, network)
if err != nil {
return err
}
Expand Down Expand Up @@ -1038,7 +1039,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
return err
}
evm.WaitForChainID(client)
extraAggregatorPeers, err := GetAggregatorExtraPeers(clusterName, aggregatorExtraEndpoints)
extraAggregatorPeers, err := blockchain.GetAggregatorExtraPeers(app, clusterName, aggregatorExtraEndpoints)
if err != nil {
return err
}
Expand Down Expand Up @@ -1067,7 +1068,7 @@ func deployBlockchain(cmd *cobra.Command, args []string) error {
BootstrapValidators: avaGoBootstrapValidators,
}
aggregatorLogger, err := utils.NewLogger(
"signature-aggregator",
constants.SignatureAggregatorLogName,
aggregatorLogLevel,
constants.DefaultAggregatorLogLevel,
app.GetAggregatorLogDir(clusterName),
Expand Down Expand Up @@ -1278,7 +1279,7 @@ func getClusterBootstrapValidators(
if err != nil {
return nil, fmt.Errorf("failed to parse nodeID: %w", err)
}
changeAddr, err = getKeyForChangeOwner(network)
changeAddr, err = blockchain.GetKeyForChangeOwner(app, network)
if err != nil {
return nil, err
}
Expand All @@ -1298,27 +1299,6 @@ func getClusterBootstrapValidators(
return subnetValidators, nil
}

func getBLSInfo(publicKey, proofOfPossesion string) (signer.ProofOfPossession, error) {
type jsonProofOfPossession struct {
PublicKey string
ProofOfPossession string
}
jsonPop := jsonProofOfPossession{
PublicKey: publicKey,
ProofOfPossession: proofOfPossesion,
}
popBytes, err := json.Marshal(jsonPop)
if err != nil {
return signer.ProofOfPossession{}, err
}
pop := &signer.ProofOfPossession{}
err = pop.UnmarshalJSON(popBytes)
if err != nil {
return signer.ProofOfPossession{}, err
}
return *pop, nil
}

// TODO: add deactivation owner?
func ConvertToAvalancheGoSubnetValidator(subnetValidators []models.SubnetValidator) ([]*txs.ConvertSubnetToL1Validator, error) {
bootstrapValidators := []*txs.ConvertSubnetToL1Validator{}
Expand All @@ -1327,7 +1307,7 @@ func ConvertToAvalancheGoSubnetValidator(subnetValidators []models.SubnetValidat
if err != nil {
return nil, err
}
blsInfo, err := getBLSInfo(validator.BLSPublicKey, validator.BLSProofOfPossession)
blsInfo, err := blockchain.ConvertToBLSProofOfPossession(validator.BLSPublicKey, validator.BLSProofOfPossession)
if err != nil {
return nil, fmt.Errorf("failure parsing BLS info: %w", err)
}
Expand Down Expand Up @@ -1504,32 +1484,8 @@ func LoadBootstrapValidator(filepath string) ([]models.SubnetValidator, error) {
return subnetValidators, nil
}

func UrisToPeers(uris []string) ([]info.Peer, error) {
peers := []info.Peer{}
ctx, cancel := utils.GetANRContext()
defer cancel()
for _, uri := range uris {
client := info.NewClient(uri)
nodeID, _, err := client.GetNodeID(ctx)
if err != nil {
return nil, err
}
ip, err := client.GetNodeIP(ctx)
if err != nil {
return nil, err
}
peers = append(peers, info.Peer{
Info: peer.Info{
ID: nodeID,
PublicIP: ip,
},
})
}
return peers, nil
}

func ConvertURIToPeers(uris []string) ([]info.Peer, error) {
aggregatorPeers, err := UrisToPeers(uris)
aggregatorPeers, err := blockchain.UrisToPeers(uris)
if err != nil {
return nil, err
}
Expand All @@ -1555,60 +1511,6 @@ func ConvertURIToPeers(uris []string) ([]info.Peer, error) {
return aggregatorPeers, nil
}

func GetAggregatorExtraPeers(
clusterName string,
extraURIs []string,
) ([]info.Peer, error) {
uris, err := GetAggregatorNetworkUris(clusterName)
if err != nil {
return nil, err
}
uris = append(uris, extraURIs...)
urisSet := set.Of(uris...)
uris = urisSet.List()
return UrisToPeers(uris)
}

func GetAggregatorNetworkUris(clusterName string) ([]string, error) {
aggregatorExtraPeerEndpointsUris := []string{}
if clusterName != "" {
clustersConfig, err := app.LoadClustersConfig()
if err != nil {
return nil, err
}
clusterConfig := clustersConfig.Clusters[clusterName]
if clusterConfig.Local {
cli, err := binutils.NewGRPCClientWithEndpoint(
binutils.LocalClusterGRPCServerEndpoint,
binutils.WithAvoidRPCVersionCheck(true),
binutils.WithDialTimeout(constants.FastGRPCDialTimeout),
)
if err != nil {
return nil, err
}
ctx, cancel := utils.GetANRContext()
defer cancel()
status, err := cli.Status(ctx)
if err != nil {
return nil, err
}
for _, nodeInfo := range status.ClusterInfo.NodeInfos {
aggregatorExtraPeerEndpointsUris = append(aggregatorExtraPeerEndpointsUris, nodeInfo.Uri)
}
} else { // remote cluster case
hostIDs := utils.Filter(clusterConfig.GetCloudIDs(), clusterConfig.IsAvalancheGoHost)
for _, hostID := range hostIDs {
if nodeConfig, err := app.LoadClusterNodeConfig(hostID); err != nil {
return nil, err
} else {
aggregatorExtraPeerEndpointsUris = append(aggregatorExtraPeerEndpointsUris, fmt.Sprintf("http://%s:%d", nodeConfig.ElasticIP, constants.AvalancheGoAPIPort))
}
}
}
}
return aggregatorExtraPeerEndpointsUris, nil
}

func simulatedPublicNetwork() bool {
return os.Getenv(constants.SimulatePublicNetwork) != ""
}
17 changes: 0 additions & 17 deletions cmd/blockchaincmd/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package blockchaincmd

import (
"fmt"
"time"

"github.com/ava-labs/avalanche-cli/pkg/binutils"
"github.com/ava-labs/avalanche-cli/pkg/utils"
Expand All @@ -13,7 +12,6 @@ import (
"github.com/ava-labs/avalanche-cli/pkg/models"
"github.com/ava-labs/avalanche-cli/pkg/networkoptions"
"github.com/ava-labs/avalanche-cli/pkg/txutils"
"github.com/ava-labs/avalanche-cli/pkg/ux"
"github.com/ava-labs/avalanchego/ids"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -96,21 +94,6 @@ func UpdateKeychainWithSubnetControlKeys(
return nil
}

func UpdatePChainHeight(
title string,
) error {
_, err := ux.TimedProgressBar(
40*time.Second,
title,
0,
)
if err != nil {
return err
}
fmt.Println()
return nil
}

func getLocalBootstrapEndpoints() ([]string, error) {
ctx, cancel := utils.GetANRContext()
defer cancel()
Expand Down
2 changes: 1 addition & 1 deletion cmd/blockchaincmd/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var (
printManual bool
// if true, doesn't ask for overwriting the config file
forceWrite bool
// for permissionless subnet only: how muchnative token will be staked in the validator
// for permissionless subnet only: how much native token will be staked in the validator
stakeAmount uint64
)

Expand Down
4 changes: 3 additions & 1 deletion cmd/blockchaincmd/prompt_genesis_input.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package blockchaincmd
import (
"fmt"

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

"github.com/ava-labs/avalanche-cli/pkg/application"
"github.com/ava-labs/avalanche-cli/pkg/constants"
"github.com/ava-labs/avalanche-cli/pkg/models"
Expand Down Expand Up @@ -162,7 +164,7 @@ func promptBootstrapValidators(
generateNodeID = !setUpNodes
}
if changeOwnerAddress == "" {
changeOwnerAddress, err = getKeyForChangeOwner(network)
changeOwnerAddress, err = blockchain.GetKeyForChangeOwner(app, network)
if err != nil {
return nil, err
}
Expand Down
43 changes: 0 additions & 43 deletions cmd/blockchaincmd/prompt_owners.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,46 +289,3 @@ func getThreshold(maxLen int) (uint32, error) {
}
return uint32(intTh), err
}

func getKeyForChangeOwner(network models.Network) (string, error) {
changeAddrPrompt := "Which key would you like to set as change owner for leftover AVAX if the node is removed from validator set?"

const (
getFromStored = "Get address from an existing stored key (created from avalanche key create or avalanche key import)"
custom = "Custom"
)

listOptions := []string{getFromStored, custom}
listDecision, err := app.Prompt.CaptureList(changeAddrPrompt, listOptions)
if err != nil {
return "", err
}

var key string

switch listDecision {
case getFromStored:
key, err = prompts.CaptureKeyAddress(
app.Prompt,
"be set as a change owner for leftover AVAX",
app.GetKeyDir(),
app.GetKey,
network,
prompts.PChainFormat,
)
if err != nil {
return "", err
}
case custom:
addrPrompt := "Enter change address (P-chain format)"
changeAddr, err := app.Prompt.CaptureAddress(addrPrompt)
if err != nil {
return "", err
}
key = changeAddr.String()
}
if err != nil {
return "", err
}
return key, nil
}
Loading

0 comments on commit a6c81b8

Please sign in to comment.