package gov import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/gov/tags" ) // Handle all "gov" type messages. func NewHandler(keeper Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { switch msg := msg.(type) { case MsgDeposit: return handleMsgDeposit(ctx, keeper, msg) case MsgSubmitProposal: return handleMsgSubmitProposal(ctx, keeper, msg) case MsgVote: return handleMsgVote(ctx, keeper, msg) default: errMsg := fmt.Sprintf("Unrecognized gov msg type: %T", msg) return sdk.ErrUnknownRequest(errMsg).Result() } } } func handleMsgSubmitProposal(ctx sdk.Context, keeper Keeper, msg MsgSubmitProposal) sdk.Result { proposal := keeper.NewTextProposal(ctx, msg.Title, msg.Description, msg.ProposalType) proposalID := proposal.GetProposalID() proposalIDBytes := []byte(fmt.Sprintf("%d", proposalID)) err, votingStarted := keeper.AddDeposit(ctx, proposalID, msg.Proposer, msg.InitialDeposit) if err != nil { return err.Result() } resTags := sdk.NewTags( tags.Action, tags.ActionProposalSubmitted, tags.Proposer, []byte(msg.Proposer.String()), tags.ProposalID, proposalIDBytes, ) if votingStarted { resTags = resTags.AppendTag(tags.VotingPeriodStart, proposalIDBytes) } return sdk.Result{ Data: keeper.cdc.MustMarshalBinaryLengthPrefixed(proposalID), Tags: resTags, } } func handleMsgDeposit(ctx sdk.Context, keeper Keeper, msg MsgDeposit) sdk.Result { err, votingStarted := keeper.AddDeposit(ctx, msg.ProposalID, msg.Depositor, msg.Amount) if err != nil { return err.Result() } proposalIDBytes := []byte(fmt.Sprintf("%d", msg.ProposalID)) resTags := sdk.NewTags( tags.Action, tags.ActionProposalDeposit, tags.Depositor, []byte(msg.Depositor.String()), tags.ProposalID, proposalIDBytes, ) if votingStarted { resTags = resTags.AppendTag(tags.VotingPeriodStart, proposalIDBytes) } return sdk.Result{ Tags: resTags, } } func handleMsgVote(ctx sdk.Context, keeper Keeper, msg MsgVote) sdk.Result { err := keeper.AddVote(ctx, msg.ProposalID, msg.Voter, msg.Option) if err != nil { return err.Result() } return sdk.Result{ Tags: sdk.NewTags( tags.Action, tags.ActionProposalVote, tags.Voter, []byte(msg.Voter.String()), tags.ProposalID, []byte(fmt.Sprintf("%d", msg.ProposalID)), ), } } // Called every block, process inflation, update validator set func EndBlocker(ctx sdk.Context, keeper Keeper) sdk.Tags { logger := ctx.Logger().With("module", "x/gov") resTags := sdk.NewTags() inactiveIterator := keeper.InactiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) for ; inactiveIterator.Valid(); inactiveIterator.Next() { var proposalID uint64 keeper.cdc.MustUnmarshalBinaryLengthPrefixed(inactiveIterator.Value(), &proposalID) inactiveProposal := keeper.GetProposal(ctx, proposalID) keeper.DeleteProposal(ctx, proposalID) keeper.DeleteDeposits(ctx, proposalID) // delete any associated deposits (burned) resTags = resTags.AppendTag(tags.ProposalID, []byte(fmt.Sprintf("%d", proposalID))) resTags = resTags.AppendTag(tags.ProposalResult, tags.ActionProposalDropped) logger.Info( fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %s (had only %s); deleted", inactiveProposal.GetProposalID(), inactiveProposal.GetTitle(), keeper.GetDepositParams(ctx).MinDeposit, inactiveProposal.GetTotalDeposit(), ), ) } inactiveIterator.Close() activeIterator := keeper.ActiveProposalQueueIterator(ctx, ctx.BlockHeader().Time) for ; activeIterator.Valid(); activeIterator.Next() { var proposalID uint64 keeper.cdc.MustUnmarshalBinaryLengthPrefixed(activeIterator.Value(), &proposalID) activeProposal := keeper.GetProposal(ctx, proposalID) passes, tallyResults := tally(ctx, keeper, activeProposal) var tagValue []byte if passes { keeper.RefundDeposits(ctx, activeProposal.GetProposalID()) activeProposal.SetStatus(StatusPassed) tagValue = tags.ActionProposalPassed } else { keeper.DeleteDeposits(ctx, activeProposal.GetProposalID()) activeProposal.SetStatus(StatusRejected) tagValue = tags.ActionProposalRejected } activeProposal.SetFinalTallyResult(tallyResults) keeper.SetProposal(ctx, activeProposal) keeper.RemoveFromActiveProposalQueue(ctx, activeProposal.GetVotingEndTime(), activeProposal.GetProposalID()) logger.Info( fmt.Sprintf( "proposal %d (%s) tallied; passed: %v", activeProposal.GetProposalID(), activeProposal.GetTitle(), passes, ), ) resTags = resTags.AppendTag(tags.ProposalID, []byte(fmt.Sprintf("%d", proposalID))) resTags = resTags.AppendTag(tags.ProposalResult, tagValue) } activeIterator.Close() return resTags }