156 lines
5.1 KiB
Go
156 lines
5.1 KiB
Go
|
package gov
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||
|
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||
|
)
|
||
|
|
||
|
// SubmitProposal create new proposal given a content
|
||
|
func (keeper Keeper) SubmitProposal(ctx sdk.Context, content Content) (Proposal, sdk.Error) {
|
||
|
if !keeper.router.HasRoute(content.ProposalRoute()) {
|
||
|
return Proposal{}, ErrNoProposalHandlerExists(keeper.codespace, content)
|
||
|
}
|
||
|
|
||
|
// Execute the proposal content in a cache-wrapped context to validate the
|
||
|
// actual parameter changes before the proposal proceeds through the
|
||
|
// governance process. State is not persisted.
|
||
|
cacheCtx, _ := ctx.CacheContext()
|
||
|
handler := keeper.router.GetRoute(content.ProposalRoute())
|
||
|
if err := handler(cacheCtx, content); err != nil {
|
||
|
return Proposal{}, ErrInvalidProposalContent(keeper.codespace, err.Result().Log)
|
||
|
}
|
||
|
|
||
|
proposalID, err := keeper.GetProposalID(ctx)
|
||
|
if err != nil {
|
||
|
return Proposal{}, err
|
||
|
}
|
||
|
|
||
|
submitTime := ctx.BlockHeader().Time
|
||
|
depositPeriod := keeper.GetDepositParams(ctx).MaxDepositPeriod
|
||
|
|
||
|
proposal := NewProposal(content, proposalID, submitTime, submitTime.Add(depositPeriod))
|
||
|
|
||
|
keeper.SetProposal(ctx, proposal)
|
||
|
keeper.InsertInactiveProposalQueue(ctx, proposalID, proposal.DepositEndTime)
|
||
|
keeper.setProposalID(ctx, proposalID+1)
|
||
|
|
||
|
return proposal, nil
|
||
|
}
|
||
|
|
||
|
// GetProposal get Proposal from store by ProposalID
|
||
|
func (keeper Keeper) GetProposal(ctx sdk.Context, proposalID uint64) (proposal Proposal, ok bool) {
|
||
|
store := ctx.KVStore(keeper.storeKey)
|
||
|
bz := store.Get(ProposalKey(proposalID))
|
||
|
if bz == nil {
|
||
|
return
|
||
|
}
|
||
|
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposal)
|
||
|
return proposal, true
|
||
|
}
|
||
|
|
||
|
// SetProposal set a proposal to store
|
||
|
func (keeper Keeper) SetProposal(ctx sdk.Context, proposal Proposal) {
|
||
|
store := ctx.KVStore(keeper.storeKey)
|
||
|
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposal)
|
||
|
store.Set(ProposalKey(proposal.ProposalID), bz)
|
||
|
}
|
||
|
|
||
|
// DeleteProposal deletes a proposal from store
|
||
|
func (keeper Keeper) DeleteProposal(ctx sdk.Context, proposalID uint64) {
|
||
|
store := ctx.KVStore(keeper.storeKey)
|
||
|
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||
|
if !ok {
|
||
|
panic(fmt.Sprintf("couldn't find proposal with id#%d", proposalID))
|
||
|
}
|
||
|
keeper.RemoveFromInactiveProposalQueue(ctx, proposalID, proposal.DepositEndTime)
|
||
|
keeper.RemoveFromActiveProposalQueue(ctx, proposalID, proposal.VotingEndTime)
|
||
|
store.Delete(ProposalKey(proposalID))
|
||
|
}
|
||
|
|
||
|
// GetProposals returns all the proposals from store
|
||
|
func (keeper Keeper) GetProposals(ctx sdk.Context) (proposals Proposals) {
|
||
|
keeper.IterateProposals(ctx, func(proposal types.Proposal) bool {
|
||
|
proposals = append(proposals, proposal)
|
||
|
return false
|
||
|
})
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// GetProposalsFiltered get Proposals from store by ProposalID
|
||
|
// voterAddr will filter proposals by whether or not that address has voted on them
|
||
|
// depositorAddr will filter proposals by whether or not that address has deposited to them
|
||
|
// status will filter proposals by status
|
||
|
// numLatest will fetch a specified number of the most recent proposals, or 0 for all proposals
|
||
|
func (keeper Keeper) GetProposalsFiltered(ctx sdk.Context, voterAddr sdk.AccAddress, depositorAddr sdk.AccAddress, status ProposalStatus, numLatest uint64) []Proposal {
|
||
|
|
||
|
maxProposalID, err := keeper.GetProposalID(ctx)
|
||
|
if err != nil {
|
||
|
return []Proposal{}
|
||
|
}
|
||
|
|
||
|
matchingProposals := []Proposal{}
|
||
|
|
||
|
if numLatest == 0 {
|
||
|
numLatest = maxProposalID
|
||
|
}
|
||
|
|
||
|
for proposalID := maxProposalID - numLatest; proposalID < maxProposalID; proposalID++ {
|
||
|
if voterAddr != nil && len(voterAddr) != 0 {
|
||
|
_, found := keeper.GetVote(ctx, proposalID, voterAddr)
|
||
|
if !found {
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if depositorAddr != nil && len(depositorAddr) != 0 {
|
||
|
_, found := keeper.GetDeposit(ctx, proposalID, depositorAddr)
|
||
|
if !found {
|
||
|
continue
|
||
|
}
|
||
|
}
|
||
|
|
||
|
proposal, ok := keeper.GetProposal(ctx, proposalID)
|
||
|
if !ok {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if ValidProposalStatus(status) && proposal.Status != status {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
matchingProposals = append(matchingProposals, proposal)
|
||
|
}
|
||
|
return matchingProposals
|
||
|
}
|
||
|
|
||
|
// GetProposalID gets the highest proposal ID
|
||
|
func (keeper Keeper) GetProposalID(ctx sdk.Context) (proposalID uint64, err sdk.Error) {
|
||
|
store := ctx.KVStore(keeper.storeKey)
|
||
|
bz := store.Get(ProposalIDKey)
|
||
|
if bz == nil {
|
||
|
return 0, ErrInvalidGenesis(keeper.codespace, "initial proposal ID hasn't been set")
|
||
|
}
|
||
|
keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &proposalID)
|
||
|
return proposalID, nil
|
||
|
}
|
||
|
|
||
|
// Set the proposal ID
|
||
|
func (keeper Keeper) setProposalID(ctx sdk.Context, proposalID uint64) {
|
||
|
store := ctx.KVStore(keeper.storeKey)
|
||
|
bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID)
|
||
|
store.Set(ProposalIDKey, bz)
|
||
|
}
|
||
|
|
||
|
func (keeper Keeper) activateVotingPeriod(ctx sdk.Context, proposal Proposal) {
|
||
|
proposal.VotingStartTime = ctx.BlockHeader().Time
|
||
|
votingPeriod := keeper.GetVotingParams(ctx).VotingPeriod
|
||
|
proposal.VotingEndTime = proposal.VotingStartTime.Add(votingPeriod)
|
||
|
proposal.Status = StatusVotingPeriod
|
||
|
keeper.SetProposal(ctx, proposal)
|
||
|
|
||
|
keeper.RemoveFromInactiveProposalQueue(ctx, proposal.ProposalID, proposal.DepositEndTime)
|
||
|
keeper.InsertActiveProposalQueue(ctx, proposal.ProposalID, proposal.VotingEndTime)
|
||
|
}
|