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

Sum validator operator's all voting power #5107

Merged
merged 13 commits into from
Oct 18, 2019
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ to detail this new feature and how state transitions occur.

* (cli) [\#4763](https://github.com/cosmos/cosmos-sdk/issues/4763) Fix flag `--min-self-delegation` for staking `EditValidator`
* (keys) Fix ledger custom coin type support bug
* (x/gov) [\#5107](https://github.com/cosmos/cosmos-sdk/pull/5107) Sum validator operator's all voting power when tally votes
* (baseapp) [\#5200](https://github.com/cosmos/cosmos-sdk/issues/5200) Remove duplicate events from previous messages.

## [v0.37.2] - 2019-10-10
Expand Down
33 changes: 17 additions & 16 deletions x/gov/keeper/tally.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,31 @@ func (keeper Keeper) Tally(ctx sdk.Context, proposal types.Proposal) (passes boo

keeper.IterateVotes(ctx, proposal.ProposalID, func(vote types.Vote) bool {
// if validator, just record it in the map
// if delegator tally voting power
valAddrStr := sdk.ValAddress(vote.Voter).String()
if val, ok := currValidators[valAddrStr]; ok {
Ruihuan marked this conversation as resolved.
Show resolved Hide resolved
val.Vote = vote.Option
currValidators[valAddrStr] = val
} else {
// iterate over all delegations from voter, deduct from any delegated-to validators
keeper.sk.IterateDelegations(ctx, vote.Voter, func(index int64, delegation exported.DelegationI) (stop bool) {
valAddrStr := delegation.GetValidatorAddr().String()
}

if val, ok := currValidators[valAddrStr]; ok {
val.DelegatorDeductions = val.DelegatorDeductions.Add(delegation.GetShares())
currValidators[valAddrStr] = val
// iterate over all delegations from voter, deduct from any delegated-to validators
Ruihuan marked this conversation as resolved.
Show resolved Hide resolved
keeper.sk.IterateDelegations(ctx, vote.Voter, func(index int64, delegation exported.DelegationI) (stop bool) {
valAddrStr := delegation.GetValidatorAddr().String()

delegatorShare := delegation.GetShares().Quo(val.DelegatorShares)
votingPower := delegatorShare.MulInt(val.BondedTokens)
if val, ok := currValidators[valAddrStr]; ok {
Ruihuan marked this conversation as resolved.
Show resolved Hide resolved
// There is no need to handle the special case that validator address equal to voter address.
// Because voter's voting power will tally again even if there will deduct voter's voting power from validator.
val.DelegatorDeductions = val.DelegatorDeductions.Add(delegation.GetShares())
currValidators[valAddrStr] = val

results[vote.Option] = results[vote.Option].Add(votingPower)
totalVotingPower = totalVotingPower.Add(votingPower)
}
delegatorShare := delegation.GetShares().Quo(val.DelegatorShares)
votingPower := delegatorShare.MulInt(val.BondedTokens)

return false
})
}
results[vote.Option] = results[vote.Option].Add(votingPower)
totalVotingPower = totalVotingPower.Add(votingPower)
}

return false
})

keeper.deleteVote(ctx, vote.ProposalID, vote.Voter)
return false
Expand Down
38 changes: 38 additions & 0 deletions x/gov/keeper/tally_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,41 @@ func TestTallyJailedValidator(t *testing.T) {
require.False(t, burnDeposits)
require.False(t, tallyResults.Equals(types.EmptyTallyResult()))
}

func TestTallyValidatorMultipleDelegations(t *testing.T) {
ctx, _, keeper, sk, _ := createTestInput(t, false, 100)
createValidators(ctx, sk, []int64{10, 10, 10})

delTokens := sdk.TokensFromConsensusPower(10)
val2, found := sk.GetValidator(ctx, valOpAddr2)
require.True(t, found)

_, err := sk.Delegate(ctx, valAccAddr1, delTokens, sdk.Unbonded, val2, true)
require.NoError(t, err)

tp := TestProposal
proposal, err := keeper.SubmitProposal(ctx, tp)
require.NoError(t, err)
proposalID := proposal.ProposalID
proposal.Status = types.StatusVotingPeriod
keeper.SetProposal(ctx, proposal)

require.NoError(t, keeper.AddVote(ctx, proposalID, valAccAddr1, types.OptionYes))
require.NoError(t, keeper.AddVote(ctx, proposalID, valAccAddr2, types.OptionNo))
require.NoError(t, keeper.AddVote(ctx, proposalID, valAccAddr3, types.OptionYes))

proposal, ok := keeper.GetProposal(ctx, proposalID)
require.True(t, ok)
passes, burnDeposits, tallyResults := keeper.Tally(ctx, proposal)

require.True(t, passes)
require.False(t, burnDeposits)

expectedYes := sdk.TokensFromConsensusPower(30)
expectedAbstain := sdk.TokensFromConsensusPower(0)
expectedNo := sdk.TokensFromConsensusPower(10)
expectedNoWithVeto := sdk.TokensFromConsensusPower(0)
expectedTallyResult := types.NewTallyResult(expectedYes, expectedAbstain, expectedNo, expectedNoWithVeto)

require.True(t, tallyResults.Equals(expectedTallyResult))
}