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

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     8  	"github.com/fibonacci-chain/fbc/x/gov/types"
     9  )
    10  
    11  // SubmitProposal creates new proposal given a content
    12  func (keeper Keeper) SubmitProposal(ctx sdk.Context, content types.Content) (types.Proposal, sdk.Error) {
    13  	if !keeper.router.HasRoute(content.ProposalRoute()) {
    14  		return types.Proposal{}, types.ErrNoProposalHandlerExists(content)
    15  	}
    16  
    17  	proposalID, err := keeper.GetProposalID(ctx)
    18  	if err != nil {
    19  		return types.Proposal{}, err
    20  	}
    21  	// get the time now as the submit time
    22  	submitTime := ctx.BlockHeader().Time
    23  	// get params for special proposal
    24  	var depositPeriod time.Duration
    25  	if !keeper.proposalHandlerRouter.HasRoute(content.ProposalRoute()) {
    26  		depositPeriod = keeper.GetDepositParams(ctx).MaxDepositPeriod
    27  	} else {
    28  		proposalParams := keeper.proposalHandlerRouter.GetRoute(content.ProposalRoute())
    29  		depositPeriod = proposalParams.GetMaxDepositPeriod(ctx, content)
    30  	}
    31  	proposal := types.NewProposal(ctx, keeper.totalPower(ctx), content, proposalID, submitTime,
    32  		submitTime.Add(depositPeriod))
    33  
    34  	keeper.SetProposal(ctx, proposal)
    35  	keeper.InsertInactiveProposalQueue(ctx, proposalID, proposal.DepositEndTime)
    36  	keeper.SetProposalID(ctx, proposalID+1)
    37  
    38  	if keeper.proposalHandlerRouter.HasRoute(content.ProposalRoute()) {
    39  		keeper.proposalHandlerRouter.GetRoute(content.ProposalRoute()).AfterSubmitProposalHandler(ctx, proposal)
    40  	}
    41  
    42  	ctx.EventManager().EmitEvent(
    43  		sdk.NewEvent(
    44  			types.EventTypeSubmitProposal,
    45  			sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)),
    46  		),
    47  	)
    48  
    49  	return proposal, nil
    50  }
    51  
    52  // GetProposal get Proposal from store by ProposalID
    53  func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID uint64) (proposal types.Proposal, ok bool) {
    54  	store := ctx.KVStore(keeper.storeKey)
    55  	bz := store.Get(types.ProposalKey(proposalID))
    56  	if bz == nil {
    57  		return
    58  	}
    59  	keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposal)
    60  	return proposal, true
    61  }
    62  
    63  // SetProposal set a proposal to store
    64  func (keeper Keeper) SetProposal(ctx sdk.Context, proposal types.Proposal) {
    65  	store := ctx.KVStore(keeper.storeKey)
    66  	bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposal)
    67  	store.Set(types.ProposalKey(proposal.ProposalID), bz)
    68  }
    69  
    70  // DeleteProposal deletes a proposal from store
    71  func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposalID uint64) {
    72  	store := ctx.KVStore(keeper.storeKey)
    73  	proposal, ok := keeper.GetProposal(ctx, proposalID)
    74  	if !ok {
    75  		panic(fmt.Sprintf("couldn't find proposal with id#%d", proposalID))
    76  	}
    77  	keeper.RemoveFromInactiveProposalQueue(ctx, proposalID, proposal.DepositEndTime)
    78  	keeper.RemoveFromActiveProposalQueue(ctx, proposalID, proposal.VotingEndTime)
    79  	store.Delete(types.ProposalKey(proposalID))
    80  }
    81  
    82  // GetProposals returns all the proposals from store
    83  func (keeper Keeper) GetProposals(ctx sdk.Context) (proposals types.Proposals) {
    84  	keeper.IterateProposals(ctx, func(proposal types.Proposal) bool {
    85  		proposals = append(proposals, proposal)
    86  		return false
    87  	})
    88  	return
    89  }
    90  
    91  // GetProposalsFiltered get Proposals from store by ProposalID
    92  // voterAddr will filter proposals by whether or not that address has voted on them
    93  // depositorAddr will filter proposals by whether or not that address has deposited to them
    94  // status will filter proposals by status
    95  // numLatest will fetch a specified number of the most recent proposals, or 0 for all proposals
    96  func (keeper Keeper) GetProposalsFiltered(
    97  	ctx sdk.Context, voterAddr sdk.AccAddress, depositorAddr sdk.AccAddress, status types.ProposalStatus,
    98  	numLatest uint64,
    99  ) []types.Proposal {
   100  
   101  	maxProposalID, err := keeper.GetProposalID(ctx)
   102  	if err != nil {
   103  		return []types.Proposal{}
   104  	}
   105  
   106  	matchingProposals := []types.Proposal{}
   107  
   108  	if numLatest == 0 {
   109  		numLatest = maxProposalID
   110  	}
   111  
   112  	for proposalID := maxProposalID - numLatest; proposalID < maxProposalID; proposalID++ {
   113  		if voterAddr != nil && len(voterAddr) != 0 {
   114  			_, found := keeper.GetVote(ctx, proposalID, voterAddr)
   115  			if !found {
   116  				continue
   117  			}
   118  		}
   119  
   120  		if depositorAddr != nil && len(depositorAddr) != 0 {
   121  			_, found := keeper.GetDeposit(ctx, proposalID, depositorAddr)
   122  			if !found {
   123  				continue
   124  			}
   125  		}
   126  
   127  		proposal, ok := keeper.GetProposal(ctx, proposalID)
   128  		if !ok {
   129  			continue
   130  		}
   131  
   132  		if types.ValidProposalStatus(status) && proposal.Status != status {
   133  			continue
   134  		}
   135  
   136  		matchingProposals = append(matchingProposals, proposal)
   137  	}
   138  	return matchingProposals
   139  }
   140  
   141  // GetProposalID gets the highest proposal ID
   142  func (keeper Keeper) GetProposalID(ctx sdk.Context) (proposalID uint64, err sdk.Error) {
   143  	store := ctx.KVStore(keeper.storeKey)
   144  	bz := store.Get(types.ProposalIDKey)
   145  	if bz == nil {
   146  		return 0, types.ErrInvalidGenesis()
   147  	}
   148  	keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalID)
   149  	return proposalID, nil
   150  }
   151  
   152  // SetProposalID sets the proposal ID to gov store
   153  func (keeper Keeper) SetProposalID(ctx sdk.Context, proposalID uint64) {
   154  	store := ctx.KVStore(keeper.storeKey)
   155  	bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID)
   156  	store.Set(types.ProposalIDKey, bz)
   157  }
   158  
   159  func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal *types.Proposal) {
   160  	proposal.VotingStartTime = ctx.BlockHeader().Time
   161  	var votingPeriod time.Duration
   162  	if !keeper.proposalHandlerRouter.HasRoute(proposal.ProposalRoute()) {
   163  		votingPeriod = keeper.GetVotingPeriod(ctx, proposal.Content)
   164  	} else {
   165  		phr := keeper.proposalHandlerRouter.GetRoute(proposal.ProposalRoute())
   166  		votingPeriod = phr.GetVotingPeriod(ctx, proposal.Content)
   167  	}
   168  	// calculate the end time of voting
   169  	proposal.VotingEndTime = proposal.VotingStartTime.Add(votingPeriod)
   170  	proposal.Status = types.StatusVotingPeriod
   171  
   172  	keeper.RemoveFromInactiveProposalQueue(ctx, proposal.ProposalID, proposal.DepositEndTime)
   173  	keeper.InsertActiveProposalQueue(ctx, proposal.ProposalID, proposal.VotingEndTime)
   174  }