2018-04-25 07:18:06 -07:00
|
|
|
package cli
|
2018-02-24 05:19:32 -08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-05-28 01:44:04 -07:00
|
|
|
"os"
|
2019-02-06 16:15:37 -08:00
|
|
|
"strings"
|
2018-11-12 10:55:24 -08:00
|
|
|
|
2019-05-28 01:44:04 -07:00
|
|
|
"github.com/spf13/cobra"
|
|
|
|
flag "github.com/spf13/pflag"
|
|
|
|
"github.com/tendermint/tendermint/crypto"
|
2019-01-03 15:28:55 -08:00
|
|
|
|
2018-07-02 21:33:53 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
2019-12-23 08:05:47 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/client/flags"
|
2020-04-03 13:06:37 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/client/tx"
|
2018-02-25 15:45:20 -08:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2019-05-28 01:44:04 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/version"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/staking/types"
|
2018-02-24 05:19:32 -08:00
|
|
|
)
|
|
|
|
|
2020-04-03 13:06:37 -07:00
|
|
|
var (
|
|
|
|
defaultTokens = sdk.TokensFromConsensusPower(100)
|
|
|
|
defaultAmount = defaultTokens.String() + sdk.DefaultBondDenom
|
|
|
|
defaultCommissionRate = "0.1"
|
|
|
|
defaultCommissionMaxRate = "0.2"
|
|
|
|
defaultCommissionMaxChangeRate = "0.01"
|
|
|
|
defaultMinSelfDelegation = "1"
|
|
|
|
)
|
|
|
|
|
|
|
|
// NewTxCmd returns a root CLI command handler for all x/staking transaction commands.
|
2020-07-21 06:54:07 -07:00
|
|
|
func NewTxCmd() *cobra.Command {
|
2019-06-05 16:26:17 -07:00
|
|
|
stakingTxCmd := &cobra.Command{
|
|
|
|
Use: types.ModuleName,
|
|
|
|
Short: "Staking transaction subcommands",
|
|
|
|
DisableFlagParsing: true,
|
|
|
|
SuggestionsMinimumDistance: 2,
|
2019-06-15 05:34:11 -07:00
|
|
|
RunE: client.ValidateCmd,
|
2019-06-05 16:26:17 -07:00
|
|
|
}
|
|
|
|
|
2020-07-11 01:13:46 -07:00
|
|
|
stakingTxCmd.AddCommand(
|
2020-07-21 06:54:07 -07:00
|
|
|
NewCreateValidatorCmd(),
|
|
|
|
NewEditValidatorCmd(),
|
|
|
|
NewDelegateCmd(),
|
|
|
|
NewRedelegateCmd(),
|
|
|
|
NewUnbondCmd(),
|
2020-07-11 01:13:46 -07:00
|
|
|
)
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-06-05 16:26:17 -07:00
|
|
|
return stakingTxCmd
|
|
|
|
}
|
|
|
|
|
2020-07-21 06:54:07 -07:00
|
|
|
func NewCreateValidatorCmd() *cobra.Command {
|
2018-03-17 09:22:11 -07:00
|
|
|
cmd := &cobra.Command{
|
2018-05-17 08:12:28 -07:00
|
|
|
Use: "create-validator",
|
|
|
|
Short: "create new validator initialized with a self-delegation to it",
|
2018-03-17 09:22:11 -07:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
2020-07-21 06:54:07 -07:00
|
|
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
|
|
|
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-07-08 13:00:34 -07:00
|
|
|
|
2020-07-20 05:30:12 -07:00
|
|
|
txf := tx.NewFactoryCLI(clientCtx, cmd.Flags()).WithTxConfig(clientCtx.TxConfig).WithAccountRetriever(clientCtx.AccountRetriever)
|
2020-04-03 13:06:37 -07:00
|
|
|
|
2020-07-08 13:00:34 -07:00
|
|
|
txf, msg, err := NewBuildCreateValidatorMsg(clientCtx, txf, cmd.Flags())
|
2018-09-24 15:23:58 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-07-21 06:54:07 -07:00
|
|
|
|
2020-06-01 05:46:03 -07:00
|
|
|
return tx.GenerateOrBroadcastTxWithFactory(clientCtx, txf, msg)
|
2018-03-17 09:22:11 -07:00
|
|
|
},
|
|
|
|
}
|
2020-07-11 01:13:46 -07:00
|
|
|
|
2020-07-06 14:48:54 -07:00
|
|
|
cmd.Flags().AddFlagSet(FlagSetPublicKey())
|
|
|
|
cmd.Flags().AddFlagSet(FlagSetAmount())
|
2020-07-08 13:00:34 -07:00
|
|
|
cmd.Flags().AddFlagSet(flagSetDescriptionCreate())
|
2020-07-06 14:48:54 -07:00
|
|
|
cmd.Flags().AddFlagSet(FlagSetCommissionCreate())
|
|
|
|
cmd.Flags().AddFlagSet(FlagSetMinSelfDelegation())
|
2019-03-05 08:55:46 -08:00
|
|
|
|
2019-12-23 08:05:47 -08:00
|
|
|
cmd.Flags().String(FlagIP, "", fmt.Sprintf("The node's public IP. It takes effect only when used in combination with --%s", flags.FlagGenerateOnly))
|
2019-01-03 15:28:55 -08:00
|
|
|
cmd.Flags().String(FlagNodeID, "", "The node's ID")
|
2020-07-11 01:13:46 -07:00
|
|
|
flags.AddTxFlagsToCmd(cmd)
|
2019-01-03 15:28:55 -08:00
|
|
|
|
2020-05-02 12:26:59 -07:00
|
|
|
_ = cmd.MarkFlagRequired(flags.FlagFrom)
|
|
|
|
_ = cmd.MarkFlagRequired(FlagAmount)
|
|
|
|
_ = cmd.MarkFlagRequired(FlagPubKey)
|
|
|
|
_ = cmd.MarkFlagRequired(FlagMoniker)
|
|
|
|
|
2020-05-21 14:29:34 -07:00
|
|
|
return cmd
|
2018-02-24 05:19:32 -08:00
|
|
|
}
|
|
|
|
|
2020-07-21 06:54:07 -07:00
|
|
|
func NewEditValidatorCmd() *cobra.Command {
|
2018-03-17 09:22:11 -07:00
|
|
|
cmd := &cobra.Command{
|
2018-05-17 08:12:28 -07:00
|
|
|
Use: "edit-validator",
|
2018-12-18 15:44:28 -08:00
|
|
|
Short: "edit an existing validator account",
|
2018-03-17 09:22:11 -07:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
2020-07-21 06:54:07 -07:00
|
|
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
|
|
|
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-03-17 09:22:11 -07:00
|
|
|
|
2020-06-01 05:46:03 -07:00
|
|
|
valAddr := clientCtx.GetFromAddress()
|
2020-07-08 13:00:34 -07:00
|
|
|
|
|
|
|
moniker, _ := cmd.Flags().GetString(FlagMoniker)
|
|
|
|
identity, _ := cmd.Flags().GetString(FlagIdentity)
|
|
|
|
website, _ := cmd.Flags().GetString(FlagWebsite)
|
|
|
|
security, _ := cmd.Flags().GetString(FlagSecurityContact)
|
|
|
|
details, _ := cmd.Flags().GetString(FlagDetails)
|
2020-07-21 06:54:07 -07:00
|
|
|
description := types.NewDescription(moniker, identity, website, security, details)
|
2018-08-30 21:06:44 -07:00
|
|
|
|
2018-09-24 15:23:58 -07:00
|
|
|
var newRate *sdk.Dec
|
|
|
|
|
2020-07-08 13:00:34 -07:00
|
|
|
commissionRate, _ := cmd.Flags().GetString(FlagCommissionRate)
|
2018-09-24 15:23:58 -07:00
|
|
|
if commissionRate != "" {
|
|
|
|
rate, err := sdk.NewDecFromStr(commissionRate)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("invalid new commission rate: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
newRate = &rate
|
|
|
|
}
|
|
|
|
|
2019-02-08 12:44:19 -08:00
|
|
|
var newMinSelfDelegation *sdk.Int
|
|
|
|
|
2020-07-08 13:00:34 -07:00
|
|
|
minSelfDelegationString, _ := cmd.Flags().GetString(FlagMinSelfDelegation)
|
2019-02-08 12:44:19 -08:00
|
|
|
if minSelfDelegationString != "" {
|
|
|
|
msb, ok := sdk.NewIntFromString(minSelfDelegationString)
|
|
|
|
if !ok {
|
2019-12-27 09:57:54 -08:00
|
|
|
return types.ErrMinSelfDelegationInvalid
|
2019-02-08 12:44:19 -08:00
|
|
|
}
|
2019-12-27 09:57:54 -08:00
|
|
|
|
2019-02-08 12:44:19 -08:00
|
|
|
newMinSelfDelegation = &msb
|
|
|
|
}
|
|
|
|
|
2019-05-28 01:44:04 -07:00
|
|
|
msg := types.NewMsgEditValidator(sdk.ValAddress(valAddr), description, newRate, newMinSelfDelegation)
|
2020-04-09 07:00:10 -07:00
|
|
|
if err := msg.ValidateBasic(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-02-08 12:44:19 -08:00
|
|
|
|
2020-07-21 06:54:07 -07:00
|
|
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
|
2018-03-17 09:22:11 -07:00
|
|
|
},
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-07-08 13:00:34 -07:00
|
|
|
cmd.Flags().AddFlagSet(flagSetDescriptionEdit())
|
|
|
|
cmd.Flags().AddFlagSet(flagSetCommissionUpdate())
|
2020-07-06 14:48:54 -07:00
|
|
|
cmd.Flags().AddFlagSet(FlagSetMinSelfDelegation())
|
2020-07-11 01:13:46 -07:00
|
|
|
flags.AddTxFlagsToCmd(cmd)
|
2020-06-13 11:50:04 -07:00
|
|
|
|
2020-05-21 14:29:34 -07:00
|
|
|
return cmd
|
2018-03-17 09:22:11 -07:00
|
|
|
}
|
2018-02-24 05:19:32 -08:00
|
|
|
|
2020-07-21 06:54:07 -07:00
|
|
|
func NewDelegateCmd() *cobra.Command {
|
2020-08-17 02:04:50 -07:00
|
|
|
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
|
|
|
|
|
2020-04-03 13:06:37 -07:00
|
|
|
cmd := &cobra.Command{
|
2019-02-06 16:15:37 -08:00
|
|
|
Use: "delegate [validator-addr] [amount]",
|
|
|
|
Args: cobra.ExactArgs(2),
|
2019-05-18 16:06:08 -07:00
|
|
|
Short: "Delegate liquid tokens to a validator",
|
|
|
|
Long: strings.TrimSpace(
|
|
|
|
fmt.Sprintf(`Delegate an amount of liquid coins to a validator from your wallet.
|
|
|
|
|
|
|
|
Example:
|
2020-08-17 02:04:50 -07:00
|
|
|
$ %s tx staking delegate %s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm 1000stake --from mykey
|
2019-05-18 16:06:08 -07:00
|
|
|
`,
|
2020-08-17 02:04:50 -07:00
|
|
|
version.AppName, bech32PrefixValAddr,
|
2019-05-18 16:06:08 -07:00
|
|
|
),
|
|
|
|
),
|
2018-03-17 09:22:11 -07:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
2020-07-20 09:42:46 -07:00
|
|
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
|
|
|
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-07-18 23:53:12 -07:00
|
|
|
|
2019-02-06 16:15:37 -08:00
|
|
|
amount, err := sdk.ParseCoin(args[1])
|
2018-03-17 09:22:11 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-02-24 05:19:32 -08:00
|
|
|
|
2020-06-01 05:46:03 -07:00
|
|
|
delAddr := clientCtx.GetFromAddress()
|
2019-02-06 16:15:37 -08:00
|
|
|
valAddr, err := sdk.ValAddressFromBech32(args[0])
|
2018-03-17 09:22:11 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-02-24 05:19:32 -08:00
|
|
|
|
2019-05-28 01:44:04 -07:00
|
|
|
msg := types.NewMsgDelegate(delAddr, valAddr, amount)
|
2020-04-09 07:00:10 -07:00
|
|
|
if err := msg.ValidateBasic(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-07-21 06:54:07 -07:00
|
|
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
|
2018-03-17 09:22:11 -07:00
|
|
|
},
|
2018-02-24 05:19:32 -08:00
|
|
|
}
|
2020-04-03 13:06:37 -07:00
|
|
|
|
2020-07-11 01:13:46 -07:00
|
|
|
flags.AddTxFlagsToCmd(cmd)
|
|
|
|
|
2020-05-21 14:29:34 -07:00
|
|
|
return cmd
|
2018-02-24 05:19:32 -08:00
|
|
|
}
|
|
|
|
|
2020-07-21 06:54:07 -07:00
|
|
|
func NewRedelegateCmd() *cobra.Command {
|
2020-08-17 02:04:50 -07:00
|
|
|
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
|
|
|
|
|
2020-04-03 13:06:37 -07:00
|
|
|
cmd := &cobra.Command{
|
2019-02-06 16:15:37 -08:00
|
|
|
Use: "redelegate [src-validator-addr] [dst-validator-addr] [amount]",
|
2019-05-18 16:06:08 -07:00
|
|
|
Short: "Redelegate illiquid tokens from one validator to another",
|
2019-02-06 16:15:37 -08:00
|
|
|
Args: cobra.ExactArgs(3),
|
2019-05-18 16:06:08 -07:00
|
|
|
Long: strings.TrimSpace(
|
|
|
|
fmt.Sprintf(`Redelegate an amount of illiquid staking tokens from one validator to another.
|
|
|
|
|
|
|
|
Example:
|
2020-08-17 02:04:50 -07:00
|
|
|
$ %s tx staking redelegate %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj %s1l2rsakp388kuv9k8qzq6lrm9taddae7fpx59wm 100stake --from mykey
|
2019-05-18 16:06:08 -07:00
|
|
|
`,
|
2020-08-17 02:04:50 -07:00
|
|
|
version.AppName, bech32PrefixValAddr, bech32PrefixValAddr,
|
2019-05-18 16:06:08 -07:00
|
|
|
),
|
|
|
|
),
|
2018-06-26 19:00:12 -07:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
2020-07-20 09:42:46 -07:00
|
|
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
|
|
|
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-06-26 19:00:12 -07:00
|
|
|
|
2020-06-01 05:46:03 -07:00
|
|
|
delAddr := clientCtx.GetFromAddress()
|
2019-02-06 16:15:37 -08:00
|
|
|
valSrcAddr, err := sdk.ValAddressFromBech32(args[0])
|
2018-06-26 19:00:12 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-08-06 11:11:30 -07:00
|
|
|
|
2019-02-06 16:15:37 -08:00
|
|
|
valDstAddr, err := sdk.ValAddressFromBech32(args[1])
|
2018-06-26 19:00:12 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-03-25 14:13:02 -07:00
|
|
|
amount, err := sdk.ParseCoin(args[2])
|
2018-06-26 19:00:12 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-05-28 01:44:04 -07:00
|
|
|
msg := types.NewMsgBeginRedelegate(delAddr, valSrcAddr, valDstAddr, amount)
|
2020-04-09 07:00:10 -07:00
|
|
|
if err := msg.ValidateBasic(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-07-21 06:54:07 -07:00
|
|
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
|
2018-06-26 19:00:12 -07:00
|
|
|
},
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-07-11 01:13:46 -07:00
|
|
|
flags.AddTxFlagsToCmd(cmd)
|
|
|
|
|
2020-05-21 14:29:34 -07:00
|
|
|
return cmd
|
2018-06-26 19:00:12 -07:00
|
|
|
}
|
|
|
|
|
2020-07-21 06:54:07 -07:00
|
|
|
func NewUnbondCmd() *cobra.Command {
|
2020-08-17 02:04:50 -07:00
|
|
|
bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix()
|
|
|
|
|
2020-04-03 13:06:37 -07:00
|
|
|
cmd := &cobra.Command{
|
2019-02-06 16:15:37 -08:00
|
|
|
Use: "unbond [validator-addr] [amount]",
|
2019-05-18 16:06:08 -07:00
|
|
|
Short: "Unbond shares from a validator",
|
2019-02-06 16:15:37 -08:00
|
|
|
Args: cobra.ExactArgs(2),
|
2019-05-18 16:06:08 -07:00
|
|
|
Long: strings.TrimSpace(
|
|
|
|
fmt.Sprintf(`Unbond an amount of bonded shares from a validator.
|
|
|
|
|
|
|
|
Example:
|
2020-08-17 02:04:50 -07:00
|
|
|
$ %s tx staking unbond %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 100stake --from mykey
|
2019-05-18 16:06:08 -07:00
|
|
|
`,
|
2020-08-17 02:04:50 -07:00
|
|
|
version.AppName, bech32PrefixValAddr,
|
2019-05-18 16:06:08 -07:00
|
|
|
),
|
|
|
|
),
|
2018-06-26 19:00:12 -07:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
2020-07-20 09:42:46 -07:00
|
|
|
clientCtx := client.GetClientContextFromCmd(cmd)
|
|
|
|
clientCtx, err := client.ReadTxCommandFlags(clientCtx, cmd.Flags())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-06-26 19:00:12 -07:00
|
|
|
|
2020-06-01 05:46:03 -07:00
|
|
|
delAddr := clientCtx.GetFromAddress()
|
2019-02-06 16:15:37 -08:00
|
|
|
valAddr, err := sdk.ValAddressFromBech32(args[0])
|
2018-03-17 09:22:11 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-03-25 14:13:02 -07:00
|
|
|
amount, err := sdk.ParseCoin(args[1])
|
2018-06-26 19:00:12 -07:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-05-28 01:44:04 -07:00
|
|
|
msg := types.NewMsgUndelegate(delAddr, valAddr, amount)
|
2020-04-09 07:00:10 -07:00
|
|
|
if err := msg.ValidateBasic(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-07-21 06:54:07 -07:00
|
|
|
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
|
2018-03-17 09:22:11 -07:00
|
|
|
},
|
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-07-11 01:13:46 -07:00
|
|
|
flags.AddTxFlagsToCmd(cmd)
|
|
|
|
|
2020-05-21 14:29:34 -07:00
|
|
|
return cmd
|
2018-02-24 05:19:32 -08:00
|
|
|
}
|
2018-11-21 15:44:13 -08:00
|
|
|
|
2020-07-08 13:00:34 -07:00
|
|
|
func NewBuildCreateValidatorMsg(clientCtx client.Context, txf tx.Factory, fs *flag.FlagSet) (tx.Factory, sdk.Msg, error) {
|
|
|
|
fAmount, _ := fs.GetString(FlagAmount)
|
|
|
|
amount, err := sdk.ParseCoin(fAmount)
|
2020-04-03 13:06:37 -07:00
|
|
|
if err != nil {
|
|
|
|
return txf, nil, err
|
|
|
|
}
|
2019-05-28 01:44:04 -07:00
|
|
|
|
2020-06-01 05:46:03 -07:00
|
|
|
valAddr := clientCtx.GetFromAddress()
|
2020-07-08 13:00:34 -07:00
|
|
|
pkStr, _ := fs.GetString(FlagPubKey)
|
2020-04-03 13:06:37 -07:00
|
|
|
|
|
|
|
pk, err := sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeConsPub, pkStr)
|
|
|
|
if err != nil {
|
|
|
|
return txf, nil, err
|
|
|
|
}
|
|
|
|
|
2020-07-08 13:00:34 -07:00
|
|
|
moniker, _ := fs.GetString(FlagMoniker)
|
|
|
|
identity, _ := fs.GetString(FlagIdentity)
|
|
|
|
website, _ := fs.GetString(FlagWebsite)
|
|
|
|
security, _ := fs.GetString(FlagSecurityContact)
|
|
|
|
details, _ := fs.GetString(FlagDetails)
|
2020-04-03 13:06:37 -07:00
|
|
|
description := types.NewDescription(
|
2020-07-08 13:00:34 -07:00
|
|
|
moniker,
|
|
|
|
identity,
|
|
|
|
website,
|
|
|
|
security,
|
|
|
|
details,
|
2020-04-03 13:06:37 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
// get the initial validator commission parameters
|
2020-07-08 13:00:34 -07:00
|
|
|
rateStr, _ := fs.GetString(FlagCommissionRate)
|
|
|
|
maxRateStr, _ := fs.GetString(FlagCommissionMaxRate)
|
|
|
|
maxChangeRateStr, _ := fs.GetString(FlagCommissionMaxChangeRate)
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-04-03 13:06:37 -07:00
|
|
|
commissionRates, err := buildCommissionRates(rateStr, maxRateStr, maxChangeRateStr)
|
|
|
|
if err != nil {
|
|
|
|
return txf, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the initial validator min self delegation
|
2020-07-08 13:00:34 -07:00
|
|
|
msbStr, _ := fs.GetString(FlagMinSelfDelegation)
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-04-03 13:06:37 -07:00
|
|
|
minSelfDelegation, ok := sdk.NewIntFromString(msbStr)
|
|
|
|
if !ok {
|
|
|
|
return txf, nil, types.ErrMinSelfDelegationInvalid
|
|
|
|
}
|
|
|
|
|
2020-10-19 06:04:55 -07:00
|
|
|
msg, err := types.NewMsgCreateValidator(
|
2020-04-03 13:06:37 -07:00
|
|
|
sdk.ValAddress(valAddr), pk, amount, description, commissionRates, minSelfDelegation,
|
|
|
|
)
|
2020-10-19 06:04:55 -07:00
|
|
|
if err != nil {
|
|
|
|
return txf, nil, err
|
|
|
|
}
|
2020-04-09 07:00:10 -07:00
|
|
|
if err := msg.ValidateBasic(); err != nil {
|
|
|
|
return txf, nil, err
|
|
|
|
}
|
2020-04-03 13:06:37 -07:00
|
|
|
|
2020-07-08 13:00:34 -07:00
|
|
|
genOnly, _ := fs.GetBool(flags.FlagGenerateOnly)
|
|
|
|
if genOnly {
|
|
|
|
ip, _ := fs.GetString(FlagIP)
|
|
|
|
nodeID, _ := fs.GetString(FlagNodeID)
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-04-03 13:06:37 -07:00
|
|
|
if nodeID != "" && ip != "" {
|
|
|
|
txf = txf.WithMemo(fmt.Sprintf("%s@%s:26656", nodeID, ip))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return txf, msg, nil
|
|
|
|
}
|
2019-05-28 01:44:04 -07:00
|
|
|
|
|
|
|
// Return the flagset, particular flags, and a description of defaults
|
|
|
|
// this is anticipated to be used with the gen-tx
|
2020-07-06 14:48:54 -07:00
|
|
|
func CreateValidatorMsgFlagSet(ipDefault string) (fs *flag.FlagSet, defaultsDesc string) {
|
2019-05-28 01:44:04 -07:00
|
|
|
fsCreateValidator := flag.NewFlagSet("", flag.ContinueOnError)
|
|
|
|
fsCreateValidator.String(FlagIP, ipDefault, "The node's public IP")
|
|
|
|
fsCreateValidator.String(FlagNodeID, "", "The node's NodeID")
|
2020-07-08 10:57:45 -07:00
|
|
|
fsCreateValidator.String(FlagMoniker, "", "The validator's (optional) moniker")
|
2019-05-28 01:44:04 -07:00
|
|
|
fsCreateValidator.String(FlagWebsite, "", "The validator's (optional) website")
|
2019-08-12 06:10:16 -07:00
|
|
|
fsCreateValidator.String(FlagSecurityContact, "", "The validator's (optional) security contact email")
|
2019-05-28 01:44:04 -07:00
|
|
|
fsCreateValidator.String(FlagDetails, "", "The validator's (optional) details")
|
|
|
|
fsCreateValidator.String(FlagIdentity, "", "The (optional) identity signature (ex. UPort or Keybase)")
|
2020-07-06 14:48:54 -07:00
|
|
|
fsCreateValidator.AddFlagSet(FlagSetCommissionCreate())
|
|
|
|
fsCreateValidator.AddFlagSet(FlagSetMinSelfDelegation())
|
|
|
|
fsCreateValidator.AddFlagSet(FlagSetAmount())
|
|
|
|
fsCreateValidator.AddFlagSet(FlagSetPublicKey())
|
2019-05-28 01:44:04 -07:00
|
|
|
|
|
|
|
defaultsDesc = fmt.Sprintf(`
|
|
|
|
delegation amount: %s
|
|
|
|
commission rate: %s
|
|
|
|
commission max rate: %s
|
|
|
|
commission max change rate: %s
|
|
|
|
minimum self delegation: %s
|
|
|
|
`, defaultAmount, defaultCommissionRate,
|
|
|
|
defaultCommissionMaxRate, defaultCommissionMaxChangeRate,
|
|
|
|
defaultMinSelfDelegation)
|
|
|
|
|
2020-07-06 14:48:54 -07:00
|
|
|
return fsCreateValidator, defaultsDesc
|
2019-05-28 01:44:04 -07:00
|
|
|
}
|
|
|
|
|
2020-07-06 14:48:54 -07:00
|
|
|
type TxCreateValidatorConfig struct {
|
|
|
|
ChainID string
|
|
|
|
NodeID string
|
|
|
|
Moniker string
|
|
|
|
|
|
|
|
Amount string
|
|
|
|
|
|
|
|
CommissionRate string
|
|
|
|
CommissionMaxRate string
|
|
|
|
CommissionMaxChangeRate string
|
|
|
|
MinSelfDelegation string
|
|
|
|
|
2020-07-22 23:44:18 -07:00
|
|
|
PubKey string
|
2020-07-06 14:48:54 -07:00
|
|
|
|
|
|
|
IP string
|
|
|
|
Website string
|
|
|
|
SecurityContact string
|
|
|
|
Details string
|
|
|
|
Identity string
|
|
|
|
}
|
|
|
|
|
2020-07-08 10:57:45 -07:00
|
|
|
func PrepareConfigForTxCreateValidator(flagSet *flag.FlagSet, moniker, nodeID, chainID string, valPubKey crypto.PubKey) (TxCreateValidatorConfig, error) {
|
2020-07-06 14:48:54 -07:00
|
|
|
c := TxCreateValidatorConfig{}
|
|
|
|
|
|
|
|
ip, err := flagSet.GetString(FlagIP)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
2019-05-28 01:44:04 -07:00
|
|
|
if ip == "" {
|
2020-05-02 12:26:59 -07:00
|
|
|
_, _ = fmt.Fprintf(os.Stderr, "couldn't retrieve an external IP; "+
|
2019-05-28 01:44:04 -07:00
|
|
|
"the tx's memo field will be unset")
|
|
|
|
}
|
2020-07-06 14:48:54 -07:00
|
|
|
c.IP = ip
|
|
|
|
|
|
|
|
website, err := flagSet.GetString(FlagWebsite)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
|
|
|
c.Website = website
|
|
|
|
|
|
|
|
securityContact, err := flagSet.GetString(FlagSecurityContact)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
|
|
|
c.SecurityContact = securityContact
|
|
|
|
|
|
|
|
details, err := flagSet.GetString(FlagDetails)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
|
|
|
c.SecurityContact = details
|
|
|
|
|
|
|
|
identity, err := flagSet.GetString(FlagIdentity)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
|
|
|
c.Identity = identity
|
|
|
|
|
|
|
|
c.Amount, err = flagSet.GetString(FlagAmount)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
2019-05-28 01:44:04 -07:00
|
|
|
|
2020-07-06 14:48:54 -07:00
|
|
|
c.CommissionRate, err = flagSet.GetString(FlagCommissionRate)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
2019-05-28 01:44:04 -07:00
|
|
|
|
2020-07-06 14:48:54 -07:00
|
|
|
c.CommissionMaxRate, err = flagSet.GetString(FlagCommissionMaxRate)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
|
|
|
|
|
|
|
c.CommissionMaxChangeRate, err = flagSet.GetString(FlagCommissionMaxChangeRate)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
|
|
|
|
|
|
|
c.MinSelfDelegation, err = flagSet.GetString(FlagMinSelfDelegation)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
|
|
|
|
|
|
|
c.NodeID = nodeID
|
|
|
|
c.PubKey = sdk.MustBech32ifyPubKey(sdk.Bech32PubKeyTypeConsPub, valPubKey)
|
|
|
|
c.Website = website
|
|
|
|
c.SecurityContact = securityContact
|
|
|
|
c.Details = details
|
|
|
|
c.Identity = identity
|
2020-07-08 10:57:45 -07:00
|
|
|
c.ChainID = chainID
|
|
|
|
c.Moniker = moniker
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-07-06 14:48:54 -07:00
|
|
|
if c.Amount == "" {
|
|
|
|
c.Amount = defaultAmount
|
2019-05-28 01:44:04 -07:00
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-07-06 14:48:54 -07:00
|
|
|
if c.CommissionRate == "" {
|
|
|
|
c.CommissionRate = defaultCommissionRate
|
2019-05-28 01:44:04 -07:00
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-07-06 14:48:54 -07:00
|
|
|
if c.CommissionMaxRate == "" {
|
|
|
|
c.CommissionMaxRate = defaultCommissionMaxRate
|
2019-05-28 01:44:04 -07:00
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-07-06 14:48:54 -07:00
|
|
|
if c.CommissionMaxChangeRate == "" {
|
|
|
|
c.CommissionMaxChangeRate = defaultCommissionMaxChangeRate
|
2019-05-28 01:44:04 -07:00
|
|
|
}
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2020-07-06 14:48:54 -07:00
|
|
|
if c.MinSelfDelegation == "" {
|
|
|
|
c.MinSelfDelegation = defaultMinSelfDelegation
|
2019-05-28 01:44:04 -07:00
|
|
|
}
|
2020-07-06 14:48:54 -07:00
|
|
|
|
|
|
|
return c, nil
|
2019-05-28 01:44:04 -07:00
|
|
|
}
|
|
|
|
|
2018-11-21 15:44:13 -08:00
|
|
|
// BuildCreateValidatorMsg makes a new MsgCreateValidator.
|
2020-07-29 15:33:42 -07:00
|
|
|
func BuildCreateValidatorMsg(clientCtx client.Context, config TxCreateValidatorConfig, txBldr tx.Factory, generateOnly bool) (tx.Factory, sdk.Msg, error) {
|
2020-07-06 14:48:54 -07:00
|
|
|
amounstStr := config.Amount
|
2018-11-21 15:44:13 -08:00
|
|
|
amount, err := sdk.ParseCoin(amounstStr)
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2018-11-21 15:44:13 -08:00
|
|
|
if err != nil {
|
2019-01-03 15:28:55 -08:00
|
|
|
return txBldr, nil, err
|
2018-11-21 15:44:13 -08:00
|
|
|
}
|
|
|
|
|
2020-06-01 05:46:03 -07:00
|
|
|
valAddr := clientCtx.GetFromAddress()
|
2020-07-06 14:48:54 -07:00
|
|
|
pkStr := config.PubKey
|
2019-01-29 11:22:47 -08:00
|
|
|
|
2020-01-09 06:04:28 -08:00
|
|
|
pk, err := sdk.GetPubKeyFromBech32(sdk.Bech32PubKeyTypeConsPub, pkStr)
|
2018-11-21 15:44:13 -08:00
|
|
|
if err != nil {
|
2019-01-03 15:28:55 -08:00
|
|
|
return txBldr, nil, err
|
2018-11-21 15:44:13 -08:00
|
|
|
}
|
|
|
|
|
2019-05-28 01:44:04 -07:00
|
|
|
description := types.NewDescription(
|
2020-07-06 14:48:54 -07:00
|
|
|
config.Moniker,
|
|
|
|
config.Identity,
|
|
|
|
config.Website,
|
|
|
|
config.SecurityContact,
|
|
|
|
config.Details,
|
2018-11-21 15:44:13 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
// get the initial validator commission parameters
|
2020-07-06 14:48:54 -07:00
|
|
|
rateStr := config.CommissionRate
|
|
|
|
maxRateStr := config.CommissionMaxRate
|
|
|
|
maxChangeRateStr := config.CommissionMaxChangeRate
|
2019-06-03 14:14:21 -07:00
|
|
|
commissionRates, err := buildCommissionRates(rateStr, maxRateStr, maxChangeRateStr)
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2018-11-21 15:44:13 -08:00
|
|
|
if err != nil {
|
2019-01-03 15:28:55 -08:00
|
|
|
return txBldr, nil, err
|
2018-11-21 15:44:13 -08:00
|
|
|
}
|
|
|
|
|
2019-02-08 12:44:19 -08:00
|
|
|
// get the initial validator min self delegation
|
2020-07-06 14:48:54 -07:00
|
|
|
msbStr := config.MinSelfDelegation
|
2019-02-08 12:44:19 -08:00
|
|
|
minSelfDelegation, ok := sdk.NewIntFromString(msbStr)
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2019-02-08 12:44:19 -08:00
|
|
|
if !ok {
|
2019-12-27 09:57:54 -08:00
|
|
|
return txBldr, nil, types.ErrMinSelfDelegationInvalid
|
2019-02-08 12:44:19 -08:00
|
|
|
}
|
|
|
|
|
2020-10-19 06:04:55 -07:00
|
|
|
msg, err := types.NewMsgCreateValidator(
|
2019-06-03 14:14:21 -07:00
|
|
|
sdk.ValAddress(valAddr), pk, amount, description, commissionRates, minSelfDelegation,
|
2019-03-05 08:55:46 -08:00
|
|
|
)
|
2020-10-19 06:04:55 -07:00
|
|
|
if err != nil {
|
|
|
|
return txBldr, msg, err
|
|
|
|
}
|
2020-07-06 14:48:54 -07:00
|
|
|
if generateOnly {
|
|
|
|
ip := config.IP
|
|
|
|
nodeID := config.NodeID
|
2020-05-02 12:26:59 -07:00
|
|
|
|
2018-11-21 15:44:13 -08:00
|
|
|
if nodeID != "" && ip != "" {
|
|
|
|
txBldr = txBldr.WithMemo(fmt.Sprintf("%s@%s:26656", nodeID, ip))
|
|
|
|
}
|
|
|
|
}
|
2019-03-05 08:55:46 -08:00
|
|
|
|
2019-01-03 15:28:55 -08:00
|
|
|
return txBldr, msg, nil
|
2018-11-21 15:44:13 -08:00
|
|
|
}
|