Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validator minimum commission #81

Merged
merged 3 commits into from Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Expand Up @@ -4,4 +4,8 @@ secret.yml
cosmoshub3.json
exchanges.json
juno_out.json
bin
bin

# emacs editor config
\#*\#
.\#*
97 changes: 97 additions & 0 deletions app/ante.go
@@ -0,0 +1,97 @@
package app

import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
channelkeeper "github.com/cosmos/ibc-go/modules/core/04-channel/keeper"
ibcante "github.com/cosmos/ibc-go/modules/core/ante"
)

// HandlerOptions extends the SDK's AnteHandler options by requiring the IBC
// channel keeper.
type HandlerOptions struct {
ante.HandlerOptions

IBCChannelkeeper channelkeeper.Keeper
}

type MinCommissionDecorator struct{}

func NewMinCommissionDecorator() MinCommissionDecorator {
return MinCommissionDecorator{}
}

func (MinCommissionDecorator) AnteHandle(
ctx sdk.Context, tx sdk.Tx,
simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
msgs := tx.GetMsgs()
minCommissionRate := sdk.NewDecWithPrec(5, 2)
for _, m := range msgs {
switch msg := m.(type) {
case *stakingtypes.MsgCreateValidator:
// prevent new validators joining the set with
// commission set below 5%
c := msg.Commission
if c.Rate.LT(minCommissionRate) {
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "commission can't be lower than 5%")
}
case *stakingtypes.MsgEditValidator:
// if commission rate is nil, it means only
// other fields are affected - skip
if msg.CommissionRate == nil {
continue
}
if msg.CommissionRate.LT(minCommissionRate) {
return ctx, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "commission can't be lower than 5%")
}
default:
continue
}
}
return next(ctx, tx, simulate)
}

// NewAnteHandler returns an AnteHandler that checks and increments sequence
// numbers, checks signatures & account numbers, and deducts fees from the first
// signer.
func NewAnteHandler(options HandlerOptions) (sdk.AnteHandler, error) {
if options.AccountKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "account keeper is required for ante builder")
}

if options.BankKeeper == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "bank keeper is required for ante builder")
}

if options.SignModeHandler == nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrLogic, "sign mode handler is required for ante builder")
}

var sigGasConsumer = options.SigGasConsumer
if sigGasConsumer == nil {
sigGasConsumer = ante.DefaultSigVerificationGasConsumer
}

anteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
NewMinCommissionDecorator(),
ante.NewRejectExtensionOptionsDecorator(),
ante.NewMempoolFeeDecorator(),
ante.NewValidateBasicDecorator(),
ante.NewTxTimeoutHeightDecorator(),
ante.NewValidateMemoDecorator(options.AccountKeeper),
ante.NewConsumeGasForTxSizeDecorator(options.AccountKeeper),
ante.NewDeductFeeDecorator(options.AccountKeeper, options.BankKeeper, options.FeegrantKeeper),
// SetPubKeyDecorator must be called before all signature verification decorators
ante.NewSetPubKeyDecorator(options.AccountKeeper),
ante.NewValidateSigCountDecorator(options.AccountKeeper),
ante.NewSigGasConsumeDecorator(options.AccountKeeper, sigGasConsumer),
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewAnteDecorator(options.IBCChannelkeeper),
}

return sdk.ChainAnteDecorators(anteDecorators...), nil
}
47 changes: 37 additions & 10 deletions app/app.go
Expand Up @@ -105,7 +105,6 @@ import (
const (
AccountAddressPrefix = "juno"
Name = "juno"
upgradeName = "moneta-alpha"
)

// this line is used by starport scaffolding # stargate/wasm/app/enabledProposals
Expand Down Expand Up @@ -524,13 +523,16 @@ func New(
app.MountTransientStores(tkeys)
app.MountMemoryStores(memKeys)

anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
FeegrantKeeper: app.FeeGrantKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
anteHandler, err := NewAnteHandler(
HandlerOptions{
HandlerOptions: ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
FeegrantKeeper: app.FeeGrantKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
IBCChannelkeeper: app.IBCKeeper.ChannelKeeper,
},
)
if err != nil {
Expand All @@ -548,7 +550,7 @@ func New(
panic(err)
}

if upgradeInfo.Name == upgradeName && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
if upgradeInfo.Name == "moneta-alpha" && !app.UpgradeKeeper.IsSkipHeight(upgradeInfo.Height) {
storeUpgrades := store.StoreUpgrades{
Added: []string{authz.ModuleName, feegrant.ModuleName, wasm.ModuleName},
}
Expand Down Expand Up @@ -702,7 +704,32 @@ func (app *App) RegisterTendermintService(clientCtx client.Context) {

// RegisterUpgradeHandlers returns upgrade handlers
func (app *App) RegisterUpgradeHandlers(cfg module.Configurator) {
app.UpgradeKeeper.SetUpgradeHandler(upgradeName, func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
app.UpgradeKeeper.SetUpgradeHandler("moneta-alpha", func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
return app.mm.RunMigrations(ctx, cfg, vm)
})

app.UpgradeKeeper.SetUpgradeHandler("moneta-beta", func(ctx sdk.Context, plan upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) {
// force an update of validator min commission
validators := app.StakingKeeper.GetAllValidators(ctx)
// hard code this because we don't want
// a) a fork or
// b) immediate reaction with additional gov props
minCommissionRate := sdk.NewDecWithPrec(5, 2)
for _, v := range validators {
if v.Commission.Rate.LT(minCommissionRate) {
comm, err := app.StakingKeeper.UpdateValidatorCommission(
ctx, v, minCommissionRate)
if err != nil {
panic(err)
}
v.Commission = comm

// call the before-modification hook since we're about to update the commission
app.StakingKeeper.BeforeValidatorModified(ctx, v.GetOperator())

app.StakingKeeper.SetValidator(ctx, v)
}
}
return app.mm.RunMigrations(ctx, cfg, vm)
})
}
Expand Down