From 748a9ed71662d0c4fcaa4de6ec99d4f60900fb53 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 11 Dec 2024 11:40:55 -0500 Subject: [PATCH 01/16] get balance --- cmd/validatorcmd/getBalance.go | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 cmd/validatorcmd/getBalance.go diff --git a/cmd/validatorcmd/getBalance.go b/cmd/validatorcmd/getBalance.go new file mode 100644 index 000000000..97ab60c0a --- /dev/null +++ b/cmd/validatorcmd/getBalance.go @@ -0,0 +1,38 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package validatorcmd + +import ( + "errors" + "github.com/ava-labs/avalanche-cli/pkg/application" + "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/spf13/cobra" +) + +var ( + ErrUserAbortedInstallation = errors.New("user canceled installation") + ErrNoVersion = errors.New("failed to find current version - did you install following official instructions?") + app *application.Avalanche + yes bool +) + +func NewGetBalanceCmd(injectedApp *application.Avalanche, version string) *cobra.Command { + app = injectedApp + cmd := &cobra.Command{ + Use: "getBalance", + Short: "Gets current balance of validator on P-Chain", + Long: `Validator's balance is used to pay for continuous fee to the P-Chain. +When this Balance reaches 0, the validator will be considered inactive and will no longer participate in validating the L1. + This command gets the remaining validator P-Chain balance`, + RunE: getBalance, + Args: cobrautils.ExactArgs(0), + Version: version, + } + + cmd.Flags().BoolVarP(&yes, "node-id", "c", false, "Assume yes for installation") + return cmd +} + +func getBalance(cmd *cobra.Command, _ []string) error { + return nil +} From 2fca6f4d809f6961b66f4977e5d089ed5efc2cdd Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Wed, 11 Dec 2024 13:28:38 -0500 Subject: [PATCH 02/16] getbalance --- cmd/root.go | 3 +++ cmd/validatorcmd/getBalance.go | 37 ++++++++++++++++++++-------------- cmd/validatorcmd/validator.go | 30 +++++++++++++++++++++++++++ pkg/txutils/info.go | 24 ++++++++++++++++++++++ 4 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 cmd/validatorcmd/validator.go diff --git a/cmd/root.go b/cmd/root.go index c6e5976e8..4433e0fc1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,6 +5,7 @@ package cmd import ( "errors" "fmt" + "github.com/ava-labs/avalanche-cli/cmd/validatorcmd" "os" "os/signal" "os/user" @@ -136,6 +137,8 @@ Deprecation notice: use 'avalanche blockchain'` // add contract command rootCmd.AddCommand(contractcmd.NewCmd(app)) + // add validator commmand + rootCmd.AddCommand(validatorcmd.NewCmd(app)) cobrautils.ConfigureRootCmd(rootCmd) diff --git a/cmd/validatorcmd/getBalance.go b/cmd/validatorcmd/getBalance.go index 97ab60c0a..cb3032e2f 100644 --- a/cmd/validatorcmd/getBalance.go +++ b/cmd/validatorcmd/getBalance.go @@ -3,36 +3,43 @@ package validatorcmd import ( - "errors" - "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/ava-labs/avalanche-cli/pkg/models" + "github.com/ava-labs/avalanche-cli/pkg/txutils" + "github.com/ava-labs/avalanchego/ids" "github.com/spf13/cobra" ) var ( - ErrUserAbortedInstallation = errors.New("user canceled installation") - ErrNoVersion = errors.New("failed to find current version - did you install following official instructions?") - app *application.Avalanche - yes bool + subnetID string + nodeID string ) -func NewGetBalanceCmd(injectedApp *application.Avalanche, version string) *cobra.Command { - app = injectedApp +func NewGetBalanceCmd() *cobra.Command { cmd := &cobra.Command{ Use: "getBalance", Short: "Gets current balance of validator on P-Chain", - Long: `Validator's balance is used to pay for continuous fee to the P-Chain. -When this Balance reaches 0, the validator will be considered inactive and will no longer participate in validating the L1. - This command gets the remaining validator P-Chain balance`, - RunE: getBalance, - Args: cobrautils.ExactArgs(0), - Version: version, + Long: `This command gets the remaining validator P-Chain balance that is available to pay +P-Chain continuous fee`, + RunE: getBalance, + Args: cobrautils.ExactArgs(0), } - cmd.Flags().BoolVarP(&yes, "node-id", "c", false, "Assume yes for installation") + cmd.Flags().StringVar(&subnetID, "subnet-id", "", "subnetID of L1 that the node is validating") + cmd.Flags().StringVar(&nodeID, "node-id", "", "Node-ID of validator") return cmd } func getBalance(cmd *cobra.Command, _ []string) error { + subnetID, err := ids.FromString("d") + if err != nil { + return err + } + index := uint32(0) + network := models.NewFujiNetwork() + err := txutils.GetBalance(network, subnetID, index) + if err != nil { + return err + } return nil } diff --git a/cmd/validatorcmd/validator.go b/cmd/validatorcmd/validator.go new file mode 100644 index 000000000..f16fa6c7b --- /dev/null +++ b/cmd/validatorcmd/validator.go @@ -0,0 +1,30 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package validatorcmd + +import ( + "github.com/ava-labs/avalanche-cli/pkg/application" + "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/spf13/cobra" +) + +var app *application.Avalanche + +// avalanche validator +func NewCmd(injectedApp *application.Avalanche) *cobra.Command { + cmd := &cobra.Command{ + Use: "validator", + Short: "Manage P-Chain validator balance", + Long: `The validator command suite provides a collection of tools for managing validator +balance on P-Chain. + +Validator's balance is used to pay for continuous fee to the P-Chain. When this Balance reaches 0, +the validator will be considered inactive and will no longer participate in validating the L1`, + RunE: cobrautils.CommandSuiteUsage, + } + app = injectedApp + // validator getBalance + cmd.AddCommand(NewGetBalanceCmd()) + + return cmd +} diff --git a/pkg/txutils/info.go b/pkg/txutils/info.go index 30bdae4da..d4d980ae6 100644 --- a/pkg/txutils/info.go +++ b/pkg/txutils/info.go @@ -111,3 +111,27 @@ func GetOwners(network models.Network, subnetID ids.ID) (bool, []string, uint32, } return isPermissioned, controlKeysStrs, threshold, nil } + +func GetBalance(network models.Network, subnetID ids.ID, index uint32) error { + pClient := platformvm.NewClient(network.Endpoint) + ctx := context.Background() + validationID := subnetID.Append(index) + validatorResponse, _, err := pClient.GetL1Validator(ctx, validationID) + if err != nil { + return err + } + fmt.Printf("validatorResponse %s \n", validatorResponse) + //controlKeys := subnetResponse.ControlKeys + //threshold := subnetResponse.Threshold + //isPermissioned := subnetResponse.IsPermissioned + //hrp := key.GetHRP(network.ID) + //controlKeysStrs := []string{} + //for _, addr := range controlKeys { + // addrStr, err := address.Format("P", hrp, addr[:]) + // if err != nil { + // return false, nil, 0, err + // } + // controlKeysStrs = append(controlKeysStrs, addrStr) + //} + return nil +} From e18696cea83e4c83557437e85f63ada579f15811 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 12 Dec 2024 10:27:20 -0500 Subject: [PATCH 03/16] get balance --- cmd/validatorcmd/getBalance.go | 90 +++++++++++++++++++++++++++++++--- pkg/txutils/info.go | 26 ++++------ 2 files changed, 91 insertions(+), 25 deletions(-) diff --git a/cmd/validatorcmd/getBalance.go b/cmd/validatorcmd/getBalance.go index cb3032e2f..d0fcd31df 100644 --- a/cmd/validatorcmd/getBalance.go +++ b/cmd/validatorcmd/getBalance.go @@ -3,18 +3,32 @@ package validatorcmd import ( + "fmt" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" - "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/ava-labs/avalanchego/utils/units" "github.com/spf13/cobra" ) +var globalNetworkFlags networkoptions.NetworkFlags + var ( - subnetID string - nodeID string + l1 string + subnetID string + validationIDStr string ) +var getBalanceSupportedNetworkOptions = []networkoptions.NetworkOption{ + networkoptions.Local, + networkoptions.Devnet, + networkoptions.EtnaDevnet, + networkoptions.Fuji, + networkoptions.Mainnet, +} + func NewGetBalanceCmd() *cobra.Command { cmd := &cobra.Command{ Use: "getBalance", @@ -25,21 +39,81 @@ P-Chain continuous fee`, Args: cobrautils.ExactArgs(0), } + networkoptions.AddNetworkFlagsToCmd(cmd, &globalNetworkFlags, true, getBalanceSupportedNetworkOptions) + cmd.Flags().StringVar(&l1, "l1", "", "name of L1 (to get balance of bootstrap validators only)") cmd.Flags().StringVar(&subnetID, "subnet-id", "", "subnetID of L1 that the node is validating") - cmd.Flags().StringVar(&nodeID, "node-id", "", "Node-ID of validator") + cmd.Flags().StringVar(&validationIDStr, "validation-id", "", "validationIDStr of the validator") return cmd } func getBalance(cmd *cobra.Command, _ []string) error { - subnetID, err := ids.FromString("d") + network, err := networkoptions.GetNetworkFromCmdLineFlags( + app, + "", + globalNetworkFlags, + true, + false, + getBalanceSupportedNetworkOptions, + "", + ) if err != nil { return err } - index := uint32(0) - network := models.NewFujiNetwork() - err := txutils.GetBalance(network, subnetID, index) + + isBootstrapValidator, err := app.Prompt.CaptureYesNo("Is the validator a bootstrap validator?") if err != nil { return err } + var balance uint64 + if validationIDStr != "" { + validationID, err := ids.FromString(validationIDStr) + balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) + if err != nil { + return err + } + } + + if isBootstrapValidator { + if l1 == "" { + return fmt.Errorf("--l1 flag is required to get bootstrap validator balance") + } + sc, err := app.LoadSidecar(l1) + if err != nil { + return fmt.Errorf("failed to load sidecar: %w", err) + } + if !sc.Sovereign { + return fmt.Errorf("avalance validator getBalance command is only applicable to sovereign L1s") + } + bootstrapValidators := sc.Networks[network.Name()].BootstrapValidators + if len(bootstrapValidators) == 0 { + return fmt.Errorf("this L1 does not have any bootstrap validators") + } + bootstrapValidatorsString := []string{} + bootstrapValidatorsToIndexMap := make(map[string]int) + for index, validator := range bootstrapValidators { + bootstrapValidatorsString = append(bootstrapValidatorsString, validator.NodeID) + bootstrapValidatorsToIndexMap[validator.NodeID] = index + } + chosenValidator, err := app.Prompt.CaptureList("Which bootstrap validator do you want to get balance of?", bootstrapValidatorsString) + if err != nil { + return err + } + validatorIndex := bootstrapValidatorsToIndexMap[chosenValidator] + balance, err = txutils.GetValidatorPChainBalanceBootstrapValidator(network, sc.Networks[network.Name()].SubnetID, uint32(validatorIndex)) + if err != nil { + return err + } + } else { + validationID, err := app.Prompt.CaptureID("What is the validator's validationID?") + if err != nil { + return err + } + balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) + if err != nil { + return err + } + } + ux.Logger.PrintToUser(" Validator Balance: %.5f", float64(balance)/float64(units.Avax)) + return nil } diff --git a/pkg/txutils/info.go b/pkg/txutils/info.go index d4d980ae6..8d89ca795 100644 --- a/pkg/txutils/info.go +++ b/pkg/txutils/info.go @@ -112,26 +112,18 @@ func GetOwners(network models.Network, subnetID ids.ID) (bool, []string, uint32, return isPermissioned, controlKeysStrs, threshold, nil } -func GetBalance(network models.Network, subnetID ids.ID, index uint32) error { +func GetValidatorPChainBalanceBootstrapValidator(network models.Network, subnetID ids.ID, index uint32) (uint64, error) { + validationID := subnetID.Append(index) + return GetValidatorPChainBalanceValidationID(network, validationID) +} + +func GetValidatorPChainBalanceValidationID(network models.Network, validationID ids.ID) (uint64, error) { pClient := platformvm.NewClient(network.Endpoint) ctx := context.Background() - validationID := subnetID.Append(index) + validationID, _ = ids.FromString("2vKCTXoueQ9SSWH7KmpMimbD6LQY1HmPuFDqKWJtAuCUjHkH23") validatorResponse, _, err := pClient.GetL1Validator(ctx, validationID) if err != nil { - return err + return 0, err } - fmt.Printf("validatorResponse %s \n", validatorResponse) - //controlKeys := subnetResponse.ControlKeys - //threshold := subnetResponse.Threshold - //isPermissioned := subnetResponse.IsPermissioned - //hrp := key.GetHRP(network.ID) - //controlKeysStrs := []string{} - //for _, addr := range controlKeys { - // addrStr, err := address.Format("P", hrp, addr[:]) - // if err != nil { - // return false, nil, 0, err - // } - // controlKeysStrs = append(controlKeysStrs, addrStr) - //} - return nil + return validatorResponse.Balance, nil } From 78f4c3c0928e5be30d0d79fb85be0c41a9305666 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 12 Dec 2024 11:58:44 -0500 Subject: [PATCH 04/16] lint --- cmd/root.go | 2 +- cmd/validatorcmd/getBalance.go | 8 ++++++-- pkg/txutils/info.go | 1 - 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 4433e0fc1..81dde9311 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -137,7 +137,7 @@ Deprecation notice: use 'avalanche blockchain'` // add contract command rootCmd.AddCommand(contractcmd.NewCmd(app)) - // add validator commmand + // add validator command rootCmd.AddCommand(validatorcmd.NewCmd(app)) cobrautils.ConfigureRootCmd(rootCmd) diff --git a/cmd/validatorcmd/getBalance.go b/cmd/validatorcmd/getBalance.go index d0fcd31df..c013bd65f 100644 --- a/cmd/validatorcmd/getBalance.go +++ b/cmd/validatorcmd/getBalance.go @@ -4,6 +4,7 @@ package validatorcmd import ( "fmt" + "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" "github.com/ava-labs/avalanche-cli/pkg/txutils" @@ -46,7 +47,7 @@ P-Chain continuous fee`, return cmd } -func getBalance(cmd *cobra.Command, _ []string) error { +func getBalance(_ *cobra.Command, _ []string) error { network, err := networkoptions.GetNetworkFromCmdLineFlags( app, "", @@ -67,6 +68,9 @@ func getBalance(cmd *cobra.Command, _ []string) error { var balance uint64 if validationIDStr != "" { validationID, err := ids.FromString(validationIDStr) + if err != nil { + return err + } balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) if err != nil { return err @@ -82,7 +86,7 @@ func getBalance(cmd *cobra.Command, _ []string) error { return fmt.Errorf("failed to load sidecar: %w", err) } if !sc.Sovereign { - return fmt.Errorf("avalance validator getBalance command is only applicable to sovereign L1s") + return fmt.Errorf("avalanche validator getBalance command is only applicable to sovereign L1s") } bootstrapValidators := sc.Networks[network.Name()].BootstrapValidators if len(bootstrapValidators) == 0 { diff --git a/pkg/txutils/info.go b/pkg/txutils/info.go index 8d89ca795..c5a525201 100644 --- a/pkg/txutils/info.go +++ b/pkg/txutils/info.go @@ -120,7 +120,6 @@ func GetValidatorPChainBalanceBootstrapValidator(network models.Network, subnetI func GetValidatorPChainBalanceValidationID(network models.Network, validationID ids.ID) (uint64, error) { pClient := platformvm.NewClient(network.Endpoint) ctx := context.Background() - validationID, _ = ids.FromString("2vKCTXoueQ9SSWH7KmpMimbD6LQY1HmPuFDqKWJtAuCUjHkH23") validatorResponse, _, err := pClient.GetL1Validator(ctx, validationID) if err != nil { return 0, err From 13683c1f72559516b0f1da2764721e710737b81d Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 12 Dec 2024 12:16:21 -0500 Subject: [PATCH 05/16] fix lint --- cmd/validatorcmd/getBalance.go | 10 ++++++---- pkg/txutils/info.go | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cmd/validatorcmd/getBalance.go b/cmd/validatorcmd/getBalance.go index c013bd65f..99d110897 100644 --- a/cmd/validatorcmd/getBalance.go +++ b/cmd/validatorcmd/getBalance.go @@ -61,10 +61,6 @@ func getBalance(_ *cobra.Command, _ []string) error { return err } - isBootstrapValidator, err := app.Prompt.CaptureYesNo("Is the validator a bootstrap validator?") - if err != nil { - return err - } var balance uint64 if validationIDStr != "" { validationID, err := ids.FromString(validationIDStr) @@ -75,8 +71,14 @@ func getBalance(_ *cobra.Command, _ []string) error { if err != nil { return err } + ux.Logger.PrintToUser(" Validator Balance: %.5f", float64(balance)/float64(units.Avax)) + return nil } + isBootstrapValidator, err := app.Prompt.CaptureYesNo("Is the validator a bootstrap validator?") + if err != nil { + return err + } if isBootstrapValidator { if l1 == "" { return fmt.Errorf("--l1 flag is required to get bootstrap validator balance") diff --git a/pkg/txutils/info.go b/pkg/txutils/info.go index c5a525201..5eb65951e 100644 --- a/pkg/txutils/info.go +++ b/pkg/txutils/info.go @@ -114,6 +114,7 @@ func GetOwners(network models.Network, subnetID ids.ID) (bool, []string, uint32, func GetValidatorPChainBalanceBootstrapValidator(network models.Network, subnetID ids.ID, index uint32) (uint64, error) { validationID := subnetID.Append(index) + fmt.Printf("obtained index %s \n", index) return GetValidatorPChainBalanceValidationID(network, validationID) } @@ -124,5 +125,6 @@ func GetValidatorPChainBalanceValidationID(network models.Network, validationID if err != nil { return 0, err } + fmt.Printf("validator %s \n", validatorResponse.NodeID) return validatorResponse.Balance, nil } From e14f5f5805b4adc887474501eceecc6c567e53bd Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 12 Dec 2024 13:40:50 -0500 Subject: [PATCH 06/16] add validation id to sidecar --- cmd/blockchaincmd/deploy.go | 13 ++++++++++++- cmd/validatorcmd/getBalance.go | 7 +++++-- pkg/models/bootstrap_validator.go | 2 ++ pkg/txutils/info.go | 7 ------- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index a90460e0b..059f86d82 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -925,7 +925,18 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { return err } ux.Logger.PrintToUser("") - + for index, avagoValidator := range avaGoBootstrapValidators { + for bootstrapValidatorIndex, validator := range bootstrapValidators { + avagoValidatorNodeID, err := ids.ToNodeID(avagoValidator.NodeID) + if err != nil { + return err + } + if validator.NodeID == avagoValidatorNodeID.String() { + validationID := subnetID.Append(uint32(index)) + bootstrapValidators[bootstrapValidatorIndex].ValidationID = validationID.String() + } + } + } if err := app.UpdateSidecarNetworks( &sidecar, network, diff --git a/cmd/validatorcmd/getBalance.go b/cmd/validatorcmd/getBalance.go index 99d110897..1e6819392 100644 --- a/cmd/validatorcmd/getBalance.go +++ b/cmd/validatorcmd/getBalance.go @@ -104,8 +104,11 @@ func getBalance(_ *cobra.Command, _ []string) error { if err != nil { return err } - validatorIndex := bootstrapValidatorsToIndexMap[chosenValidator] - balance, err = txutils.GetValidatorPChainBalanceBootstrapValidator(network, sc.Networks[network.Name()].SubnetID, uint32(validatorIndex)) + validationID, err := ids.FromString(bootstrapValidators[bootstrapValidatorsToIndexMap[chosenValidator]].ValidationID) + if err != nil { + return err + } + balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) if err != nil { return err } diff --git a/pkg/models/bootstrap_validator.go b/pkg/models/bootstrap_validator.go index 8072bf39a..c3419a04f 100644 --- a/pkg/models/bootstrap_validator.go +++ b/pkg/models/bootstrap_validator.go @@ -14,4 +14,6 @@ type SubnetValidator struct { BLSProofOfPossession string `json:"BLSProofOfPossession"` ChangeOwnerAddr string `json:"ChangeOwnerAddr"` + + ValidationID string `json:"ValidationID"` } diff --git a/pkg/txutils/info.go b/pkg/txutils/info.go index 5eb65951e..4cd48b8d1 100644 --- a/pkg/txutils/info.go +++ b/pkg/txutils/info.go @@ -112,12 +112,6 @@ func GetOwners(network models.Network, subnetID ids.ID) (bool, []string, uint32, return isPermissioned, controlKeysStrs, threshold, nil } -func GetValidatorPChainBalanceBootstrapValidator(network models.Network, subnetID ids.ID, index uint32) (uint64, error) { - validationID := subnetID.Append(index) - fmt.Printf("obtained index %s \n", index) - return GetValidatorPChainBalanceValidationID(network, validationID) -} - func GetValidatorPChainBalanceValidationID(network models.Network, validationID ids.ID) (uint64, error) { pClient := platformvm.NewClient(network.Endpoint) ctx := context.Background() @@ -125,6 +119,5 @@ func GetValidatorPChainBalanceValidationID(network models.Network, validationID if err != nil { return 0, err } - fmt.Printf("validator %s \n", validatorResponse.NodeID) return validatorResponse.Balance, nil } From e752b8a2e2dcc8905bdfe355c2c2f131886c7d08 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 12 Dec 2024 14:01:20 -0500 Subject: [PATCH 07/16] fix lint --- cmd/blockchaincmd/deploy.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/cmd/blockchaincmd/deploy.go b/cmd/blockchaincmd/deploy.go index 059f86d82..d9c18073b 100644 --- a/cmd/blockchaincmd/deploy.go +++ b/cmd/blockchaincmd/deploy.go @@ -925,17 +925,8 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { return err } ux.Logger.PrintToUser("") - for index, avagoValidator := range avaGoBootstrapValidators { - for bootstrapValidatorIndex, validator := range bootstrapValidators { - avagoValidatorNodeID, err := ids.ToNodeID(avagoValidator.NodeID) - if err != nil { - return err - } - if validator.NodeID == avagoValidatorNodeID.String() { - validationID := subnetID.Append(uint32(index)) - bootstrapValidators[bootstrapValidatorIndex].ValidationID = validationID.String() - } - } + if err = setBootstrapValidatorValidationID(avaGoBootstrapValidators, bootstrapValidators, subnetID); err != nil { + return err } if err := app.UpdateSidecarNetworks( &sidecar, @@ -1185,6 +1176,22 @@ func deployBlockchain(cmd *cobra.Command, args []string) error { return nil } +func setBootstrapValidatorValidationID(avaGoBootstrapValidators []*txs.ConvertSubnetToL1Validator, bootstrapValidators []models.SubnetValidator, subnetID ids.ID) error { + for index, avagoValidator := range avaGoBootstrapValidators { + for bootstrapValidatorIndex, validator := range bootstrapValidators { + avagoValidatorNodeID, err := ids.ToNodeID(avagoValidator.NodeID) + if err != nil { + return err + } + if validator.NodeID == avagoValidatorNodeID.String() { + validationID := subnetID.Append(uint32(index)) + bootstrapValidators[bootstrapValidatorIndex].ValidationID = validationID.String() + } + } + } + return nil +} + func getClusterBootstrapValidators(clusterName string, network models.Network) ([]models.SubnetValidator, error) { clusterConf, err := app.GetClusterConfig(clusterName) if err != nil { From ba87cc408337a3fb623393fafdf64bca1b77ce76 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Thu, 12 Dec 2024 16:14:41 -0500 Subject: [PATCH 08/16] increase balance --- cmd/validatorcmd/getBalance.go | 4 +- cmd/validatorcmd/increaseBalance.go | 119 ++++++++++++++++++++++++++++ cmd/validatorcmd/validator.go | 2 +- pkg/subnet/public.go | 49 ++++++++++++ 4 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 cmd/validatorcmd/increaseBalance.go diff --git a/cmd/validatorcmd/getBalance.go b/cmd/validatorcmd/getBalance.go index 1e6819392..98ae9ff5a 100644 --- a/cmd/validatorcmd/getBalance.go +++ b/cmd/validatorcmd/getBalance.go @@ -32,7 +32,7 @@ var getBalanceSupportedNetworkOptions = []networkoptions.NetworkOption{ func NewGetBalanceCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "getBalance", + Use: "increaseBalance", Short: "Gets current balance of validator on P-Chain", Long: `This command gets the remaining validator P-Chain balance that is available to pay P-Chain continuous fee`, @@ -88,7 +88,7 @@ func getBalance(_ *cobra.Command, _ []string) error { return fmt.Errorf("failed to load sidecar: %w", err) } if !sc.Sovereign { - return fmt.Errorf("avalanche validator getBalance command is only applicable to sovereign L1s") + return fmt.Errorf("avalanche validator increaseBalance command is only applicable to sovereign L1s") } bootstrapValidators := sc.Networks[network.Name()].BootstrapValidators if len(bootstrapValidators) == 0 { diff --git a/cmd/validatorcmd/increaseBalance.go b/cmd/validatorcmd/increaseBalance.go new file mode 100644 index 000000000..a338c80fc --- /dev/null +++ b/cmd/validatorcmd/increaseBalance.go @@ -0,0 +1,119 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package validatorcmd + +import ( + "fmt" + + "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "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/ava-labs/avalanchego/utils/units" + "github.com/spf13/cobra" +) + +var increaseBalanceSupportedNetworkOptions = []networkoptions.NetworkOption{ + networkoptions.Local, + networkoptions.Devnet, + networkoptions.EtnaDevnet, + networkoptions.Fuji, + networkoptions.Mainnet, +} + +func NewIncreaseBalanceCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "increaseBalance", + Short: "Increase current balance of validator on P-Chain", + Long: `This command increases the validator P-Chain balance`, + RunE: increaseBalance, + Args: cobrautils.ExactArgs(0), + } + + networkoptions.AddNetworkFlagsToCmd(cmd, &globalNetworkFlags, true, increaseBalanceSupportedNetworkOptions) + cmd.Flags().StringVar(&l1, "l1", "", "name of L1 (to get balance of bootstrap validators only)") + cmd.Flags().StringVar(&subnetID, "subnet-id", "", "subnetID of L1 that the node is validating") + cmd.Flags().StringVar(&validationIDStr, "validation-id", "", "validationIDStr of the validator") + return cmd +} + +func increaseBalance(_ *cobra.Command, _ []string) error { + network, err := networkoptions.GetNetworkFromCmdLineFlags( + app, + "", + globalNetworkFlags, + true, + false, + getBalanceSupportedNetworkOptions, + "", + ) + if err != nil { + return err + } + + var balance uint64 + if validationIDStr != "" { + validationID, err := ids.FromString(validationIDStr) + if err != nil { + return err + } + balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) + if err != nil { + return err + } + ux.Logger.PrintToUser(" Validator Balance: %.5f", float64(balance)/float64(units.Avax)) + return nil + } + + isBootstrapValidator, err := app.Prompt.CaptureYesNo("Is the validator a bootstrap validator?") + if err != nil { + return err + } + if isBootstrapValidator { + if l1 == "" { + return fmt.Errorf("--l1 flag is required to get bootstrap validator balance") + } + sc, err := app.LoadSidecar(l1) + if err != nil { + return fmt.Errorf("failed to load sidecar: %w", err) + } + if !sc.Sovereign { + return fmt.Errorf("avalanche validator increaseBalance command is only applicable to sovereign L1s") + } + bootstrapValidators := sc.Networks[network.Name()].BootstrapValidators + if len(bootstrapValidators) == 0 { + return fmt.Errorf("this L1 does not have any bootstrap validators") + } + bootstrapValidatorsString := []string{} + bootstrapValidatorsToIndexMap := make(map[string]int) + for index, validator := range bootstrapValidators { + bootstrapValidatorsString = append(bootstrapValidatorsString, validator.NodeID) + bootstrapValidatorsToIndexMap[validator.NodeID] = index + } + chosenValidator, err := app.Prompt.CaptureList("Which bootstrap validator do you want to get balance of?", bootstrapValidatorsString) + if err != nil { + return err + } + validationID, err := ids.FromString(bootstrapValidators[bootstrapValidatorsToIndexMap[chosenValidator]].ValidationID) + if err != nil { + return err + } + balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) + if err != nil { + return err + } + } else { + validationID, err := app.Prompt.CaptureID("What is the validator's validationID?") + if err != nil { + return err + } + balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) + if err != nil { + return err + } + } + ux.Logger.PrintToUser(" Validator Balance: %.5f", float64(balance)/float64(units.Avax)) + + return nil +} diff --git a/cmd/validatorcmd/validator.go b/cmd/validatorcmd/validator.go index f16fa6c7b..1ca59d0e3 100644 --- a/cmd/validatorcmd/validator.go +++ b/cmd/validatorcmd/validator.go @@ -23,7 +23,7 @@ the validator will be considered inactive and will no longer participate in vali RunE: cobrautils.CommandSuiteUsage, } app = injectedApp - // validator getBalance + // validator increaseBalance cmd.AddCommand(NewGetBalanceCmd()) return cmd diff --git a/pkg/subnet/public.go b/pkg/subnet/public.go index f3b980985..d2572039b 100644 --- a/pkg/subnet/public.go +++ b/pkg/subnet/public.go @@ -919,6 +919,38 @@ func (d *PublicDeployer) createSubnetTx(controlKeys []string, threshold uint32, return d.Commit(&tx, true) } +func (d *PublicDeployer) increaseValidatorPChainBalance(controlKeys []string, threshold uint32, wallet *primary.Wallet) (ids.ID, error) { + addrs, err := address.ParseToIDs(controlKeys) + if err != nil { + return ids.Empty, fmt.Errorf("failure parsing control keys: %w", err) + } + owners := &secp256k1fx.OutputOwners{ + Addrs: addrs, + Threshold: threshold, + Locktime: 0, + } + if d.kc.UsesLedger { + showLedgerSignatureMsg(d.kc.UsesLedger, d.kc.HasOnlyOneKey(), "CreateSubnet transaction") + } + unsignedTx, err := wallet.P().Builder().NewIncreaseL1ValidatorBalanceTx( + owners, + ) + if unsignedTx != nil { + if err := printFee("CreateSubnetTx", wallet, unsignedTx); err != nil { + return ids.Empty, err + } + } + if err != nil { + return ids.Empty, fmt.Errorf("error building tx: %w", err) + } + tx := txs.Tx{Unsigned: unsignedTx} + if err := wallet.P().Signer().Sign(context.Background(), &tx); err != nil { + return ids.Empty, fmt.Errorf("error signing tx: %w", err) + } + + return d.Commit(&tx, true) +} + func printFee(kind string, wallet *primary.Wallet, unsignedTx txs.UnsignedTx) error { if showFees { var pFeeCalculator avagofee.Calculator @@ -1083,3 +1115,20 @@ func showLedgerSignatureMsg( ux.Logger.PrintToUser("*** Please sign %s on the ledger device %s***", toSignDesc, multipleTimesMsg) } } + +func (d *PublicDeployer) IncreaseValidatorPChainBalance( + controlKeys []string, + threshold uint32, +) (ids.ID, error) { + wallet, err := d.loadWallet() + if err != nil { + return ids.Empty, err + } + subnetID, err := d.createSubnetTx(controlKeys, threshold, wallet) + if err != nil { + return ids.Empty, err + } + ux.Logger.PrintToUser("Subnet has been created with ID: %s", subnetID.String()) + time.Sleep(2 * time.Second) + return subnetID, nil +} From 2d65ccd4672287c782d5026b7d88263724941664 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Fri, 13 Dec 2024 17:06:18 -0500 Subject: [PATCH 09/16] increase balance --- cmd/validatorcmd/increaseBalance.go | 85 +++++++++++++---------------- pkg/subnet/public.go | 28 ++++------ 2 files changed, 47 insertions(+), 66 deletions(-) diff --git a/cmd/validatorcmd/increaseBalance.go b/cmd/validatorcmd/increaseBalance.go index a338c80fc..85807e650 100644 --- a/cmd/validatorcmd/increaseBalance.go +++ b/cmd/validatorcmd/increaseBalance.go @@ -3,7 +3,9 @@ package validatorcmd import ( - "fmt" + "github.com/ava-labs/avalanche-cli/pkg/constants" + "github.com/ava-labs/avalanche-cli/pkg/keychain" + "github.com/ava-labs/avalanche-cli/pkg/subnet" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" @@ -14,6 +16,13 @@ import ( "github.com/spf13/cobra" ) +var ( + keyName string + useLedger bool + useEwoq bool + ledgerAddresses []string +) + var increaseBalanceSupportedNetworkOptions = []networkoptions.NetworkOption{ networkoptions.Local, networkoptions.Devnet, @@ -32,6 +41,7 @@ func NewIncreaseBalanceCmd() *cobra.Command { } networkoptions.AddNetworkFlagsToCmd(cmd, &globalNetworkFlags, true, increaseBalanceSupportedNetworkOptions) + cmd.Flags().StringVarP(&keyName, "key", "k", "", "select the key to use [fuji/devnet deploy only]") cmd.Flags().StringVar(&l1, "l1", "", "name of L1 (to get balance of bootstrap validators only)") cmd.Flags().StringVar(&subnetID, "subnet-id", "", "subnetID of L1 that the node is validating") cmd.Flags().StringVar(&validationIDStr, "validation-id", "", "validationIDStr of the validator") @@ -53,65 +63,44 @@ func increaseBalance(_ *cobra.Command, _ []string) error { } var balance uint64 + var validationID ids.ID if validationIDStr != "" { - validationID, err := ids.FromString(validationIDStr) + validationID, err = ids.FromString(validationIDStr) if err != nil { return err } - balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) + + return nil + } else { + validationID, err = app.Prompt.CaptureID("What is the validator's validationID?") if err != nil { return err } - ux.Logger.PrintToUser(" Validator Balance: %.5f", float64(balance)/float64(units.Avax)) - return nil } + fee := network.GenesisParams().TxFeeConfig.StaticFeeConfig.TxFee + kc, err := keychain.GetKeychainFromCmdLineFlags( + app, + constants.PayTxsFeesMsg, + network, + keyName, + useEwoq, + useLedger, + ledgerAddresses, + fee, + ) + if err != nil { + return err + } + deployer := subnet.NewPublicDeployer(app, kc, network) - isBootstrapValidator, err := app.Prompt.CaptureYesNo("Is the validator a bootstrap validator?") + _, err = deployer.IncreaseValidatorPChainBalance(validationID, balance) if err != nil { return err } - if isBootstrapValidator { - if l1 == "" { - return fmt.Errorf("--l1 flag is required to get bootstrap validator balance") - } - sc, err := app.LoadSidecar(l1) - if err != nil { - return fmt.Errorf("failed to load sidecar: %w", err) - } - if !sc.Sovereign { - return fmt.Errorf("avalanche validator increaseBalance command is only applicable to sovereign L1s") - } - bootstrapValidators := sc.Networks[network.Name()].BootstrapValidators - if len(bootstrapValidators) == 0 { - return fmt.Errorf("this L1 does not have any bootstrap validators") - } - bootstrapValidatorsString := []string{} - bootstrapValidatorsToIndexMap := make(map[string]int) - for index, validator := range bootstrapValidators { - bootstrapValidatorsString = append(bootstrapValidatorsString, validator.NodeID) - bootstrapValidatorsToIndexMap[validator.NodeID] = index - } - chosenValidator, err := app.Prompt.CaptureList("Which bootstrap validator do you want to get balance of?", bootstrapValidatorsString) - if err != nil { - return err - } - validationID, err := ids.FromString(bootstrapValidators[bootstrapValidatorsToIndexMap[chosenValidator]].ValidationID) - if err != nil { - return err - } - balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) - if err != nil { - return err - } - } else { - validationID, err := app.Prompt.CaptureID("What is the validator's validationID?") - if err != nil { - return err - } - balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) - if err != nil { - return err - } + deployer.CleanCacheWallet() + balance, err = txutils.GetValidatorPChainBalanceValidationID(network, validationID) + if err != nil { + return err } ux.Logger.PrintToUser(" Validator Balance: %.5f", float64(balance)/float64(units.Avax)) diff --git a/pkg/subnet/public.go b/pkg/subnet/public.go index d2572039b..c878e6b6b 100644 --- a/pkg/subnet/public.go +++ b/pkg/subnet/public.go @@ -919,24 +919,16 @@ func (d *PublicDeployer) createSubnetTx(controlKeys []string, threshold uint32, return d.Commit(&tx, true) } -func (d *PublicDeployer) increaseValidatorPChainBalance(controlKeys []string, threshold uint32, wallet *primary.Wallet) (ids.ID, error) { - addrs, err := address.ParseToIDs(controlKeys) - if err != nil { - return ids.Empty, fmt.Errorf("failure parsing control keys: %w", err) - } - owners := &secp256k1fx.OutputOwners{ - Addrs: addrs, - Threshold: threshold, - Locktime: 0, - } +func (d *PublicDeployer) increaseValidatorPChainBalance(validationID ids.ID, balance uint64, wallet *primary.Wallet) (ids.ID, error) { if d.kc.UsesLedger { - showLedgerSignatureMsg(d.kc.UsesLedger, d.kc.HasOnlyOneKey(), "CreateSubnet transaction") + showLedgerSignatureMsg(d.kc.UsesLedger, d.kc.HasOnlyOneKey(), "IncreaseL1ValidatorBalance transaction") } unsignedTx, err := wallet.P().Builder().NewIncreaseL1ValidatorBalanceTx( - owners, + validationID, + balance, ) if unsignedTx != nil { - if err := printFee("CreateSubnetTx", wallet, unsignedTx); err != nil { + if err := printFee("IncreaseL1ValidatorBalanceTx", wallet, unsignedTx); err != nil { return ids.Empty, err } } @@ -1117,18 +1109,18 @@ func showLedgerSignatureMsg( } func (d *PublicDeployer) IncreaseValidatorPChainBalance( - controlKeys []string, - threshold uint32, + validationID ids.ID, + balance uint64, ) (ids.ID, error) { wallet, err := d.loadWallet() if err != nil { return ids.Empty, err } - subnetID, err := d.createSubnetTx(controlKeys, threshold, wallet) + txID, err := d.increaseValidatorPChainBalance(validationID, balance, wallet) if err != nil { return ids.Empty, err } - ux.Logger.PrintToUser("Subnet has been created with ID: %s", subnetID.String()) + ux.Logger.PrintToUser("Validator balance has been increased with tx ID: %s", txID.String()) time.Sleep(2 * time.Second) - return subnetID, nil + return txID, nil } From 9ff1d3d6d7484662e3efb242327323073dca8abd Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Fri, 13 Dec 2024 17:15:52 -0500 Subject: [PATCH 10/16] fix lint --- cmd/validatorcmd/increaseBalance.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/validatorcmd/increaseBalance.go b/cmd/validatorcmd/increaseBalance.go index 85807e650..0d7923ccf 100644 --- a/cmd/validatorcmd/increaseBalance.go +++ b/cmd/validatorcmd/increaseBalance.go @@ -43,7 +43,6 @@ func NewIncreaseBalanceCmd() *cobra.Command { networkoptions.AddNetworkFlagsToCmd(cmd, &globalNetworkFlags, true, increaseBalanceSupportedNetworkOptions) cmd.Flags().StringVarP(&keyName, "key", "k", "", "select the key to use [fuji/devnet deploy only]") cmd.Flags().StringVar(&l1, "l1", "", "name of L1 (to get balance of bootstrap validators only)") - cmd.Flags().StringVar(&subnetID, "subnet-id", "", "subnetID of L1 that the node is validating") cmd.Flags().StringVar(&validationIDStr, "validation-id", "", "validationIDStr of the validator") return cmd } From 101075fd8c9d3dbeb2163b39e912099c40bd08a3 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Fri, 13 Dec 2024 17:16:23 -0500 Subject: [PATCH 11/16] fix lint --- cmd/root.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/root.go b/cmd/root.go index 8b1772a0b..0e3b08bea 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,7 +5,6 @@ package cmd import ( "errors" "fmt" - "github.com/ava-labs/avalanche-cli/cmd/validatorcmd" "os" "os/signal" "os/user" @@ -16,6 +15,8 @@ import ( "github.com/ava-labs/avalanche-cli/cmd/validatorcmd" + "github.com/ava-labs/avalanche-cli/cmd/validatorcmd" + "github.com/ava-labs/avalanche-cli/cmd/backendcmd" "github.com/ava-labs/avalanche-cli/cmd/blockchaincmd" "github.com/ava-labs/avalanche-cli/cmd/configcmd" From 3ad1544ada24e10cabc3ff09904cfe269f78de03 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Fri, 13 Dec 2024 17:17:41 -0500 Subject: [PATCH 12/16] fix lint --- cmd/root.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 0e3b08bea..a4c04b1f7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -15,8 +15,6 @@ import ( "github.com/ava-labs/avalanche-cli/cmd/validatorcmd" - "github.com/ava-labs/avalanche-cli/cmd/validatorcmd" - "github.com/ava-labs/avalanche-cli/cmd/backendcmd" "github.com/ava-labs/avalanche-cli/cmd/blockchaincmd" "github.com/ava-labs/avalanche-cli/cmd/configcmd" From 47021c2b4b920bbb9f2e289f11312117d9d01ae4 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Sun, 15 Dec 2024 15:03:42 -0500 Subject: [PATCH 13/16] increase balance --- cmd/validatorcmd/validator.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/validatorcmd/validator.go b/cmd/validatorcmd/validator.go index f16fa6c7b..54c3fe25d 100644 --- a/cmd/validatorcmd/validator.go +++ b/cmd/validatorcmd/validator.go @@ -25,6 +25,7 @@ the validator will be considered inactive and will no longer participate in vali app = injectedApp // validator getBalance cmd.AddCommand(NewGetBalanceCmd()) - + // validator increaseBalance + cmd.AddCommand(NewIncreaseBalanceCmd()) return cmd } From ce0a0f1523401d72ff2991009ebb733a37041105 Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Sun, 15 Dec 2024 16:16:26 -0500 Subject: [PATCH 14/16] add balance --- cmd/blockchaincmd/add_validator.go | 2 +- cmd/validatorcmd/getBalance.go | 2 +- cmd/validatorcmd/increaseBalance.go | 67 ++++++++++++++++++++++++++--- pkg/prompts/prompts.go | 5 ++- pkg/prompts/validations.go | 11 +++-- pkg/subnet/public.go | 1 - 6 files changed, 73 insertions(+), 15 deletions(-) diff --git a/cmd/blockchaincmd/add_validator.go b/cmd/blockchaincmd/add_validator.go index 31059c702..afece9265 100644 --- a/cmd/blockchaincmd/add_validator.go +++ b/cmd/blockchaincmd/add_validator.go @@ -311,7 +311,7 @@ func promptValidatorBalance(availableBalance uint64) (uint64, error) { ux.Logger.PrintToUser("Validator's balance is used to pay for continuous fee to the P-Chain") ux.Logger.PrintToUser("When this Balance reaches 0, the validator will be considered inactive and will no longer participate in validating the L1") txt := "What balance would you like to assign to the validator (in AVAX)?" - return app.Prompt.CaptureValidatorBalance(txt, availableBalance) + return app.Prompt.CaptureValidatorBalance(txt, availableBalance, constants.BootstrapValidatorBalanceAVAX) } func CallAddValidator( diff --git a/cmd/validatorcmd/getBalance.go b/cmd/validatorcmd/getBalance.go index d2f6f6cb2..2afd6fb7f 100644 --- a/cmd/validatorcmd/getBalance.go +++ b/cmd/validatorcmd/getBalance.go @@ -120,7 +120,7 @@ func getBalance(_ *cobra.Command, _ []string) error { return err } } - ux.Logger.PrintToUser(" Validator Balance: %.5f", float64(balance)/float64(units.Avax)) + ux.Logger.PrintToUser(" Validator Balance: %.5f AVAX", float64(balance)/float64(units.Avax)) return nil } diff --git a/cmd/validatorcmd/increaseBalance.go b/cmd/validatorcmd/increaseBalance.go index 0d7923ccf..2e17d2527 100644 --- a/cmd/validatorcmd/increaseBalance.go +++ b/cmd/validatorcmd/increaseBalance.go @@ -3,9 +3,11 @@ package validatorcmd import ( + "fmt" "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/keychain" "github.com/ava-labs/avalanche-cli/pkg/subnet" + "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/networkoptions" @@ -21,6 +23,7 @@ var ( useLedger bool useEwoq bool ledgerAddresses []string + balanceFlag float64 ) var increaseBalanceSupportedNetworkOptions = []networkoptions.NetworkOption{ @@ -42,8 +45,9 @@ func NewIncreaseBalanceCmd() *cobra.Command { networkoptions.AddNetworkFlagsToCmd(cmd, &globalNetworkFlags, true, increaseBalanceSupportedNetworkOptions) cmd.Flags().StringVarP(&keyName, "key", "k", "", "select the key to use [fuji/devnet deploy only]") - cmd.Flags().StringVar(&l1, "l1", "", "name of L1 (to get balance of bootstrap validators only)") + cmd.Flags().StringVar(&l1, "l1", "", "name of L1 (to increase balance of bootstrap validators only)") cmd.Flags().StringVar(&validationIDStr, "validation-id", "", "validationIDStr of the validator") + cmd.Flags().Float64Var(&balanceFlag, "balance", 0, "amount of AVAX to increase validator's balance by") return cmd } @@ -60,7 +64,6 @@ func increaseBalance(_ *cobra.Command, _ []string) error { if err != nil { return err } - var balance uint64 var validationID ids.ID if validationIDStr != "" { @@ -68,13 +71,46 @@ func increaseBalance(_ *cobra.Command, _ []string) error { if err != nil { return err } - - return nil } else { - validationID, err = app.Prompt.CaptureID("What is the validator's validationID?") + isBootstrapValidator, err := app.Prompt.CaptureYesNo("Is the validator a bootstrap validator?") if err != nil { return err } + if isBootstrapValidator { + if l1 == "" { + return fmt.Errorf("--l1 flag is required to get bootstrap validator balance") + } + sc, err := app.LoadSidecar(l1) + if err != nil { + return fmt.Errorf("failed to load sidecar: %w", err) + } + if !sc.Sovereign { + return fmt.Errorf("avalanche validator increaseBalance command is only applicable to sovereign L1s") + } + bootstrapValidators := sc.Networks[network.Name()].BootstrapValidators + if len(bootstrapValidators) == 0 { + return fmt.Errorf("this L1 does not have any bootstrap validators") + } + bootstrapValidatorsString := []string{} + bootstrapValidatorsToIndexMap := make(map[string]int) + for index, validator := range bootstrapValidators { + bootstrapValidatorsString = append(bootstrapValidatorsString, validator.NodeID) + bootstrapValidatorsToIndexMap[validator.NodeID] = index + } + chosenValidator, err := app.Prompt.CaptureList("Which bootstrap validator do you want to get balance of?", bootstrapValidatorsString) + if err != nil { + return err + } + validationID, err = ids.FromString(bootstrapValidators[bootstrapValidatorsToIndexMap[chosenValidator]].ValidationID) + if err != nil { + return err + } + } else { + validationID, err = app.Prompt.CaptureID("What is the validator's validationID?") + if err != nil { + return err + } + } } fee := network.GenesisParams().TxFeeConfig.StaticFeeConfig.TxFee kc, err := keychain.GetKeychainFromCmdLineFlags( @@ -91,6 +127,18 @@ func increaseBalance(_ *cobra.Command, _ []string) error { return err } deployer := subnet.NewPublicDeployer(app, kc, network) + if balanceFlag == 0 { + availableBalance, err := utils.GetNetworkBalance(kc.Addresses().List(), network.Endpoint) + if err != nil { + return err + } + balance, err = promptValidatorBalance(availableBalance / units.Avax) + if err != nil { + return err + } + } else { + balance = uint64(balanceFlag * float64(units.Avax)) + } _, err = deployer.IncreaseValidatorPChainBalance(validationID, balance) if err != nil { @@ -101,7 +149,14 @@ func increaseBalance(_ *cobra.Command, _ []string) error { if err != nil { return err } - ux.Logger.PrintToUser(" Validator Balance: %.5f", float64(balance)/float64(units.Avax)) + ux.Logger.PrintToUser(" New Validator Balance: %.5f AVAX", float64(balance)/float64(units.Avax)) return nil } + +func promptValidatorBalance(availableBalance uint64) (uint64, error) { + ux.Logger.PrintToUser("Validator's balance is used to pay for continuous fee to the P-Chain") + ux.Logger.PrintToUser("When this Balance reaches 0, the validator will be considered inactive and will no longer participate in validating the L1") + txt := "How many AVAX do you want to increase the balance of this validator by?" + return app.Prompt.CaptureValidatorBalance(txt, availableBalance, 0) +} diff --git a/pkg/prompts/prompts.go b/pkg/prompts/prompts.go index 78e5e85c4..a5fd7baf9 100644 --- a/pkg/prompts/prompts.go +++ b/pkg/prompts/prompts.go @@ -111,7 +111,7 @@ type Prompter interface { CaptureNodeID(promptStr string) (ids.NodeID, error) CaptureID(promptStr string) (ids.ID, error) CaptureWeight(promptStr string) (uint64, error) - CaptureValidatorBalance(promptStr string, availableBalance uint64) (uint64, error) + CaptureValidatorBalance(promptStr string, availableBalance uint64, minBalance float64) (uint64, error) CapturePositiveInt(promptStr string, comparators []Comparator) (int, error) CaptureInt(promptStr string, validator func(int) error) (int, error) CaptureUint8(promptStr string) (uint8, error) @@ -307,10 +307,11 @@ func (*realPrompter) CaptureNodeID(promptStr string) (ids.NodeID, error) { func (*realPrompter) CaptureValidatorBalance( promptStr string, availableBalance uint64, + minBalance float64, ) (uint64, error) { prompt := promptui.Prompt{ Label: promptStr, - Validate: validateValidatorBalanceFunc(availableBalance), + Validate: validateValidatorBalanceFunc(availableBalance, minBalance), } amountStr, err := prompt.Run() if err != nil { diff --git a/pkg/prompts/validations.go b/pkg/prompts/validations.go index a35b65a60..fdfa11ea2 100644 --- a/pkg/prompts/validations.go +++ b/pkg/prompts/validations.go @@ -145,17 +145,20 @@ func validateWeight(input string) error { return nil } -func validateValidatorBalanceFunc(availableBalance uint64) func(string) error { +func validateValidatorBalanceFunc(availableBalance uint64, minBalance float64) func(string) error { return func(input string) error { val, err := strconv.ParseFloat(input, 64) if err != nil { return err } - if val < constants.BootstrapValidatorBalanceAVAX { - return fmt.Errorf("subnet validator balance must be at least 0.1 AVAX") + if val == 0 { + return fmt.Errorf("entered value has to be greater than 0 AVAX") + } + if val < minBalance { + return fmt.Errorf("validator balance must be at least %2f AVAX", minBalance) } if val > float64(availableBalance) { - return fmt.Errorf("current balance of %d is not sufficient for subnet validator balance to be %2f AVAX", availableBalance, val) + return fmt.Errorf("current balance of %d is not sufficient for validator balance to be %2f AVAX", availableBalance, val) } return nil } diff --git a/pkg/subnet/public.go b/pkg/subnet/public.go index c878e6b6b..f25207686 100644 --- a/pkg/subnet/public.go +++ b/pkg/subnet/public.go @@ -1121,6 +1121,5 @@ func (d *PublicDeployer) IncreaseValidatorPChainBalance( return ids.Empty, err } ux.Logger.PrintToUser("Validator balance has been increased with tx ID: %s", txID.String()) - time.Sleep(2 * time.Second) return txID, nil } From 12b596d8da520497c3416abce204d6e28e02543b Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Sun, 15 Dec 2024 16:20:29 -0500 Subject: [PATCH 15/16] update prompt --- internal/mocks/prompter.go | 28 ++++++++++++++-------------- pkg/constants/constants.go | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/internal/mocks/prompter.go b/internal/mocks/prompter.go index 5588d0483..74a552840 100644 --- a/internal/mocks/prompter.go +++ b/internal/mocks/prompter.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. +// Code generated by mockery v2.46.2. DO NOT EDIT. package mocks @@ -369,7 +369,7 @@ func (_m *Prompter) CaptureID(promptStr string) (ids.ID, error) { } // CaptureIndex provides a mock function with given fields: promptStr, options -func (_m *Prompter) CaptureIndex(promptStr string, options []interface{}) (int, error) { +func (_m *Prompter) CaptureIndex(promptStr string, options []any) (int, error) { ret := _m.Called(promptStr, options) if len(ret) == 0 { @@ -378,16 +378,16 @@ func (_m *Prompter) CaptureIndex(promptStr string, options []interface{}) (int, var r0 int var r1 error - if rf, ok := ret.Get(0).(func(string, []interface{}) (int, error)); ok { + if rf, ok := ret.Get(0).(func(string, []any) (int, error)); ok { return rf(promptStr, options) } - if rf, ok := ret.Get(0).(func(string, []interface{}) int); ok { + if rf, ok := ret.Get(0).(func(string, []any) int); ok { r0 = rf(promptStr, options) } else { r0 = ret.Get(0).(int) } - if rf, ok := ret.Get(1).(func(string, []interface{}) error); ok { + if rf, ok := ret.Get(1).(func(string, []any) error); ok { r1 = rf(promptStr, options) } else { r1 = ret.Error(1) @@ -988,9 +988,9 @@ func (_m *Prompter) CaptureValidatedString(promptStr string, validator func(stri return r0, r1 } -// CaptureValidatorBalance provides a mock function with given fields: promptStr, availableBalance -func (_m *Prompter) CaptureValidatorBalance(promptStr string, availableBalance uint64) (uint64, error) { - ret := _m.Called(promptStr, availableBalance) +// CaptureValidatorBalance provides a mock function with given fields: promptStr, availableBalance, minBalance +func (_m *Prompter) CaptureValidatorBalance(promptStr string, availableBalance uint64, minBalance float64) (uint64, error) { + ret := _m.Called(promptStr, availableBalance, minBalance) if len(ret) == 0 { panic("no return value specified for CaptureValidatorBalance") @@ -998,17 +998,17 @@ func (_m *Prompter) CaptureValidatorBalance(promptStr string, availableBalance u var r0 uint64 var r1 error - if rf, ok := ret.Get(0).(func(string, uint64) (uint64, error)); ok { - return rf(promptStr, availableBalance) + if rf, ok := ret.Get(0).(func(string, uint64, float64) (uint64, error)); ok { + return rf(promptStr, availableBalance, minBalance) } - if rf, ok := ret.Get(0).(func(string, uint64) uint64); ok { - r0 = rf(promptStr, availableBalance) + if rf, ok := ret.Get(0).(func(string, uint64, float64) uint64); ok { + r0 = rf(promptStr, availableBalance, minBalance) } else { r0 = ret.Get(0).(uint64) } - if rf, ok := ret.Get(1).(func(string, uint64) error); ok { - r1 = rf(promptStr, availableBalance) + if rf, ok := ret.Get(1).(func(string, uint64, float64) error); ok { + r1 = rf(promptStr, availableBalance, minBalance) } else { r1 = ret.Error(1) } diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 4ed225ac6..8d8b45c8a 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -59,7 +59,7 @@ const ( FastGRPCDialTimeout = 100 * time.Millisecond FujiBootstrapTimeout = 15 * time.Minute - MainnetBootstrapTimeout = 2 * time.Hour + MainnetBootstrapTimeout = 10 * time.Hour SSHServerStartTimeout = 1 * time.Minute SSHScriptTimeout = 2 * time.Minute From 714fd0f33d84c313897f9a12d9cd227edcd072aa Mon Sep 17 00:00:00 2001 From: Raymond Sukanto Date: Sun, 15 Dec 2024 16:21:23 -0500 Subject: [PATCH 16/16] lint --- cmd/validatorcmd/increaseBalance.go | 1 + pkg/constants/constants.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/validatorcmd/increaseBalance.go b/cmd/validatorcmd/increaseBalance.go index 2e17d2527..a143a35f0 100644 --- a/cmd/validatorcmd/increaseBalance.go +++ b/cmd/validatorcmd/increaseBalance.go @@ -4,6 +4,7 @@ package validatorcmd import ( "fmt" + "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/keychain" "github.com/ava-labs/avalanche-cli/pkg/subnet" diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 8d8b45c8a..4ed225ac6 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -59,7 +59,7 @@ const ( FastGRPCDialTimeout = 100 * time.Millisecond FujiBootstrapTimeout = 15 * time.Minute - MainnetBootstrapTimeout = 10 * time.Hour + MainnetBootstrapTimeout = 2 * time.Hour SSHServerStartTimeout = 1 * time.Minute SSHScriptTimeout = 2 * time.Minute