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: removed governance slashing #2395

Merged
merged 1 commit into from Sep 25, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions PENDING.md
Expand Up @@ -36,6 +36,7 @@ BREAKING CHANGES
* `cosmosvaladdr` / `cosmosvalpub` => `cosmosvaloper` / `cosmosvaloperpub`
* [x/stake] [#1013] TendermintUpdates now uses transient store
* [x/gov] [#2195] Governance uses BFT Time
* [x/gov] \#2256 Removed slashing for governance non-voting validators

* SDK
* [core] [\#1807](https://github.com/cosmos/cosmos-sdk/issues/1807) Switch from use of rational to decimal
Expand Down
11 changes: 3 additions & 8 deletions docs/spec/governance/state.md
Expand Up @@ -28,7 +28,6 @@ type TallyingProcedure struct {
Threshold sdk.Dec // Minimum propotion of Yes votes for proposal to pass. Initial value: 0.5
Veto sdk.Dec // Minimum proportion of Veto votes to Total votes ratio for proposal to be vetoed. Initial value: 1/3
GovernancePenalty sdk.Dec // Penalty if validator does not vote
GracePeriod time.Time // If validator entered validator set in this period of blocks before vote ended, governance penalty does not apply
}
```

Expand Down Expand Up @@ -192,14 +191,10 @@ And the pseudocode for the `ProposalProcessingQueue`:

tallyingProcedure = load(GlobalParams, 'TallyingProcedure')

// Slash validators that did not vote, or update tally if they voted
// Update tally if validator voted they voted
for each validator in validators
if (validator.bondTime < CurrentTime - tallyingProcedure.GracePeriod)
// only slash if validator entered validator set before grace period
if (!tmpValMap(validator).HasVoted)
slash validator by tallyingProcedure.GovernancePenalty
else
proposal.updateTally(tmpValMap(validator).Vote, (validator.TotalShares - tmpValMap(validator).Minus))
if tmpValMap(validator).HasVoted
proposal.updateTally(tmpValMap(validator).Vote, (validator.TotalShares - tmpValMap(validator).Minus))



Expand Down
60 changes: 0 additions & 60 deletions x/gov/endblocker_test.go
Expand Up @@ -7,7 +7,6 @@ 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 @@ -194,62 +193,3 @@ func TestTickPassedVotingPeriod(t *testing.T) {
require.Equal(t, StatusRejected, keeper.GetProposal(ctx, proposalID).GetStatus())
require.True(t, keeper.GetProposal(ctx, proposalID).GetTallyResult().Equals(EmptyTallyResult()))
}

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)

valAddrs := make([]sdk.ValAddress, len(addrs[:3]))
for i, addr := range addrs[:3] {
valAddrs[i] = sdk.ValAddress(addr)
}

createValidators(t, stakeHandler, ctx, valAddrs, []int64{25, 6, 7})

initTotalPower := keeper.ds.GetValidatorSet().TotalPower(ctx)
val0Initial := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[0])).GetPower().Quo(initTotalPower)
val1Initial := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[1])).GetPower().Quo(initTotalPower)
val2Initial := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[2])).GetPower().Quo(initTotalPower)

newProposalMsg := NewMsgSubmitProposal("Test", "test", ProposalTypeText, addrs[0], sdk.Coins{sdk.NewInt64Coin("steak", 15)})

res := govHandler(ctx, newProposalMsg)
require.True(t, res.IsOK())
var proposalID int64
keeper.cdc.UnmarshalBinaryBare(res.Data, &proposalID)

newHeader := ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(time.Duration(1) * time.Second)
ctx = ctx.WithBlockHeader(newHeader)

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)

newHeader = ctx.BlockHeader()
newHeader.Time = ctx.BlockHeader().Time.Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod).Add(keeper.GetDepositProcedure(ctx).MaxDepositPeriod)
ctx = ctx.WithBlockHeader(newHeader)

require.Equal(t, StatusVotingPeriod, keeper.GetProposal(ctx, proposalID).GetStatus())

EndBlocker(ctx, keeper)

require.False(t, keeper.GetProposal(ctx, proposalID).GetTallyResult().Equals(EmptyTallyResult()))

endTotalPower := keeper.ds.GetValidatorSet().TotalPower(ctx)
val0End := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[0])).GetPower().Quo(endTotalPower)
val1End := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(addrs[1])).GetPower().Quo(endTotalPower)
val2End := keeper.ds.GetValidatorSet().Validator(ctx, sdk.ValAddress(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: 1 addition & 13 deletions x/gov/handler.go
Expand Up @@ -134,7 +134,7 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
continue
}

passes, tallyResults, nonVotingVals := tally(ctx, keeper, activeProposal)
passes, tallyResults := tally(ctx, keeper, activeProposal)
proposalIDBytes := keeper.cdc.MustMarshalBinaryBare(activeProposal.GetProposalID())
var action []byte
if passes {
Expand All @@ -152,18 +152,6 @@ func EndBlocker(ctx sdk.Context, keeper Keeper) (resTags sdk.Tags) {
logger.Info(fmt.Sprintf("proposal %d (%s) tallied; passed: %v",
activeProposal.GetProposalID(), activeProposal.GetTitle(), passes))

for _, valAddr := range nonVotingVals {
val := keeper.ds.GetValidatorSet().Validator(ctx, valAddr)
keeper.ds.GetValidatorSet().Slash(ctx,
val.GetConsAddr(),
ctx.BlockHeight(),
val.GetPower().RoundInt64(),
keeper.GetTallyingProcedure(ctx).GovernancePenalty)

logger.Info(fmt.Sprintf("validator %s failed to vote on proposal %d; slashing",
val.GetOperator(), activeProposal.GetProposalID()))
}

resTags.AppendTag(tags.Action, action)
resTags.AppendTag(tags.ProposalID, proposalIDBytes)
}
Expand Down
2 changes: 1 addition & 1 deletion x/gov/queryable.go
Expand Up @@ -220,7 +220,7 @@ func queryTally(ctx sdk.Context, path []string, req abci.RequestQuery, keeper Ke
} else if proposal.GetStatus() == StatusPassed || proposal.GetStatus() == StatusRejected {
tallyResult = proposal.GetTallyResult()
} else {
_, tallyResult, _ = tally(ctx, keeper, proposal)
_, tallyResult = tally(ctx, keeper, proposal)
}

bz, err2 := codec.MarshalJSONIndent(keeper.cdc, tallyResult)
Expand Down
17 changes: 6 additions & 11 deletions x/gov/tally.go
Expand Up @@ -13,7 +13,7 @@ type validatorGovInfo struct {
Vote VoteOption // Vote of the validator
}

func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult, nonVoting []sdk.ValAddress) {
func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tallyResults TallyResult) {
results := make(map[VoteOption]sdk.Dec)
results[OptionYes] = sdk.ZeroDec()
results[OptionAbstain] = sdk.ZeroDec()
Expand Down Expand Up @@ -70,12 +70,9 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall
keeper.deleteVote(ctx, vote.ProposalID, vote.Voter)
}

// iterate over the validators again to tally their voting power and see
// who didn't vote
nonVoting = []sdk.ValAddress{}
// iterate over the validators again to tally their voting power
for _, val := range currValidators {
if val.Vote == OptionEmpty {
nonVoting = append(nonVoting, val.Address)
continue
}

Expand All @@ -98,19 +95,17 @@ func tally(ctx sdk.Context, keeper Keeper, proposal Proposal) (passes bool, tall

// If no one votes, proposal fails
if totalVotingPower.Sub(results[OptionAbstain]).Equal(sdk.ZeroDec()) {
return false, tallyResults, nonVoting
return false, tallyResults
}
// If more than 1/3 of voters veto, proposal fails
if results[OptionNoWithVeto].Quo(totalVotingPower).GT(tallyingProcedure.Veto) {
return false, tallyResults, nonVoting
return false, tallyResults
}
// If more than 1/2 of non-abstaining voters vote Yes, proposal passes
if results[OptionYes].Quo(totalVotingPower.Sub(results[OptionAbstain])).GT(tallyingProcedure.Threshold) {
return true, tallyResults, nonVoting
return true, tallyResults
}
// If more than 1/2 of non-abstaining voters vote No, proposal fails

SortValAddresses(nonVoting)

return false, tallyResults, nonVoting
return false, tallyResults
}
29 changes: 13 additions & 16 deletions x/gov/tally_test.go
Expand Up @@ -51,7 +51,7 @@ func TestTallyNoOneVotes(t *testing.T) {
proposal.SetStatus(StatusVotingPeriod)
keeper.SetProposal(ctx, proposal)

passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.False(t, passes)
require.True(t, tallyResults.Equals(EmptyTallyResult()))
Expand Down Expand Up @@ -80,7 +80,7 @@ func TestTallyOnlyValidatorsAllYes(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionYes)
require.Nil(t, err)

passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.True(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
Expand Down Expand Up @@ -109,7 +109,7 @@ func TestTallyOnlyValidators51No(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[1], OptionNo)
require.Nil(t, err)

passes, _, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.False(t, passes)
}
Expand Down Expand Up @@ -139,7 +139,7 @@ func TestTallyOnlyValidators51Yes(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
require.Nil(t, err)

passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.True(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
Expand Down Expand Up @@ -170,7 +170,7 @@ func TestTallyOnlyValidatorsVetoed(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNoWithVeto)
require.Nil(t, err)

passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.False(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
Expand Down Expand Up @@ -201,7 +201,7 @@ func TestTallyOnlyValidatorsAbstainPasses(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionYes)
require.Nil(t, err)

passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.True(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
Expand Down Expand Up @@ -232,7 +232,7 @@ func TestTallyOnlyValidatorsAbstainFails(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
require.Nil(t, err)

passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.False(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
Expand Down Expand Up @@ -261,11 +261,9 @@ func TestTallyOnlyValidatorsNonVoter(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
require.Nil(t, err)

passes, tallyResults, nonVoting := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.False(t, passes)
require.Equal(t, 1, len(nonVoting))
require.Equal(t, sdk.ValAddress(addrs[0]), nonVoting[0])
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}

Expand Down Expand Up @@ -299,7 +297,7 @@ func TestTallyDelgatorOverride(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[3], OptionNo)
require.Nil(t, err)

passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.False(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
Expand Down Expand Up @@ -333,10 +331,9 @@ func TestTallyDelgatorInherit(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionYes)
require.Nil(t, err)

passes, tallyResults, nonVoting := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.True(t, passes)
require.Equal(t, 0, len(nonVoting))
require.False(t, tallyResults.Equals(EmptyTallyResult()))
}

Expand Down Expand Up @@ -372,7 +369,7 @@ func TestTallyDelgatorMultipleOverride(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[3], OptionNo)
require.Nil(t, err)

passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.False(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
Expand Down Expand Up @@ -417,7 +414,7 @@ func TestTallyDelgatorMultipleInherit(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
require.Nil(t, err)

passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.False(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
Expand Down Expand Up @@ -458,7 +455,7 @@ func TestTallyJailedValidator(t *testing.T) {
err = keeper.AddVote(ctx, proposalID, addrs[2], OptionNo)
require.Nil(t, err)

passes, tallyResults, _ := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))
passes, tallyResults := tally(ctx, keeper, keeper.GetProposal(ctx, proposalID))

require.True(t, passes)
require.False(t, tallyResults.Equals(EmptyTallyResult()))
Expand Down