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

R4R: Add slashing to governance for non-voting validators #1859

Merged
merged 2 commits into from
Jul 30, 2018
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ FEATURES
* This allows SDK users to initialize a new project repository.
* [tests] Remotenet commands for AWS (awsnet)
* [store] Add transient store
* [gov] Add slashing for validators who do not vote on a proposal

IMPROVEMENTS
* [baseapp] Allow any alphanumeric character in route
Expand Down
3 changes: 1 addition & 2 deletions cmd/gaia/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,8 @@ func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) ab
// application updates every end block
// nolint: unparam
func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {

tags := gov.EndBlocker(ctx, app.govKeeper)
validatorUpdates := stake.EndBlocker(ctx, app.stakeKeeper)
tags, _ := gov.EndBlocker(ctx, app.govKeeper)

return abci.ResponseEndBlock{
ValidatorUpdates: validatorUpdates,
Expand Down
47 changes: 47 additions & 0 deletions x/gov/endblocker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake"
abci "github.com/tendermint/tendermint/abci/types"
)

Expand Down Expand Up @@ -166,3 +167,49 @@ func TestTickPassedVotingPeriod(t *testing.T) {
depositsIterator.Close()
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))
}
14 changes: 12 additions & 2 deletions x/gov/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result {
}

// 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()

Expand All @@ -112,6 +112,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags, nonVotingVals
}

var passes bool
var nonVotingVals []sdk.AccAddress

// Check if earliest Active Proposal ended voting period yet
for shouldPopActiveProposalQueue(ctx, keeper) {
Expand All @@ -137,11 +138,20 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags, nonVotingVals
}
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.ProposalID, proposalIDBytes)
}

return resTags, nonVotingVals
return resTags
}
func shouldPopInactiveProposalQueue(ctx sdk.Context, keeper Keeper) bool {
depositProcedure := keeper.GetDepositProcedure(ctx)
Expand Down
2 changes: 1 addition & 1 deletion x/gov/test_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func getMockApp(t *testing.T, numGenAccs int) (*mock.App, Keeper, stake.Keeper,
// gov and stake endblocker
func getEndBlocker(keeper Keeper) sdk.EndBlocker {
return func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
tags, _ := EndBlocker(ctx, keeper)
tags := EndBlocker(ctx, keeper)
return abci.ResponseEndBlock{
Tags: tags,
}
Expand Down