-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtally.go
98 lines (90 loc) · 3.26 KB
/
tally.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package main
import (
"fmt"
h "github.com/dustin/go-humanize"
sdk "github.com/cosmos/cosmos-sdk/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)
func tally(
votesByAddr map[string]govtypes.WeightedVoteOptions, valsByAddr map[string]govtypes.ValidatorGovInfo,
delegsByAddr map[string][]stakingtypes.Delegation,
) (map[govtypes.VoteOption]sdk.Dec, sdk.Dec) {
var (
results = map[govtypes.VoteOption]sdk.Dec{
govtypes.OptionYes: sdk.ZeroDec(),
govtypes.OptionAbstain: sdk.ZeroDec(),
govtypes.OptionNo: sdk.ZeroDec(),
govtypes.OptionNoWithVeto: sdk.ZeroDec(),
}
totalVotingPower = sdk.ZeroDec()
)
for voterAddr, vote := range votesByAddr {
// Check voter delegations
dels := delegsByAddr[voterAddr]
// Initialize voter balance
// balance := sdk.NewDec(0)
for _, del := range dels {
val, ok := valsByAddr[del.ValidatorAddress]
if !ok {
// Validator isn't in active set or jailed, ignore
continue
}
// Reduce validator voting power with delegation that has voted
val.DelegatorDeductions = val.DelegatorDeductions.Add(del.GetShares())
valsByAddr[del.ValidatorAddress] = val
// delegation shares * bonded / total shares
votingPower := del.GetShares().MulInt(val.BondedTokens).Quo(val.DelegatorShares)
// Iterate over vote options
for _, option := range vote {
subPower := votingPower.Mul(option.Weight)
results[option.Option] = results[option.Option].Add(subPower)
}
totalVotingPower = totalVotingPower.Add(votingPower)
}
}
// iterate over the validators again to tally their voting power
for _, val := range valsByAddr {
if len(val.Vote) == 0 {
continue
}
sharesAfterDeductions := val.DelegatorShares.Sub(val.DelegatorDeductions)
votingPower := sharesAfterDeductions.MulInt(val.BondedTokens).Quo(val.DelegatorShares)
for _, option := range val.Vote {
subPower := votingPower.Mul(option.Weight)
results[option.Option] = results[option.Option].Add(subPower)
}
totalVotingPower = totalVotingPower.Add(votingPower)
}
return results, totalVotingPower
}
func printTallyResults(results map[govtypes.VoteOption]sdk.Dec, totalVotingPower sdk.Dec, prop govtypes.Proposal) {
fmt.Println("Computed total voting power", h.Comma(totalVotingPower.TruncateInt64()))
yesPercent := results[govtypes.OptionYes].
Quo(totalVotingPower.Sub(results[govtypes.OptionAbstain]))
fmt.Println("Yes percent:", yesPercent)
tallyResult := govtypes.NewTallyResultFromMap(results)
fmt.Println("--- TALLY RESULT ---")
table := newMarkdownTable("", "Yes", "No", "NoWithVeto", "Abstain", "Total")
appendTable := func(source string, t govtypes.TallyResult) {
total := t.Yes.Add(t.No).Add(t.Abstain).Add(t.NoWithVeto)
table.Append([]string{
source,
human(t.Yes),
human(t.No),
human(t.NoWithVeto),
human(t.Abstain),
human(total),
})
}
appendTable("computed", tallyResult)
appendTable("from prop", prop.FinalTallyResult)
diff := govtypes.NewTallyResult(
tallyResult.Yes.Sub(prop.FinalTallyResult.Yes),
tallyResult.Abstain.Sub(prop.FinalTallyResult.Abstain),
tallyResult.No.Sub(prop.FinalTallyResult.No),
tallyResult.NoWithVeto.Sub(prop.FinalTallyResult.NoWithVeto),
)
appendTable("diff", diff)
table.Render()
}