diff --git a/baseapp/abci.go b/baseapp/abci.go index b934255da4..84a330c11e 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -60,7 +60,9 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC // add block gas meter for any genesis transactions (allow infinite gas) app.deliverState.ctx = app.deliverState.ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter()) + fmt.Println("abci.go - 63") res = app.initChainer(app.deliverState.ctx, req) + fmt.Println("abci.go - 65") // sanity check if len(req.Validators) > 0 { diff --git a/go.sum b/go.sum index 35ec958f0e..8759ca606e 100644 --- a/go.sum +++ b/go.sum @@ -309,6 +309,7 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/golangci-lint v1.48.0 h1:hRiBNk9iRqdAKMa06ntfEiLyza1/3IE9rHLNJaek4a8= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= diff --git a/proto/cosmos/staking/v1beta1/staking.proto b/proto/cosmos/staking/v1beta1/staking.proto index 76e9599e2d..04c9dcadc2 100644 --- a/proto/cosmos/staking/v1beta1/staking.proto +++ b/proto/cosmos/staking/v1beta1/staking.proto @@ -282,6 +282,11 @@ message Params { 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 min_commission_rate = 200 [ +// (gogoproto.moretags) = "yaml:\"min_commission_rate\"", +// (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", +// (gogoproto.nullable) = true +// ]; } // DelegationResponse is equivalent to Delegation except that it contains a diff --git a/simapp/app.go b/simapp/app.go index 16302ecc35..7224c6d3b0 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -2,6 +2,7 @@ package simapp import ( "encoding/json" + "fmt" "io" "net/http" "os" @@ -440,6 +441,7 @@ func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci. panic(err) } app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap()) + fmt.Println("app.go - 74") return app.mm.InitGenesis(ctx, app.appCodec, genesisState) } diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 7db09cee43..a992d987d3 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -297,7 +297,6 @@ func TestAppStateDeterminism(t *testing.T) { } else { logger = log.NewNopLogger() } - db := dbm.NewMemDB() app := NewSimApp(logger, db, nil, true, map[int64]bool{}, DefaultNodeHome, FlagPeriodValue, MakeTestEncodingConfig(), EmptyAppOptions{}, interBlockCacheOpt()) diff --git a/types/errors/errors.go b/types/errors/errors.go index 2c211f93d6..d1a12e949b 100644 --- a/types/errors/errors.go +++ b/types/errors/errors.go @@ -147,6 +147,8 @@ var ( // ErrPanic is only set when we recover from a panic, so we know to // redact potentially sensitive system info ErrPanic = Register(UndefinedCodespace, 111222, "panic") + + ErrInvalidCommission = Register(RootCodespace, 41, "invalid commission rate") ) // Register returns an error instance that should be used as the base for diff --git a/types/module/module.go b/types/module/module.go index 795553e78c..b63bb45654 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -324,8 +324,10 @@ func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData continue } + fmt.Println("module.go - 327") moduleValUpdates := m.Modules[moduleName].InitGenesis(ctx, cdc, genesisData[moduleName]) + fmt.Println("module.go - 330") // use these validator updates if provided, the module manager assumes // only one module will update the validator set if len(moduleValUpdates) > 0 { diff --git a/x/params/types/subspace.go b/x/params/types/subspace.go index 948d5f1c32..90f848d531 100644 --- a/x/params/types/subspace.go +++ b/x/params/types/subspace.go @@ -236,15 +236,19 @@ func (s Subspace) GetParamSetIfExists(ctx sdk.Context, ps ParamSet) { // corresponding parameter key in the Subspace's KVStore. func (s Subspace) SetParamSet(ctx sdk.Context, ps ParamSet) { for _, pair := range ps.ParamSetPairs() { + fmt.Println(pair.Key) // pair.Field is a pointer to the field, so indirecting the ptr. // go-amino automatically handles it but just for sure, // since SetStruct is meant to be used in InitGenesis // so this method will not be called frequently + fmt.Println("subspace.go - 243") v := reflect.Indirect(reflect.ValueOf(pair.Value)).Interface() + fmt.Println("subspace.go - 245") if err := pair.ValidatorFn(v); err != nil { panic(fmt.Sprintf("value from ParamSetPair is invalid: %s", err)) } + fmt.Println("subspace.go - 250") s.Set(ctx, pair.Key, v) } diff --git a/x/simulation/simulate.go b/x/simulation/simulate.go index 0bc17e07b9..a2f2469a0a 100644 --- a/x/simulation/simulate.go +++ b/x/simulation/simulate.go @@ -39,7 +39,9 @@ func initChain( ConsensusParams: consensusParams, Time: genesisTimestamp, } + fmt.Println("simulate.go - 42") res := app.InitChain(req) + fmt.Println("simulate.go - 44") validators := newMockValidators(r, res.Validators, params) return validators, genesisTimestamp, accounts, chainID @@ -67,9 +69,11 @@ func SimulateFromSeed( params := RandomParams(r) fmt.Fprintf(w, "Randomized simulation params: \n%s\n", mustMarshalJSONIndent(params)) + fmt.Println("simulate.go - 70") timeDiff := maxTimePerBlock - minTimePerBlock accs := randAccFn(r, params.NumKeys()) eventStats := NewEventStats() + fmt.Println("simulate.go - 74") // Second variable to keep pending validator set (delayed one block since // TM 0.24) Initially this is the same as the initial validator set @@ -77,6 +81,7 @@ func SimulateFromSeed( if len(accs) == 0 { return true, params, fmt.Errorf("must have greater than zero genesis accounts") } + fmt.Println("simulate.go - 82") config.ChainID = chainID diff --git a/x/staking/genesis.go b/x/staking/genesis.go index 51ae11a25f..564011772a 100644 --- a/x/staking/genesis.go +++ b/x/staking/genesis.go @@ -32,8 +32,11 @@ func InitGenesis( // genesis.json are in block 0. ctx = ctx.WithBlockHeight(1 - sdk.ValidatorUpdateDelay) + fmt.Println("staking/genesis.go - 35") keeper.SetParams(ctx, data.Params) + fmt.Println("staking/genesis.go - 37") keeper.SetLastTotalPower(ctx, data.LastTotalPower) + fmt.Println("staking/genesis.go - 39") for _, validator := range data.Validators { keeper.SetValidator(ctx, validator) @@ -61,6 +64,7 @@ func InitGenesis( panic("invalid validator status") } } + fmt.Println("staking/genesis.go - 67") for _, delegation := range data.Delegations { delegatorAddress := sdk.MustAccAddressFromBech32(delegation.DelegatorAddress) @@ -76,6 +80,7 @@ func InitGenesis( keeper.AfterDelegationModified(ctx, delegatorAddress, delegation.GetValidatorAddr()) } } + fmt.Println("staking/genesis.go - 83") for _, ubd := range data.UnbondingDelegations { keeper.SetUnbondingDelegation(ctx, ubd) @@ -85,6 +90,7 @@ func InitGenesis( notBondedTokens = notBondedTokens.Add(entry.Balance) } } + fmt.Println("staking/genesis.go - 93") for _, red := range data.Redelegations { keeper.SetRedelegation(ctx, red) @@ -93,10 +99,12 @@ func InitGenesis( keeper.InsertRedelegationQueue(ctx, red, entry.CompletionTime) } } + fmt.Println("staking/genesis.go - 102") bondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, bondedTokens)) notBondedCoins := sdk.NewCoins(sdk.NewCoin(data.Params.BondDenom, notBondedTokens)) + fmt.Println("staking/genesis.go - 107") // check if the unbonded and bonded pools accounts exists bondedPool := keeper.GetBondedPool(ctx) if bondedPool == nil { @@ -107,6 +115,7 @@ func InitGenesis( if bondedBalance.IsZero() { accountKeeper.SetModuleAccount(ctx, bondedPool) } + fmt.Println("staking/genesis.go - 118") // if balance is different from bonded coins panic because genesis is most likely malformed if !bondedBalance.IsEqual(bondedCoins) { panic(fmt.Sprintf("bonded pool balance is different from bonded coins: %s <-> %s", bondedBalance, bondedCoins)) @@ -116,6 +125,7 @@ func InitGenesis( panic(fmt.Sprintf("%s module account has not been set", types.NotBondedPoolName)) } + fmt.Println("staking/genesis.go - 128") notBondedBalance := bankKeeper.GetAllBalances(ctx, notBondedPool.GetAddress()) if notBondedBalance.IsZero() { accountKeeper.SetModuleAccount(ctx, notBondedPool) @@ -124,8 +134,11 @@ func InitGenesis( if !notBondedBalance.IsEqual(notBondedCoins) { panic(fmt.Sprintf("not bonded pool balance is different from not bonded coins: %s <-> %s", notBondedBalance, notBondedCoins)) } + fmt.Println("staking/genesis.go - 137") + fmt.Println(data.Exported) // don't need to run Tendermint updates if we exported if data.Exported { + fmt.Println("staking/genesis.go - 140") for _, lv := range data.LastValidatorPowers { valAddr, err := sdk.ValAddressFromBech32(lv.Address) if err != nil { @@ -143,12 +156,16 @@ func InitGenesis( res = append(res, update) } } else { + fmt.Println("staking/genesis.go - 158") var err error + fmt.Println("staking/genesis.go - 160") res, err = keeper.ApplyAndReturnValidatorSetUpdates(ctx) + fmt.Println("staking/genesis.go - 162") if err != nil { log.Fatal(err) } } + fmt.Println("staking/genesis.go - 167") return res } diff --git a/x/staking/keeper/msg_server.go b/x/staking/keeper/msg_server.go index 3642cef1e5..1b756f4305 100644 --- a/x/staking/keeper/msg_server.go +++ b/x/staking/keeper/msg_server.go @@ -35,6 +35,13 @@ func (k msgServer) CreateValidator(goCtx context.Context, msg *types.MsgCreateVa return nil, err } + minRate := k.MinCommissionRate(ctx) + if minRate.GT(sdk.ZeroDec()) { + if msg.Commission.Rate.LT(*minRate) { // check to see if commission rate is less than minimum + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidCommission, "Commission observed less than minimum, "+k.MinCommissionRate(ctx).String()) + } + } + // check to see if the pubkey or sender has been registered before if _, found := k.GetValidator(ctx, valAddr); found { return nil, types.ErrValidatorOwnerExists @@ -144,6 +151,13 @@ func (k msgServer) EditValidator(goCtx context.Context, msg *types.MsgEditValida validator.Description = description if msg.CommissionRate != nil { + + minRate := k.MinCommissionRate(ctx) + if minRate.GT(sdk.ZeroDec()) { + if msg.CommissionRate.LT(*minRate) { // check to see if commission rate is less than minimum + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidCommission, "Commission observed less than minimum, "+k.MinCommissionRate(ctx).String()) + } + } commission, err := k.UpdateValidatorCommission(ctx, validator, *msg.CommissionRate) if err != nil { return nil, err diff --git a/x/staking/keeper/params.go b/x/staking/keeper/params.go index 10a8b7e8f0..410552cb80 100644 --- a/x/staking/keeper/params.go +++ b/x/staking/keeper/params.go @@ -1,6 +1,7 @@ package keeper import ( + "fmt" "time" sdk "github.com/cosmos/cosmos-sdk/types" @@ -39,6 +40,12 @@ func (k Keeper) BondDenom(ctx sdk.Context) (res string) { return } +func (k Keeper) MinCommissionRate(ctx sdk.Context) (res *sdk.Dec) { + fmt.Println(res) + k.paramstore.Get(ctx, types.KeyMinCommissionRate, res) + return +} + // PowerReduction - is the amount of staking tokens required for 1 unit of consensus-engine power. // Currently, this returns a global variable that the app developer can tweak. // TODO: we might turn this into an on-chain param: @@ -55,6 +62,7 @@ func (k Keeper) GetParams(ctx sdk.Context) types.Params { k.MaxEntries(ctx), k.HistoricalEntries(ctx), k.BondDenom(ctx), + k.MinCommissionRate(ctx), ) } diff --git a/x/staking/keeper/val_state_change.go b/x/staking/keeper/val_state_change.go index 22f6993661..d72f6612ce 100644 --- a/x/staking/keeper/val_state_change.go +++ b/x/staking/keeper/val_state_change.go @@ -115,15 +115,20 @@ func (k Keeper) ApplyAndReturnValidatorSetUpdates(ctx sdk.Context) (updates []ab // Retrieve the last validator set. // The persistent set is updated later in this function. // (see LastValidatorPowerKey). + + fmt.Println("val_state_change.go - 119") last, err := k.getLastValidatorsByAddr(ctx) if err != nil { return nil, err } + fmt.Println("val_state_change.go - 125") + // Iterate over validators, highest power to lowest. iterator := k.ValidatorsPowerStoreIterator(ctx) - defer iterator.Close() + fmt.Println("val_state_change.go - 130") + defer iterator.Close() for count := 0; iterator.Valid() && count < int(maxValidators); iterator.Next() { // everything that is iterated in this loop is becoming or already a // part of the bonded validator set diff --git a/x/staking/module.go b/x/staking/module.go index 3892a8aa93..0ecc8908f0 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -149,7 +149,7 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json. var genesisState types.GenesisState cdc.MustUnmarshalJSON(data, &genesisState) - + fmt.Println("staking/module.go - 152") return InitGenesis(ctx, am.keeper, am.accountKeeper, am.bankKeeper, &genesisState) } diff --git a/x/staking/simulation/genesis.go b/x/staking/simulation/genesis.go index cf4e8e50c4..da5dc0b99e 100644 --- a/x/staking/simulation/genesis.go +++ b/x/staking/simulation/genesis.go @@ -63,7 +63,8 @@ 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) + minCommission := sdk.NewDec(1) + params := types.NewParams(simState.UnbondTime, maxVals, 7, histEntries, sdk.DefaultBondDenom, &minCommission) // validators & delegations var ( @@ -72,6 +73,7 @@ func RandomizedGenState(simState *module.SimulationState) { ) valAddrs := make([]sdk.ValAddress, simState.NumBonded) + fmt.Println("genesis.go - 76") for i := 0; i < int(simState.NumBonded); i++ { valAddr := sdk.ValAddress(simState.Accounts[i].Address) @@ -97,13 +99,18 @@ func RandomizedGenState(simState *module.SimulationState) { validators = append(validators, validator) delegations = append(delegations, delegation) } + fmt.Println("genesis.go - 102") stakingGenesis := types.NewGenesisState(params, validators, delegations) + fmt.Println("genesis.go - 105") bz, err := json.MarshalIndent(&stakingGenesis.Params, "", " ") + fmt.Println("genesis.go - 108") if err != nil { panic(err) } fmt.Printf("Selected randomly generated staking parameters:\n%s\n", bz) + fmt.Println("genesis.go - 113") simState.GenState[types.ModuleName] = simState.Cdc.MustMarshalJSON(stakingGenesis) + fmt.Println("genesis.go - 115") } diff --git a/x/staking/types/errors.go b/x/staking/types/errors.go index 777941e53c..a450ebe1f7 100644 --- a/x/staking/types/errors.go +++ b/x/staking/types/errors.go @@ -21,32 +21,33 @@ var ( ErrCommissionNegative = sdkerrors.Register(ModuleName, 9, "commission must be positive") ErrCommissionHuge = sdkerrors.Register(ModuleName, 10, "commission cannot be more than 100%") ErrCommissionGTMaxRate = sdkerrors.Register(ModuleName, 11, "commission cannot be more than the max rate") - ErrCommissionUpdateTime = sdkerrors.Register(ModuleName, 12, "commission cannot be changed more than once in 24h") - ErrCommissionChangeRateNegative = sdkerrors.Register(ModuleName, 13, "commission change rate must be positive") - ErrCommissionChangeRateGTMaxRate = sdkerrors.Register(ModuleName, 14, "commission change rate cannot be more than the max rate") - ErrCommissionGTMaxChangeRate = sdkerrors.Register(ModuleName, 15, "commission cannot be changed more than max change rate") - ErrSelfDelegationBelowMinimum = sdkerrors.Register(ModuleName, 16, "validator's self delegation must be greater than their minimum self delegation") - ErrMinSelfDelegationDecreased = sdkerrors.Register(ModuleName, 17, "minimum self delegation cannot be decrease") - ErrEmptyDelegatorAddr = sdkerrors.Register(ModuleName, 18, "empty delegator address") - ErrNoDelegation = sdkerrors.Register(ModuleName, 19, "no delegation for (address, validator) tuple") - ErrBadDelegatorAddr = sdkerrors.Register(ModuleName, 20, "delegator does not exist with address") - ErrNoDelegatorForAddress = sdkerrors.Register(ModuleName, 21, "delegator does not contain delegation") - ErrInsufficientShares = sdkerrors.Register(ModuleName, 22, "insufficient delegation shares") - ErrDelegationValidatorEmpty = sdkerrors.Register(ModuleName, 23, "cannot delegate to an empty validator") - ErrNotEnoughDelegationShares = sdkerrors.Register(ModuleName, 24, "not enough delegation shares") - ErrNotMature = sdkerrors.Register(ModuleName, 25, "entry not mature") - ErrNoUnbondingDelegation = sdkerrors.Register(ModuleName, 26, "no unbonding delegation found") - ErrMaxUnbondingDelegationEntries = sdkerrors.Register(ModuleName, 27, "too many unbonding delegation entries for (delegator, validator) tuple") - ErrNoRedelegation = sdkerrors.Register(ModuleName, 28, "no redelegation found") - ErrSelfRedelegation = sdkerrors.Register(ModuleName, 29, "cannot redelegate to the same validator") - ErrTinyRedelegationAmount = sdkerrors.Register(ModuleName, 30, "too few tokens to redelegate (truncates to zero tokens)") - ErrBadRedelegationDst = sdkerrors.Register(ModuleName, 31, "redelegation destination validator not found") - ErrTransitiveRedelegation = sdkerrors.Register(ModuleName, 32, "redelegation to this validator already in progress; first redelegation to this validator must complete before next redelegation") - ErrMaxRedelegationEntries = sdkerrors.Register(ModuleName, 33, "too many redelegation entries for (delegator, src-validator, dst-validator) tuple") - ErrDelegatorShareExRateInvalid = sdkerrors.Register(ModuleName, 34, "cannot delegate to validators with invalid (zero) ex-rate") - ErrBothShareMsgsGiven = sdkerrors.Register(ModuleName, 35, "both shares amount and shares percent provided") - ErrNeitherShareMsgsGiven = sdkerrors.Register(ModuleName, 36, "neither shares amount nor shares percent provided") - 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, 12, "commission cannot be less than the min rate") + ErrCommissionUpdateTime = sdkerrors.Register(ModuleName, 13, "commission cannot be changed more than once in 24h") + ErrCommissionChangeRateNegative = sdkerrors.Register(ModuleName, 14, "commission change rate must be positive") + ErrCommissionChangeRateGTMaxRate = sdkerrors.Register(ModuleName, 15, "commission change rate cannot be more than the max rate") + ErrCommissionGTMaxChangeRate = sdkerrors.Register(ModuleName, 16, "commission cannot be changed more than max change rate") + ErrSelfDelegationBelowMinimum = sdkerrors.Register(ModuleName, 17, "validator's self delegation must be greater than their minimum self delegation") + ErrMinSelfDelegationDecreased = sdkerrors.Register(ModuleName, 18, "minimum self delegation cannot be decrease") + ErrEmptyDelegatorAddr = sdkerrors.Register(ModuleName, 19, "empty delegator address") + ErrNoDelegation = sdkerrors.Register(ModuleName, 20, "no delegation for (address, validator) tuple") + ErrBadDelegatorAddr = sdkerrors.Register(ModuleName, 21, "delegator does not exist with address") + ErrNoDelegatorForAddress = sdkerrors.Register(ModuleName, 22, "delegator does not contain delegation") + ErrInsufficientShares = sdkerrors.Register(ModuleName, 23, "insufficient delegation shares") + ErrDelegationValidatorEmpty = sdkerrors.Register(ModuleName, 24, "cannot delegate to an empty validator") + ErrNotEnoughDelegationShares = sdkerrors.Register(ModuleName, 25, "not enough delegation shares") + ErrNotMature = sdkerrors.Register(ModuleName, 26, "entry not mature") + ErrNoUnbondingDelegation = sdkerrors.Register(ModuleName, 27, "no unbonding delegation found") + ErrMaxUnbondingDelegationEntries = sdkerrors.Register(ModuleName, 28, "too many unbonding delegation entries for (delegator, validator) tuple") + ErrNoRedelegation = sdkerrors.Register(ModuleName, 29, "no redelegation found") + ErrSelfRedelegation = sdkerrors.Register(ModuleName, 30, "cannot redelegate to the same validator") + ErrTinyRedelegationAmount = sdkerrors.Register(ModuleName, 31, "too few tokens to redelegate (truncates to zero tokens)") + ErrBadRedelegationDst = sdkerrors.Register(ModuleName, 32, "redelegation destination validator not found") + ErrTransitiveRedelegation = sdkerrors.Register(ModuleName, 33, "redelegation to this validator already in progress; first redelegation to this validator must complete before next redelegation") + ErrMaxRedelegationEntries = sdkerrors.Register(ModuleName, 34, "too many redelegation entries for (delegator, src-validator, dst-validator) tuple") + ErrDelegatorShareExRateInvalid = sdkerrors.Register(ModuleName, 35, "cannot delegate to validators with invalid (zero) ex-rate") + ErrBothShareMsgsGiven = sdkerrors.Register(ModuleName, 36, "both shares amount and shares percent provided") + ErrNeitherShareMsgsGiven = sdkerrors.Register(ModuleName, 37, "neither shares amount nor shares percent provided") + ErrInvalidHistoricalInfo = sdkerrors.Register(ModuleName, 38, "invalid historical info") + ErrNoHistoricalInfo = sdkerrors.Register(ModuleName, 39, "no historical info found") + ErrEmptyValidatorPubKey = sdkerrors.Register(ModuleName, 40, "empty validator public key") ) diff --git a/x/staking/types/params.go b/x/staking/types/params.go index 8ccae6b565..c4d3e0f542 100644 --- a/x/staking/types/params.go +++ b/x/staking/types/params.go @@ -39,6 +39,14 @@ var ( KeyBondDenom = []byte("BondDenom") KeyHistoricalEntries = []byte("HistoricalEntries") KeyPowerReduction = []byte("PowerReduction") + KeyMinCommissionRate = []byte("MinCommissionRate") + + // TODO: add comments and set value properly, go through conversion to pointer + + //DefaultMinCommissionRate, _ = sdk.NewDecFromStr("0.05") + testMin, _ = sdk.NewDecFromStr("0.05") + + DefaultMinCommissionRate *sdk.Dec = &testMin ) var _ paramtypes.ParamSet = (*Params)(nil) @@ -49,13 +57,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, } } @@ -67,6 +76,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), } } @@ -78,6 +88,7 @@ func DefaultParams() Params { DefaultMaxEntries, DefaultHistoricalEntries, sdk.DefaultBondDenom, + DefaultMinCommissionRate, ) } @@ -205,3 +216,16 @@ 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.LT(sdk.ZeroDec()) { + return errors.New("minimum commission rate cannot be zero") + } + + return nil +} diff --git a/x/staking/types/staking.pb.go b/x/staking/types/staking.pb.go index db19e5d83e..c25832b97a 100644 --- a/x/staking/types/staking.pb.go +++ b/x/staking/types/staking.pb.go @@ -843,6 +843,8 @@ type Params struct { HistoricalEntries uint32 `protobuf:"varint,4,opt,name=historical_entries,json=historicalEntries,proto3" json:"historical_entries,omitempty" yaml:"historical_entries"` // bond_denom defines the bondable coin denomination. BondDenom string `protobuf:"bytes,5,opt,name=bond_denom,json=bondDenom,proto3" json:"bond_denom,omitempty" yaml:"bond_denom"` + // min_ defines the maximum daily increase of the validator commission, as a fraction. + MinCommissionRate *github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,200,opt,name=min_commission_rate,json=minCommissionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_commission_rate" yaml:"min_commission_rate"` } func (m *Params) Reset() { *m = Params{} }