github.com/Finschia/finschia-sdk@v0.48.1/x/gov/keeper/vote.go (about) 1 package keeper 2 3 import ( 4 "fmt" 5 6 sdk "github.com/Finschia/finschia-sdk/types" 7 sdkerrors "github.com/Finschia/finschia-sdk/types/errors" 8 "github.com/Finschia/finschia-sdk/x/gov/types" 9 ) 10 11 // AddVote adds a vote on a specific proposal 12 func (keeper Keeper) AddVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress, options types.WeightedVoteOptions) error { 13 proposal, ok := keeper.GetProposal(ctx, proposalID) 14 if !ok { 15 return sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID) 16 } 17 if proposal.Status != types.StatusVotingPeriod { 18 return sdkerrors.Wrapf(types.ErrInactiveProposal, "%d", proposalID) 19 } 20 21 for _, option := range options { 22 if !types.ValidWeightedVoteOption(option) { 23 return sdkerrors.Wrap(types.ErrInvalidVote, option.String()) 24 } 25 } 26 27 vote := types.NewVote(proposalID, voterAddr, options) 28 keeper.SetVote(ctx, vote) 29 30 // called after a vote on a proposal is cast 31 keeper.AfterProposalVote(ctx, proposalID, voterAddr) 32 33 ctx.EventManager().EmitEvent( 34 sdk.NewEvent( 35 types.EventTypeProposalVote, 36 sdk.NewAttribute(types.AttributeKeyOption, options.String()), 37 sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)), 38 ), 39 ) 40 41 return nil 42 } 43 44 // GetAllVotes returns all the votes from the store 45 func (keeper Keeper) GetAllVotes(ctx sdk.Context) (votes types.Votes) { 46 keeper.IterateAllVotes(ctx, func(vote types.Vote) bool { 47 populateLegacyOption(&vote) 48 votes = append(votes, vote) 49 return false 50 }) 51 return 52 } 53 54 // GetVotes returns all the votes from a proposal 55 func (keeper Keeper) GetVotes(ctx sdk.Context, proposalID uint64) (votes types.Votes) { 56 keeper.IterateVotes(ctx, proposalID, func(vote types.Vote) bool { 57 populateLegacyOption(&vote) 58 votes = append(votes, vote) 59 return false 60 }) 61 return 62 } 63 64 // GetVote gets the vote from an address on a specific proposal 65 func (keeper Keeper) GetVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) (vote types.Vote, found bool) { 66 store := ctx.KVStore(keeper.storeKey) 67 bz := store.Get(types.VoteKey(proposalID, voterAddr)) 68 if bz == nil { 69 return vote, false 70 } 71 72 keeper.cdc.MustUnmarshal(bz, &vote) 73 populateLegacyOption(&vote) 74 75 return vote, true 76 } 77 78 // SetVote sets a Vote to the gov store 79 func (keeper Keeper) SetVote(ctx sdk.Context, vote types.Vote) { 80 // vote.Option is a deprecated field, we don't set it in state 81 if vote.Option != types.OptionEmpty { //nolint 82 vote.Option = types.OptionEmpty //nolint 83 } 84 85 store := ctx.KVStore(keeper.storeKey) 86 bz := keeper.cdc.MustMarshal(&vote) 87 addr := sdk.MustAccAddressFromBech32(vote.Voter) 88 89 store.Set(types.VoteKey(vote.ProposalId, addr), bz) 90 } 91 92 // IterateAllVotes iterates over the all the stored votes and performs a callback function 93 func (keeper Keeper) IterateAllVotes(ctx sdk.Context, cb func(vote types.Vote) (stop bool)) { 94 store := ctx.KVStore(keeper.storeKey) 95 iterator := sdk.KVStorePrefixIterator(store, types.VotesKeyPrefix) 96 97 defer iterator.Close() 98 for ; iterator.Valid(); iterator.Next() { 99 var vote types.Vote 100 keeper.cdc.MustUnmarshal(iterator.Value(), &vote) 101 populateLegacyOption(&vote) 102 103 if cb(vote) { 104 break 105 } 106 } 107 } 108 109 // IterateVotes iterates over the all the proposals votes and performs a callback function 110 func (keeper Keeper) IterateVotes(ctx sdk.Context, proposalID uint64, cb func(vote types.Vote) (stop bool)) { 111 store := ctx.KVStore(keeper.storeKey) 112 iterator := sdk.KVStorePrefixIterator(store, types.VotesKey(proposalID)) 113 114 defer iterator.Close() 115 for ; iterator.Valid(); iterator.Next() { 116 var vote types.Vote 117 keeper.cdc.MustUnmarshal(iterator.Value(), &vote) 118 populateLegacyOption(&vote) 119 120 if cb(vote) { 121 break 122 } 123 } 124 } 125 126 // deleteVote deletes a vote from a given proposalID and voter from the store 127 func (keeper Keeper) deleteVote(ctx sdk.Context, proposalID uint64, voterAddr sdk.AccAddress) { 128 store := ctx.KVStore(keeper.storeKey) 129 store.Delete(types.VoteKey(proposalID, voterAddr)) 130 } 131 132 // populateLegacyOption adds graceful fallback of deprecated `Option` field, in case 133 // there's only 1 VoteOption. 134 func populateLegacyOption(vote *types.Vote) { 135 if len(vote.Options) == 1 && vote.Options[0].Weight.Equal(sdk.MustNewDecFromStr("1.0")) { 136 vote.Option = vote.Options[0].Option //nolint 137 } 138 }