Merge PR #2365: Validator Commission Model
* Update validator commission fields * Remove CommissionChangeToday and update to use CommissionChangeTime * Implement commission as a first class citizen type * Implement stringer for Comission * Move commission type and logic to new file * Add new commission errors * Add commission to create validator message * Implement and call UpdateValidatorCommission * Update godoc for UpdateValidatorCommission * Add Abs to the decimal type * Implement new SetValidatorCommission * Update decimal short godocs * Move set initial commission logic * Move initial commission validation to Commission type * Update initial validator commission logic and unit tests * Remove commission update time from struct and move to validator * Update validator create handler tests * Implement commission logic for CLI * Fix make lint failure * Fix make cover failure * Update edit validator logic to handle new commission rate * Fix lint and cover * Update create/edit validator simulation to include commission params * Update MsgEditValidator godoc * Update pending log * Update staking tx docs * Fix CLI create validator test * Update variables names for commission strings * Merge UpdateTime into Commission type * Update create-validator usage in docs * Update more docs with examples * More doc updates
This commit is contained in:
committed by
Rigel
parent
8774adc7de
commit
9dafa3252d
@@ -21,6 +21,10 @@ const (
|
||||
FlagIdentity = "identity"
|
||||
FlagWebsite = "website"
|
||||
FlagDetails = "details"
|
||||
|
||||
FlagCommissionRate = "commission-rate"
|
||||
FlagCommissionMaxRate = "commission-max-rate"
|
||||
FlagCommissionMaxChangeRate = "commission-max-change-rate"
|
||||
)
|
||||
|
||||
// common flagsets to add to various functions
|
||||
@@ -29,6 +33,8 @@ var (
|
||||
fsAmount = flag.NewFlagSet("", flag.ContinueOnError)
|
||||
fsShares = flag.NewFlagSet("", flag.ContinueOnError)
|
||||
fsDescriptionCreate = flag.NewFlagSet("", flag.ContinueOnError)
|
||||
fsCommissionCreate = flag.NewFlagSet("", flag.ContinueOnError)
|
||||
fsCommissionUpdate = flag.NewFlagSet("", flag.ContinueOnError)
|
||||
fsDescriptionEdit = flag.NewFlagSet("", flag.ContinueOnError)
|
||||
fsValidator = flag.NewFlagSet("", flag.ContinueOnError)
|
||||
fsDelegator = flag.NewFlagSet("", flag.ContinueOnError)
|
||||
@@ -44,6 +50,10 @@ func init() {
|
||||
fsDescriptionCreate.String(FlagIdentity, "", "optional identity signature (ex. UPort or Keybase)")
|
||||
fsDescriptionCreate.String(FlagWebsite, "", "optional website")
|
||||
fsDescriptionCreate.String(FlagDetails, "", "optional details")
|
||||
fsCommissionUpdate.String(FlagCommissionRate, "", "The new commission rate percentage")
|
||||
fsCommissionCreate.String(FlagCommissionRate, "", "The initial commission rate percentage")
|
||||
fsCommissionCreate.String(FlagCommissionMaxRate, "", "The maximum commission rate percentage")
|
||||
fsCommissionCreate.String(FlagCommissionMaxChangeRate, "", "The maximum commission change rate percentage (per day)")
|
||||
fsDescriptionEdit.String(FlagMoniker, types.DoNotModifyDesc, "validator name")
|
||||
fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)")
|
||||
fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website")
|
||||
|
||||
+33
-53
@@ -12,9 +12,7 @@ import (
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
@@ -66,6 +64,15 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command {
|
||||
Details: viper.GetString(FlagDetails),
|
||||
}
|
||||
|
||||
// get the initial validator commission parameters
|
||||
rateStr := viper.GetString(FlagCommissionRate)
|
||||
maxRateStr := viper.GetString(FlagCommissionMaxRate)
|
||||
maxChangeRateStr := viper.GetString(FlagCommissionMaxChangeRate)
|
||||
commissionMsg, err := buildCommissionMsg(rateStr, maxRateStr, maxChangeRateStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var msg sdk.Msg
|
||||
if viper.GetString(FlagAddressDelegator) != "" {
|
||||
delAddr, err := sdk.AccAddressFromBech32(viper.GetString(FlagAddressDelegator))
|
||||
@@ -73,13 +80,19 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command {
|
||||
return err
|
||||
}
|
||||
|
||||
msg = stake.NewMsgCreateValidatorOnBehalfOf(delAddr, sdk.ValAddress(valAddr), pk, amount, description)
|
||||
msg = stake.NewMsgCreateValidatorOnBehalfOf(
|
||||
delAddr, sdk.ValAddress(valAddr), pk, amount, description, commissionMsg,
|
||||
)
|
||||
} else {
|
||||
msg = stake.NewMsgCreateValidator(sdk.ValAddress(valAddr), pk, amount, description)
|
||||
msg = stake.NewMsgCreateValidator(
|
||||
sdk.ValAddress(valAddr), pk, amount, description, commissionMsg,
|
||||
)
|
||||
}
|
||||
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
}
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
@@ -88,6 +101,7 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command {
|
||||
cmd.Flags().AddFlagSet(fsPk)
|
||||
cmd.Flags().AddFlagSet(fsAmount)
|
||||
cmd.Flags().AddFlagSet(fsDescriptionCreate)
|
||||
cmd.Flags().AddFlagSet(fsCommissionCreate)
|
||||
cmd.Flags().AddFlagSet(fsDelegator)
|
||||
|
||||
return cmd
|
||||
@@ -117,17 +131,31 @@ func GetCmdEditValidator(cdc *codec.Codec) *cobra.Command {
|
||||
Details: viper.GetString(FlagDetails),
|
||||
}
|
||||
|
||||
msg := stake.NewMsgEditValidator(sdk.ValAddress(valAddr), description)
|
||||
var newRate *sdk.Dec
|
||||
|
||||
commissionRate := viper.GetString(FlagCommissionRate)
|
||||
if commissionRate != "" {
|
||||
rate, err := sdk.NewDecFromStr(commissionRate)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid new commission rate: %v", err)
|
||||
}
|
||||
|
||||
newRate = &rate
|
||||
}
|
||||
|
||||
msg := stake.NewMsgEditValidator(sdk.ValAddress(valAddr), description, newRate)
|
||||
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
}
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.SendTx(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().AddFlagSet(fsDescriptionEdit)
|
||||
cmd.Flags().AddFlagSet(fsCommissionUpdate)
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -247,54 +275,6 @@ func GetCmdBeginRedelegate(storeName string, cdc *codec.Codec) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
// TODO: Make this pass gocyclo linting
|
||||
func getShares(
|
||||
storeName string, cdc *codec.Codec, sharesAmountStr,
|
||||
sharesPercentStr string, delAddr sdk.AccAddress, valAddr sdk.ValAddress,
|
||||
) (sharesAmount sdk.Dec, err error) {
|
||||
switch {
|
||||
case sharesAmountStr != "" && sharesPercentStr != "":
|
||||
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
|
||||
case sharesAmountStr == "" && sharesPercentStr == "":
|
||||
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
|
||||
case sharesAmountStr != "":
|
||||
sharesAmount, err = sdk.NewDecFromStr(sharesAmountStr)
|
||||
if err != nil {
|
||||
return sharesAmount, err
|
||||
}
|
||||
if !sharesAmount.GT(sdk.ZeroDec()) {
|
||||
return sharesAmount, errors.Errorf("shares amount must be positive number (ex. 123, 1.23456789)")
|
||||
}
|
||||
case sharesPercentStr != "":
|
||||
var sharesPercent sdk.Dec
|
||||
sharesPercent, err = sdk.NewDecFromStr(sharesPercentStr)
|
||||
if err != nil {
|
||||
return sharesAmount, err
|
||||
}
|
||||
if !sharesPercent.GT(sdk.ZeroDec()) || !sharesPercent.LTE(sdk.OneDec()) {
|
||||
return sharesAmount, errors.Errorf("shares percent must be >0 and <=1 (ex. 0.01, 0.75, 1)")
|
||||
}
|
||||
|
||||
// make a query to get the existing delegation shares
|
||||
key := stake.GetDelegationKey(delAddr, valAddr)
|
||||
cliCtx := context.NewCLIContext().
|
||||
WithCodec(cdc).
|
||||
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
|
||||
|
||||
resQuery, err := cliCtx.QueryStore(key, storeName)
|
||||
if err != nil {
|
||||
return sharesAmount, errors.Errorf("cannot find delegation to determine percent Error: %v", err)
|
||||
}
|
||||
delegation, err := types.UnmarshalDelegation(cdc, key, resQuery)
|
||||
if err != nil {
|
||||
return sdk.ZeroDec(), err
|
||||
}
|
||||
sharesAmount = sharesPercent.Mul(delegation.Shares)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetCmdCompleteRedelegate implements the complete redelegation command.
|
||||
func GetCmdCompleteRedelegate(cdc *codec.Codec) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"github.com/cosmos/cosmos-sdk/client/context"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func getShares(
|
||||
storeName string, cdc *codec.Codec, sharesAmountStr,
|
||||
sharesPercentStr string, delAddr sdk.AccAddress, valAddr sdk.ValAddress,
|
||||
) (sharesAmount sdk.Dec, err error) {
|
||||
|
||||
switch {
|
||||
case sharesAmountStr != "" && sharesPercentStr != "":
|
||||
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
|
||||
|
||||
case sharesAmountStr == "" && sharesPercentStr == "":
|
||||
return sharesAmount, errors.Errorf("can either specify the amount OR the percent of the shares, not both")
|
||||
|
||||
case sharesAmountStr != "":
|
||||
sharesAmount, err = sdk.NewDecFromStr(sharesAmountStr)
|
||||
if err != nil {
|
||||
return sharesAmount, err
|
||||
}
|
||||
if !sharesAmount.GT(sdk.ZeroDec()) {
|
||||
return sharesAmount, errors.Errorf("shares amount must be positive number (ex. 123, 1.23456789)")
|
||||
}
|
||||
|
||||
case sharesPercentStr != "":
|
||||
var sharesPercent sdk.Dec
|
||||
sharesPercent, err = sdk.NewDecFromStr(sharesPercentStr)
|
||||
if err != nil {
|
||||
return sharesAmount, err
|
||||
}
|
||||
if !sharesPercent.GT(sdk.ZeroDec()) || !sharesPercent.LTE(sdk.OneDec()) {
|
||||
return sharesAmount, errors.Errorf("shares percent must be >0 and <=1 (ex. 0.01, 0.75, 1)")
|
||||
}
|
||||
|
||||
// make a query to get the existing delegation shares
|
||||
key := stake.GetDelegationKey(delAddr, valAddr)
|
||||
cliCtx := context.NewCLIContext().
|
||||
WithCodec(cdc).
|
||||
WithAccountDecoder(authcmd.GetAccountDecoder(cdc))
|
||||
|
||||
resQuery, err := cliCtx.QueryStore(key, storeName)
|
||||
if err != nil {
|
||||
return sharesAmount, errors.Errorf("cannot find delegation to determine percent Error: %v", err)
|
||||
}
|
||||
|
||||
delegation, err := types.UnmarshalDelegation(cdc, key, resQuery)
|
||||
if err != nil {
|
||||
return sdk.ZeroDec(), err
|
||||
}
|
||||
|
||||
sharesAmount = sharesPercent.Mul(delegation.Shares)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func buildCommissionMsg(rateStr, maxRateStr, maxChangeRateStr string) (commission types.CommissionMsg, err error) {
|
||||
if rateStr == "" || maxRateStr == "" || maxChangeRateStr == "" {
|
||||
return commission, errors.Errorf("must specify all validator commission parameters")
|
||||
}
|
||||
|
||||
rate, err := sdk.NewDecFromStr(rateStr)
|
||||
if err != nil {
|
||||
return commission, err
|
||||
}
|
||||
|
||||
maxRate, err := sdk.NewDecFromStr(maxRateStr)
|
||||
if err != nil {
|
||||
return commission, err
|
||||
}
|
||||
|
||||
maxChangeRate, err := sdk.NewDecFromStr(maxChangeRateStr)
|
||||
if err != nil {
|
||||
return commission, err
|
||||
}
|
||||
|
||||
commission = types.NewCommissionMsg(rate, maxRate, maxChangeRate)
|
||||
return commission, nil
|
||||
}
|
||||
Reference in New Issue
Block a user