Merge pull request #1859: slashing to governance for non-voting validators
* added slashing to governance non voting * minor formatting
This commit is contained in:
parent
53d30aff88
commit
7fc2ed61d7
|
@ -37,6 +37,7 @@ FEATURES
|
||||||
* This allows SDK users to initialize a new project repository.
|
* This allows SDK users to initialize a new project repository.
|
||||||
* [tests] Remotenet commands for AWS (awsnet)
|
* [tests] Remotenet commands for AWS (awsnet)
|
||||||
* [store] Add transient store
|
* [store] Add transient store
|
||||||
|
* [gov] Add slashing for validators who do not vote on a proposal
|
||||||
|
|
||||||
IMPROVEMENTS
|
IMPROVEMENTS
|
||||||
* [baseapp] Allow any alphanumeric character in route
|
* [baseapp] Allow any alphanumeric character in route
|
||||||
|
|
|
@ -146,9 +146,8 @@ func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab
|
||||||
// application updates every end block
|
// application updates every end block
|
||||||
// nolint: unparam
|
// nolint: unparam
|
||||||
func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||||
|
tags := gov.EndBlocker(ctx, app.govKeeper)
|
||||||
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
|
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
|
||||||
tags, _ := gov.EndBlocker(ctx, app.govKeeper)
|
|
||||||
|
|
||||||
return abci.ResponseEndBlock{
|
return abci.ResponseEndBlock{
|
||||||
ValidatorUpdates: validatorUpdates,
|
ValidatorUpdates: validatorUpdates,
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
"github.com/cosmos/cosmos-sdk/x/stake"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -166,3 +167,49 @@ func TestTickPassedVotingPeriod(t *testing.T) {
|
||||||
depositsIterator.Close()
|
depositsIterator.Close()
|
||||||
require.Equal(t, StatusRejected, keeper.GetProposal(ctx, proposalID).GetStatus())
|
require.Equal(t, StatusRejected, keeper.GetProposal(ctx, proposalID).GetStatus())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSlashing(t *testing.T) {
|
||||||
|
mapp, keeper, sk, addrs, _, _ := getMockApp(t, 10)
|
||||||
|
SortAddresses(addrs)
|
||||||
|
mapp.BeginBlock(abci.RequestBeginBlock{})
|
||||||
|
ctx := mapp.BaseApp.NewContext(false, abci.Header{})
|
||||||
|
govHandler := NewHandler(keeper)
|
||||||
|
stakeHandler := stake.NewHandler(sk)
|
||||||
|
|
||||||
|
createValidators(t, stakeHandler, ctx, addrs[:3], []int64{25, 6, 7})
|
||||||
|
|
||||||
|
initTotalPower := keeper.ds.GetValidatorSet().TotalPower(ctx)
|
||||||
|
val0Initial := keeper.ds.GetValidatorSet().Validator(ctx, addrs[0]).GetPower().Quo(initTotalPower)
|
||||||
|
val1Initial := keeper.ds.GetValidatorSet().Validator(ctx, addrs[1]).GetPower().Quo(initTotalPower)
|
||||||
|
val2Initial := keeper.ds.GetValidatorSet().Validator(ctx, addrs[2]).GetPower().Quo(initTotalPower)
|
||||||
|
|
||||||
|
newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewCoin("steak", 15)})
|
||||||
|
|
||||||
|
res := govHandler(ctx, newProposalMsg)
|
||||||
|
require.True(t, res.IsOK())
|
||||||
|
var proposalID int64
|
||||||
|
keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID)
|
||||||
|
|
||||||
|
ctx = ctx.WithBlockHeight(10)
|
||||||
|
require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus())
|
||||||
|
|
||||||
|
newVoteMsg := NewMsgVote(addrs[0], proposalID, OptionYes)
|
||||||
|
res = govHandler(ctx, newVoteMsg)
|
||||||
|
require.True(t, res.IsOK())
|
||||||
|
|
||||||
|
EndBlocker(ctx, keeper)
|
||||||
|
|
||||||
|
ctx = ctx.WithBlockHeight(215)
|
||||||
|
require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus())
|
||||||
|
|
||||||
|
EndBlocker(ctx, keeper)
|
||||||
|
|
||||||
|
endTotalPower := keeper.ds.GetValidatorSet().TotalPower(ctx)
|
||||||
|
val0End := keeper.ds.GetValidatorSet().Validator(ctx, addrs[0]).GetPower().Quo(endTotalPower)
|
||||||
|
val1End := keeper.ds.GetValidatorSet().Validator(ctx, addrs[1]).GetPower().Quo(endTotalPower)
|
||||||
|
val2End := keeper.ds.GetValidatorSet().Validator(ctx, addrs[2]).GetPower().Quo(endTotalPower)
|
||||||
|
|
||||||
|
require.True(t, val0End.GTE(val0Initial))
|
||||||
|
require.True(t, val1End.LT(val1Initial))
|
||||||
|
require.True(t, val2End.LT(val2Initial))
|
||||||
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called every block, process inflation, update validator set
|
// Called every block, process inflation, update validator set
|
||||||
func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags, nonVotingVals []sdk.AccAddress) {
|
func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
|
||||||
|
|
||||||
resTags = sdk.NewTags()
|
resTags = sdk.NewTags()
|
||||||
|
|
||||||
|
@ -112,6 +112,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags, nonVotingVals
|
||||||
}
|
}
|
||||||
|
|
||||||
var passes bool
|
var passes bool
|
||||||
|
var nonVotingVals []sdk.AccAddress
|
||||||
|
|
||||||
// Check if earliest Active Proposal ended voting period yet
|
// Check if earliest Active Proposal ended voting period yet
|
||||||
for shouldPopActiveProposalQueue(ctx, keeper) {
|
for shouldPopActiveProposalQueue(ctx, keeper) {
|
||||||
|
@ -137,11 +138,20 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags, nonVotingVals
|
||||||
}
|
}
|
||||||
keeper.SetProposal(ctx, activeProposal)
|
keeper.SetProposal(ctx, activeProposal)
|
||||||
|
|
||||||
|
for _, valAddr := range nonVotingVals {
|
||||||
|
val := keeper.ds.GetValidatorSet().Validator(ctx, valAddr)
|
||||||
|
keeper.ds.GetValidatorSet().Slash(ctx,
|
||||||
|
val.GetPubKey(),
|
||||||
|
ctx.BlockHeight(),
|
||||||
|
val.GetPower().RoundInt64(),
|
||||||
|
keeper.GetTallyingProcedure(ctx).GovernancePenalty)
|
||||||
|
}
|
||||||
|
|
||||||
resTags.AppendTag(tags.Action, action)
|
resTags.AppendTag(tags.Action, action)
|
||||||
resTags.AppendTag(tags.ProposalID, proposalIDBytes)
|
resTags.AppendTag(tags.ProposalID, proposalIDBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resTags, nonVotingVals
|
return resTags
|
||||||
}
|
}
|
||||||
func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
|
func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
|
||||||
depositProcedure := keeper.GetDepositProcedure(ctx)
|
depositProcedure := keeper.GetDepositProcedure(ctx)
|
||||||
|
|
|
@ -50,7 +50,7 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper,
|
||||||
// gov and stake endblocker
|
// gov and stake endblocker
|
||||||
func getEndBlocker(keeper Keeper) sdk.EndBlocker {
|
func getEndBlocker(keeper Keeper) sdk.EndBlocker {
|
||||||
return func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
return func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||||
tags, _ := EndBlocker(ctx, keeper)
|
tags := EndBlocker(ctx, keeper)
|
||||||
return abci.ResponseEndBlock{
|
return abci.ResponseEndBlock{
|
||||||
Tags: tags,
|
Tags: tags,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue