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  }