forked from cosmos/cosmos-sdk
/
vote.go
140 lines (117 loc) · 4.16 KB
/
vote.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package keeper
import (
"fmt"
sdk "github.com/eligion/cosmos-sdk/types"
sdkerrors "github.com/eligion/cosmos-sdk/types/errors"
"github.com/eligion/cosmos-sdk/x/gov/types"
)
// AddVote adds a vote on a specific proposal
func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, options types.WeightedVoteOptions) error {
proposal, ok := keeper.GetProposal(ctx, proposalID)
if !ok {
return sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID)
}
if proposal.Status != types.StatusVotingPeriod {
return sdkerrors.Wrapf(types.ErrInactiveProposal, "%d", proposalID)
}
for _, option := range options {
if !types.ValidWeightedVoteOption(option) {
return sdkerrors.Wrap(types.ErrInvalidVote, option.String())
}
}
vote := types.NewVote(proposalID, voterAddr, options)
keeper.SetVote(ctx, vote)
// called after a vote on a proposal is cast
keeper.AfterProposalVote(ctx, proposalID, voterAddr)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeProposalVote,
sdk.NewAttribute(types.AttributeKeyOption, options.String()),
sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)),
),
)
return nil
}
// GetAllVotes returns all the votes from the store
func (keeper Keeper) GetAllVotes(ctx sdk.Context) (votes types.Votes) {
keeper.IterateAllVotes(ctx, func(vote types.Vote) bool {
populateLegacyOption(&vote)
votes = append(votes, vote)
return false
})
return
}
// GetVotes returns all the votes from a proposal
func (keeper Keeper) GetVotes(ctx sdk.Context, proposalID uint64) (votes types.Votes) {
keeper.IterateVotes(ctx, proposalID, func(vote types.Vote) bool {
populateLegacyOption(&vote)
votes = append(votes, vote)
return false
})
return
}
// GetVote gets the vote from an address on a specific proposal
func (keeper Keeper) GetVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) (vote types.Vote, found bool) {
store := ctx.KVStore(keeper.storeKey)
bz := store.Get(types.VoteKey(proposalID, voterAddr))
if bz == nil {
return vote, false
}
keeper.cdc.MustUnmarshal(bz, &vote)
populateLegacyOption(&vote)
return vote, true
}
// SetVote sets a Vote to the gov store
func (keeper Keeper) SetVote(ctx sdk.Context, vote types.Vote) {
// vote.Option is a deprecated field, we don't set it in state
if vote.Option != types.OptionEmpty { //nolint
vote.Option = types.OptionEmpty //nolint
}
store := ctx.KVStore(keeper.storeKey)
bz := keeper.cdc.MustMarshal(&vote)
addr, err := sdk.AccAddressFromBech32(vote.Voter)
if err != nil {
panic(err)
}
store.Set(types.VoteKey(vote.ProposalId, addr), bz)
}
// IterateAllVotes iterates over the all the stored votes and performs a callback function
func (keeper Keeper) IterateAllVotes(ctx sdk.Context, cb func(vote types.Vote) (stop bool)) {
store := ctx.KVStore(keeper.storeKey)
iterator := sdk.KVStorePrefixIterator(store, types.VotesKeyPrefix)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var vote types.Vote
keeper.cdc.MustUnmarshal(iterator.Value(), &vote)
populateLegacyOption(&vote)
if cb(vote) {
break
}
}
}
// IterateVotes iterates over the all the proposals votes and performs a callback function
func (keeper Keeper) IterateVotes(ctx sdk.Context, proposalID uint64, cb func(vote types.Vote) (stop bool)) {
store := ctx.KVStore(keeper.storeKey)
iterator := sdk.KVStorePrefixIterator(store, types.VotesKey(proposalID))
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var vote types.Vote
keeper.cdc.MustUnmarshal(iterator.Value(), &vote)
populateLegacyOption(&vote)
if cb(vote) {
break
}
}
}
// deleteVote deletes a vote from a given proposalID and voter from the store
func (keeper Keeper) deleteVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) {
store := ctx.KVStore(keeper.storeKey)
store.Delete(types.VoteKey(proposalID, voterAddr))
}
// populateLegacyOption adds graceful fallback of deprecated `Option` field, in case
// there's only 1 VoteOption.
func populateLegacyOption(vote *types.Vote) {
if len(vote.Options) == 1 && vote.Options[0].Weight.Equal(sdk.MustNewDecFromStr("1.0")) {
vote.Option = vote.Options[0].Option //nolint
}
}