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 }