github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/gov/keeper/proposal.go (about)

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client"
     7  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     8  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
     9  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/gov/types"
    10  )
    11  
    12  // SubmitProposal create new proposal given a content
    13  func (keeper Keeper) SubmitProposal(ctx sdk.Context, content types.Content) (types.Proposal, error) {
    14  	if !keeper.router.HasRoute(content.ProposalRoute()) {
    15  		return types.Proposal{}, sdkerrors.Wrap(types.ErrNoProposalHandlerExists, content.ProposalRoute())
    16  	}
    17  
    18  	// Execute the proposal content in a cache-wrapped context to validate the
    19  	// actual parameter changes before the proposal proceeds through the
    20  	// governance process. State is not persisted.
    21  	cacheCtx, _ := ctx.CacheContext()
    22  	handler := keeper.router.GetRoute(content.ProposalRoute())
    23  	if err := handler(cacheCtx, content); err != nil {
    24  		return types.Proposal{}, sdkerrors.Wrap(types.ErrInvalidProposalContent, err.Error())
    25  	}
    26  
    27  	proposalID, err := keeper.GetProposalID(ctx)
    28  	if err != nil {
    29  		return types.Proposal{}, err
    30  	}
    31  
    32  	submitTime := ctx.BlockHeader().Time
    33  	depositPeriod := keeper.GetDepositParams(ctx).MaxDepositPeriod
    34  
    35  	proposal := types.NewProposal(content, proposalID, submitTime, submitTime.Add(depositPeriod))
    36  
    37  	keeper.SetProposal(ctx, proposal)
    38  	keeper.InsertInactiveProposalQueue(ctx, proposalID, proposal.DepositEndTime)
    39  	keeper.SetProposalID(ctx, proposalID+1)
    40  
    41  	ctx.EventManager().EmitEvent(
    42  		sdk.NewEvent(
    43  			types.EventTypeSubmitProposal,
    44  			sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)),
    45  		),
    46  	)
    47  
    48  	return proposal, nil
    49  }
    50  
    51  // GetProposal get proposal from store by ProposalID
    52  func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID uint64) (proposal types.Proposal, ok bool) {
    53  	store := ctx.KVStore(keeper.storeKey)
    54  	bz := store.Get(types.ProposalKey(proposalID))
    55  	if bz == nil {
    56  		return
    57  	}
    58  	keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposal)
    59  	return proposal, true
    60  }
    61  
    62  // SetProposal set a proposal to store
    63  func (keeper Keeper) SetProposal(ctx sdk.Context, proposal types.Proposal) {
    64  	store := ctx.KVStore(keeper.storeKey)
    65  	bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposal)
    66  	store.Set(types.ProposalKey(proposal.ProposalID), bz)
    67  }
    68  
    69  // DeleteProposal deletes a proposal from store
    70  func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposalID uint64) {
    71  	store := ctx.KVStore(keeper.storeKey)
    72  	proposal, ok := keeper.GetProposal(ctx, proposalID)
    73  	if !ok {
    74  		panic(fmt.Sprintf("couldn't find proposal with id#%d", proposalID))
    75  	}
    76  	keeper.RemoveFromInactiveProposalQueue(ctx, proposalID, proposal.DepositEndTime)
    77  	keeper.RemoveFromActiveProposalQueue(ctx, proposalID, proposal.VotingEndTime)
    78  	store.Delete(types.ProposalKey(proposalID))
    79  }
    80  
    81  // IterateProposals iterates over the all the proposals and performs a callback function
    82  func (keeper Keeper) IterateProposals(ctx sdk.Context, cb func(proposal types.Proposal) (stop bool)) {
    83  	store := ctx.KVStore(keeper.storeKey)
    84  	iterator := sdk.KVStorePrefixIterator(store, types.ProposalsKeyPrefix)
    85  
    86  	defer iterator.Close()
    87  	for ; iterator.Valid(); iterator.Next() {
    88  		var proposal types.Proposal
    89  		keeper.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &proposal)
    90  
    91  		if cb(proposal) {
    92  			break
    93  		}
    94  	}
    95  }
    96  
    97  // GetProposals returns all the proposals from store
    98  func (keeper Keeper) GetProposals(ctx sdk.Context) (proposals types.Proposals) {
    99  	keeper.IterateProposals(ctx, func(proposal types.Proposal) bool {
   100  		proposals = append(proposals, proposal)
   101  		return false
   102  	})
   103  	return
   104  }
   105  
   106  // GetProposalsFiltered retrieves proposals filtered by a given set of params which
   107  // include pagination parameters along with voter and depositor addresses and a
   108  // proposal status. The voter address will filter proposals by whether or not
   109  // that address has voted on proposals. The depositor address will filter proposals
   110  // by whether or not that address has deposited to them. Finally, status will filter
   111  // proposals by status.
   112  //
   113  // NOTE: If no filters are provided, all proposals will be returned in paginated
   114  // form.
   115  func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, params types.QueryProposalsParams) []types.Proposal {
   116  	proposals := keeper.GetProposals(ctx)
   117  	filteredProposals := make([]types.Proposal, 0, len(proposals))
   118  
   119  	for _, p := range proposals {
   120  		matchVoter, matchDepositor, matchStatus := true, true, true
   121  
   122  		// match status (if supplied/valid)
   123  		if types.ValidProposalStatus(params.ProposalStatus) {
   124  			matchStatus = p.Status == params.ProposalStatus
   125  		}
   126  
   127  		// match voter address (if supplied)
   128  		if len(params.Voter) > 0 {
   129  			_, matchVoter = keeper.GetVote(ctx, p.ProposalID, params.Voter)
   130  		}
   131  
   132  		// match depositor (if supplied)
   133  		if len(params.Depositor) > 0 {
   134  			_, matchDepositor = keeper.GetDeposit(ctx, p.ProposalID, params.Depositor)
   135  		}
   136  
   137  		if matchVoter && matchDepositor && matchStatus {
   138  			filteredProposals = append(filteredProposals, p)
   139  		}
   140  	}
   141  
   142  	start, end := client.Paginate(len(filteredProposals), params.Page, params.Limit, 100)
   143  	if start < 0 || end < 0 {
   144  		filteredProposals = []types.Proposal{}
   145  	} else {
   146  		filteredProposals = filteredProposals[start:end]
   147  	}
   148  
   149  	return filteredProposals
   150  }
   151  
   152  // GetProposalID gets the highest proposal ID
   153  func (keeper Keeper) GetProposalID(ctx sdk.Context) (proposalID uint64, err error) {
   154  	store := ctx.KVStore(keeper.storeKey)
   155  	bz := store.Get(types.ProposalIDKey)
   156  	if bz == nil {
   157  		return 0, sdkerrors.Wrap(types.ErrInvalidGenesis, "initial proposal ID hasn't been set")
   158  	}
   159  
   160  	proposalID = types.GetProposalIDFromBytes(bz)
   161  	return proposalID, nil
   162  }
   163  
   164  // SetProposalID sets the new proposal ID to the store
   165  func (keeper Keeper) SetProposalID(ctx sdk.Context, proposalID uint64) {
   166  	store := ctx.KVStore(keeper.storeKey)
   167  	store.Set(types.ProposalIDKey, types.GetProposalIDBytes(proposalID))
   168  }
   169  
   170  func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal types.Proposal) {
   171  	proposal.VotingStartTime = ctx.BlockHeader().Time
   172  	votingPeriod := keeper.GetVotingParams(ctx).VotingPeriod
   173  	proposal.VotingEndTime = proposal.VotingStartTime.Add(votingPeriod)
   174  	proposal.Status = types.StatusVotingPeriod
   175  	keeper.SetProposal(ctx, proposal)
   176  
   177  	keeper.RemoveFromInactiveProposalQueue(ctx, proposal.ProposalID, proposal.DepositEndTime)
   178  	keeper.InsertActiveProposalQueue(ctx, proposal.ProposalID, proposal.VotingEndTime)
   179  }