98 lines
2.9 KiB
Go
98 lines
2.9 KiB
Go
package gov
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
|
)
|
|
|
|
// EndBlocker called every block, process inflation, update validator set.
|
|
func EndBlocker(ctx sdk.Context, keeper Keeper) {
|
|
logger := keeper.Logger(ctx)
|
|
|
|
// delete inactive proposal from store and its deposits
|
|
keeper.IterateInactiveProposalsQueue(ctx, ctx.BlockHeader().Time, func(proposal Proposal) bool {
|
|
keeper.DeleteProposal(ctx, proposal.ProposalID)
|
|
keeper.DeleteDeposits(ctx, proposal.ProposalID)
|
|
|
|
ctx.EventManager().EmitEvent(
|
|
sdk.NewEvent(
|
|
types.EventTypeInactiveProposal,
|
|
sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposal.ProposalID)),
|
|
sdk.NewAttribute(types.AttributeKeyProposalResult, types.AttributeValueProposalDropped),
|
|
),
|
|
)
|
|
|
|
logger.Info(
|
|
fmt.Sprintf("proposal %d (%s) didn't meet minimum deposit of %s (had only %s); deleted",
|
|
proposal.ProposalID,
|
|
proposal.GetTitle(),
|
|
keeper.GetDepositParams(ctx).MinDeposit,
|
|
proposal.TotalDeposit,
|
|
),
|
|
)
|
|
return false
|
|
})
|
|
|
|
// fetch active proposals whose voting periods have ended (are passed the block time)
|
|
keeper.IterateActiveProposalsQueue(ctx, ctx.BlockHeader().Time, func(proposal Proposal) bool {
|
|
var tagValue, logMsg string
|
|
|
|
passes, burnDeposits, tallyResults := tally(ctx, keeper, proposal)
|
|
|
|
if burnDeposits {
|
|
keeper.DeleteDeposits(ctx, proposal.ProposalID)
|
|
} else {
|
|
keeper.RefundDeposits(ctx, proposal.ProposalID)
|
|
}
|
|
|
|
if passes {
|
|
handler := keeper.router.GetRoute(proposal.ProposalRoute())
|
|
cacheCtx, writeCache := ctx.CacheContext()
|
|
|
|
// The proposal handler may execute state mutating logic depending
|
|
// on the proposal content. If the handler fails, no state mutation
|
|
// is written and the error message is logged.
|
|
err := handler(cacheCtx, proposal.Content)
|
|
if err == nil {
|
|
proposal.Status = StatusPassed
|
|
tagValue = types.AttributeValueProposalPassed
|
|
logMsg = "passed"
|
|
|
|
// write state to the underlying multi-store
|
|
writeCache()
|
|
} else {
|
|
proposal.Status = StatusFailed
|
|
tagValue = types.AttributeValueProposalFailed
|
|
logMsg = fmt.Sprintf("passed, but failed on execution: %s", err.ABCILog())
|
|
}
|
|
} else {
|
|
proposal.Status = StatusRejected
|
|
tagValue = types.AttributeValueProposalRejected
|
|
logMsg = "rejected"
|
|
}
|
|
|
|
proposal.FinalTallyResult = tallyResults
|
|
|
|
keeper.SetProposal(ctx, proposal)
|
|
keeper.RemoveFromActiveProposalQueue(ctx, proposal.ProposalID, proposal.VotingEndTime)
|
|
|
|
logger.Info(
|
|
fmt.Sprintf(
|
|
"proposal %d (%s) tallied; result: %s",
|
|
proposal.ProposalID, proposal.GetTitle(), logMsg,
|
|
),
|
|
)
|
|
|
|
ctx.EventManager().EmitEvent(
|
|
sdk.NewEvent(
|
|
types.EventTypeActiveProposal,
|
|
sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposal.ProposalID)),
|
|
sdk.NewAttribute(types.AttributeKeyProposalResult, tagValue),
|
|
),
|
|
)
|
|
return false
|
|
})
|
|
}
|