Skip to content

Commit

Permalink
Merge pull request #2 from pomifer/lydia/backport-min-commish
Browse files Browse the repository at this point in the history
feat: Backport minimum commission to v0.45.0
  • Loading branch information
evan-forbes authored Mar 2, 2022
2 parents 12fffc1 + 81092fc commit b734178
Show file tree
Hide file tree
Showing 17 changed files with 894 additions and 743 deletions.
1 change: 1 addition & 0 deletions docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -6433,6 +6433,7 @@ Params defines the parameters for the staking module.
| `max_entries` | [uint32](#uint32) | | max_entries is the max entries for either unbonding delegation or redelegation (per pair/trio). |
| `historical_entries` | [uint32](#uint32) | | historical_entries is the number of historical entries to persist. |
| `bond_denom` | [string](#string) | | bond_denom defines the bondable coin denomination. |
| `min_commission_rate` | [string](#string) | | min_commission_rate is the chain-wide minimum commission rate that a validator can charge their delegators |



Expand Down
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ require (
github.com/coinbase/rosetta-sdk-go v0.7.0
github.com/confio/ics23/go v0.6.6
github.com/cosmos/btcutil v1.0.4
github.com/cosmos/cosmos-proto v1.0.0-alpha7
github.com/cosmos/cosmos-sdk/api v0.1.0-alpha4
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/iavl v0.17.3
github.com/cosmos/ledger-cosmos-go v0.11.1
github.com/gogo/gateway v1.1.0
github.com/gogo/protobuf v1.3.3
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.2
github.com/google/go-cmp v0.5.6 // indirect
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
Expand Down
5 changes: 0 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,6 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44=
github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU=
github.com/cosmos/cosmos-proto v1.0.0-alpha7 h1:yqYUOHF2jopwZh4dVQp3xgqwftE5/2hkrwIV6vkUbO0=
github.com/cosmos/cosmos-proto v1.0.0-alpha7/go.mod h1:dosO4pSAbJF8zWCzCoTWP7nNsjcvSUBQmniFxDg5daw=
github.com/cosmos/cosmos-sdk/api v0.1.0-alpha4 h1:z2si9sQNUTj2jw+24SujuUxcoNS3TVga/fdYsS4rJII=
github.com/cosmos/cosmos-sdk/api v0.1.0-alpha4/go.mod h1:gZu6sOu2vl4Fd7I+BjDSx2bxndwPgFLGfOegek3SQQo=
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY=
github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw=
Expand Down Expand Up @@ -1293,7 +1289,6 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down
8 changes: 7 additions & 1 deletion proto/cosmos/staking/v1beta1/staking.proto
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,13 @@ message Params {
// historical_entries is the number of historical entries to persist.
uint32 historical_entries = 4 [(gogoproto.moretags) = "yaml:\"historical_entries\""];
// bond_denom defines the bondable coin denomination.
string bond_denom = 5 [(gogoproto.moretags) = "yaml:\"bond_denom\""];
string bond_denom = 5;
// min_commission_rate is the chain-wide minimum commission rate that a validator can charge their delegators
string min_commission_rate = 6 [
(gogoproto.moretags) = "yaml:\"min_commission_rate\"",
(gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec",
(gogoproto.nullable) = false
];
}

// DelegationResponse is equivalent to Delegation except that it contains a
Expand Down
3 changes: 2 additions & 1 deletion x/staking/client/testutil/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -876,12 +876,13 @@ func (s *IntegrationTestSuite) TestGetCmdQueryParams() {
historical_entries: 10000
max_entries: 7
max_validators: 100
min_commission_rate: "0.000000000000000000"
unbonding_time: 1814400s`,
},
{
"with json output",
[]string{fmt.Sprintf("--%s=json", tmcli.OutputFlag)},
`{"unbonding_time":"1814400s","max_validators":100,"max_entries":7,"historical_entries":10000,"bond_denom":"stake"}`,
`{"unbonding_time":"1814400s","max_validators":100,"max_entries":7,"historical_entries":10000,"bond_denom":"stake","min_commission_rate":"0.000000000000000000"}`,
},
}
for _, tc := range testCases {
Expand Down
6 changes: 6 additions & 0 deletions x/staking/keeper/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package keeper
import (
sdk "github.com/cosmos/cosmos-sdk/types"
v043 "github.com/cosmos/cosmos-sdk/x/staking/legacy/v043"
v045 "github.com/cosmos/cosmos-sdk/x/staking/migrations/v045"
)

// Migrator is a struct for handling in-place store migrations.
Expand All @@ -19,3 +20,8 @@ func NewMigrator(keeper Keeper) Migrator {
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
return v043.MigrateStore(ctx, m.keeper.storeKey)
}

// Migrate2to3 migrates x/staking state from consensus version 2 to 3.
func (m Migrator) Migrate2to3(ctx sdk.Context) error {
return v045.MigrateStore(ctx, m.keeper.storeKey, m.keeper.cdc, m.keeper.paramstore)
}
5 changes: 5 additions & 0 deletions x/staking/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
return nil, err
}

if msg.Commission.Rate.LT(k.MinCommissionRate(ctx)) {
return nil, sdkerrors.Wrapf(types.ErrCommissionLTMinRate, "cannot set validator commission to less than minimum rate of %s", k.MinCommissionRate(ctx))
}

// check to see if the pubkey or sender has been registered before
if _, found := k.GetValidator(ctx, valAddr); found {
return nil, types.ErrValidatorOwnerExists
Expand Down Expand Up @@ -74,6 +78,7 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa
if err != nil {
return nil, err
}

commission := types.NewCommissionWithTime(
msg.Commission.Rate, msg.Commission.MaxRate,
msg.Commission.MaxChangeRate, ctx.BlockHeader().Time,
Expand Down
9 changes: 8 additions & 1 deletion x/staking/keeper/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,21 @@ func (k Keeper) PowerReduction(ctx sdk.Context) sdk.Int {
return sdk.DefaultPowerReduction
}

// Get all parameteras as types.Params
// MinCommissionRate - Minimum validator commission rate
func (k Keeper) MinCommissionRate(ctx sdk.Context) (res sdk.Dec) {
k.paramstore.Get(ctx, types.KeyMinCommissionRate, &res)
return
}

// Get all parameters as types.Params
func (k Keeper) GetParams(ctx sdk.Context) types.Params {
return types.NewParams(
k.UnbondingTime(ctx),
k.MaxValidators(ctx),
k.MaxEntries(ctx),
k.HistoricalEntries(ctx),
k.BondDenom(ctx),
k.MinCommissionRate(ctx),
)
}

Expand Down
4 changes: 4 additions & 0 deletions x/staking/keeper/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ func (k Keeper) UpdateValidatorCommission(ctx sdk.Context,
return commission, err
}

if newRate.LT(k.MinCommissionRate(ctx)) {
return commission, fmt.Errorf("cannot set validator commission to less than minimum rate of %s", k.MinCommissionRate(ctx))
}

commission.Rate = newRate
commission.UpdateTime = blockTime

Expand Down
6 changes: 6 additions & 0 deletions x/staking/keeper/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,11 @@ func TestUpdateValidatorCommission(t *testing.T) {
app, ctx, _, addrVals := bootstrapValidatorTest(t, 1000, 20)
ctx = ctx.WithBlockHeader(tmproto.Header{Time: time.Now().UTC()})

// Set MinCommissionRate to 0.05
params := app.StakingKeeper.GetParams(ctx)
params.MinCommissionRate = sdk.NewDecWithPrec(5, 2)
app.StakingKeeper.SetParams(ctx, params)

commission1 := types.NewCommissionWithTime(
sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(3, 1),
sdk.NewDecWithPrec(1, 1), time.Now().UTC().Add(time.Duration(-1)*time.Hour),
Expand All @@ -1065,6 +1070,7 @@ func TestUpdateValidatorCommission(t *testing.T) {
{val2, sdk.NewDecWithPrec(-1, 1), true},
{val2, sdk.NewDecWithPrec(4, 1), true},
{val2, sdk.NewDecWithPrec(3, 1), true},
{val2, sdk.NewDecWithPrec(1, 2), true},
{val2, sdk.NewDecWithPrec(2, 1), false},
}

Expand Down
24 changes: 24 additions & 0 deletions x/staking/migrations/v045/store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package v045

import (
"github.com/cosmos/cosmos-sdk/codec"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)

// MigrateStore performs in-place store migrations from v0.43/v0.44 to v0.45.
// The migration includes:
//
// - Setting the MinCommissionRate param in the paramstore
func MigrateStore(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.BinaryCodec, paramstore paramtypes.Subspace) error {
migrateParamsStore(ctx, paramstore)

return nil
}

func migrateParamsStore(ctx sdk.Context, paramstore paramtypes.Subspace) {
paramstore.WithKeyTable(types.ParamKeyTable())
paramstore.Set(ctx, types.KeyMinCommissionRate, types.DefaultMinCommissionRate)
}
9 changes: 5 additions & 4 deletions x/staking/simulation/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ func getHistEntries(r *rand.Rand) uint32 {
func RandomizedGenState(simState *module.SimulationState) {
// params
var (
unbondTime time.Duration
maxVals uint32
histEntries uint32
unbondTime time.Duration
maxVals uint32
histEntries uint32
minCommissionRate sdk.Dec
)

simState.AppParams.GetOrGenerate(
Expand All @@ -63,7 +64,7 @@ func RandomizedGenState(simState *module.SimulationState) {
// NOTE: the slashing module need to be defined after the staking module on the
// NewSimulationManager constructor for this to work
simState.UnbondTime = unbondTime
params := types.NewParams(simState.UnbondTime, maxVals, 7, histEntries, sdk.DefaultBondDenom)
params := types.NewParams(simState.UnbondTime, maxVals, 7, histEntries, sdk.DefaultBondDenom, minCommissionRate)

// validators & delegations
var (
Expand Down
16 changes: 8 additions & 8 deletions x/staking/spec/08_params.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ order: 8

The staking module contains the following parameters:

| Key | Type | Example |
|-------------------|------------------|-------------------|
| UnbondingTime | string (time ns) | "259200000000000" |
| MaxValidators | uint16 | 100 |
| KeyMaxEntries | uint16 | 7 |
| HistoricalEntries | uint16 | 3 |
| BondDenom | string | "stake" |
| PowerReduction | string | "1000000" |
| Key | Type | Example |
|-------------------|------------------|------------------------|
| UnbondingTime | string (time ns) | "259200000000000" |
| MaxValidators | uint16 | 100 |
| KeyMaxEntries | uint16 | 7 |
| HistoricalEntries | uint16 | 3 |
| BondDenom | string | "stake" |
| MinCommissionRate | string | "0.000000000000000000" |
1 change: 1 addition & 0 deletions x/staking/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ var (
ErrInvalidHistoricalInfo = sdkerrors.Register(ModuleName, 37, "invalid historical info")
ErrNoHistoricalInfo = sdkerrors.Register(ModuleName, 38, "no historical info found")
ErrEmptyValidatorPubKey = sdkerrors.Register(ModuleName, 39, "empty validator public key")
ErrCommissionLTMinRate = sdkerrors.Register(ModuleName, 40, "commission cannot be less than min rate")
)
32 changes: 30 additions & 2 deletions x/staking/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,18 @@ const (
DefaultHistoricalEntries uint32 = 10000
)

var (
// DefaultMinCommissionRate is set to 0%
DefaultMinCommissionRate = sdk.ZeroDec()
)

var (
KeyUnbondingTime = []byte("UnbondingTime")
KeyMaxValidators = []byte("MaxValidators")
KeyMaxEntries = []byte("MaxEntries")
KeyBondDenom = []byte("BondDenom")
KeyHistoricalEntries = []byte("HistoricalEntries")
KeyPowerReduction = []byte("PowerReduction")
KeyMinCommissionRate = []byte("MinCommissionRate")
)

var _ paramtypes.ParamSet = (*Params)(nil)
Expand All @@ -49,13 +54,14 @@ func ParamKeyTable() paramtypes.KeyTable {
}

// NewParams creates a new Params instance
func NewParams(unbondingTime time.Duration, maxValidators, maxEntries, historicalEntries uint32, bondDenom string) Params {
func NewParams(unbondingTime time.Duration, maxValidators, maxEntries, historicalEntries uint32, bondDenom string, minCommissionRate sdk.Dec) Params {
return Params{
UnbondingTime: unbondingTime,
MaxValidators: maxValidators,
MaxEntries: maxEntries,
HistoricalEntries: historicalEntries,
BondDenom: bondDenom,
MinCommissionRate: minCommissionRate,
}
}

Expand All @@ -67,6 +73,7 @@ func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs {
paramtypes.NewParamSetPair(KeyMaxEntries, &p.MaxEntries, validateMaxEntries),
paramtypes.NewParamSetPair(KeyHistoricalEntries, &p.HistoricalEntries, validateHistoricalEntries),
paramtypes.NewParamSetPair(KeyBondDenom, &p.BondDenom, validateBondDenom),
paramtypes.NewParamSetPair(KeyMinCommissionRate, &p.MinCommissionRate, validateMinCommissionRate),
}
}

Expand All @@ -78,6 +85,7 @@ func DefaultParams() Params {
DefaultMaxEntries,
DefaultHistoricalEntries,
sdk.DefaultBondDenom,
DefaultMinCommissionRate,
)
}

Expand Down Expand Up @@ -125,6 +133,10 @@ func (p Params) Validate() error {
return err
}

if err := validateMinCommissionRate(p.MinCommissionRate); err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -205,3 +217,19 @@ func ValidatePowerReduction(i interface{}) error {

return nil
}

func validateMinCommissionRate(i interface{}) error {
v, ok := i.(sdk.Dec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}

if v.IsNegative() {
return fmt.Errorf("minimum commission rate cannot be negative: %s", v)
}
if v.GT(sdk.OneDec()) {
return fmt.Errorf("minimum commission rate cannot be greater than 100%%: %s", v)
}

return nil
}
15 changes: 15 additions & 0 deletions x/staking/types/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/staking/types"
)

Expand All @@ -21,3 +22,17 @@ func TestParamsEqual(t *testing.T) {
ok = p1.Equal(p2)
require.False(t, ok)
}

func Test_validateParams(t *testing.T) {
params := types.DefaultParams()

// default params have no error
require.NoError(t, params.Validate())

// validate mincommision
params.MinCommissionRate = sdk.NewDec(-1)
require.Error(t, params.Validate())

params.MinCommissionRate = sdk.NewDec(2)
require.Error(t, params.Validate())
}
Loading

0 comments on commit b734178

Please sign in to comment.