155 lines
4.5 KiB
Go
155 lines
4.5 KiB
Go
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.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.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.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
|
|
}
|