2019-02-08 18:33:06 -08:00
package gov
import (
"fmt"
2020-07-17 08:34:37 -07:00
"time"
2019-02-08 18:33:06 -08:00
2020-06-18 11:12:44 -07:00
"github.com/cosmos/cosmos-sdk/telemetry"
2019-02-08 18:33:06 -08:00
sdk "github.com/cosmos/cosmos-sdk/types"
2020-06-13 02:07:51 -07:00
"github.com/cosmos/cosmos-sdk/x/gov/keeper"
2019-06-26 09:03:25 -07:00
"github.com/cosmos/cosmos-sdk/x/gov/types"
2022-01-21 03:14:00 -08:00
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta2"
2019-02-08 18:33:06 -08:00
)
2019-06-26 09:03:25 -07:00
// EndBlocker called every block, process inflation, update validator set.
2020-06-13 02:07:51 -07:00
func EndBlocker ( ctx sdk . Context , keeper keeper . Keeper ) {
2022-01-21 03:14:00 -08:00
defer telemetry . ModuleMeasureSince ( types . ModuleName , time . Now ( ) , telemetry . MetricKeyEndBlocker )
2020-06-18 11:12:44 -07:00
2019-04-15 20:58:06 -07:00
logger := keeper . Logger ( ctx )
2019-02-08 18:33:06 -08:00
2022-01-26 10:36:24 -08:00
// delete dead proposals from store and returns theirs deposits. A proposal is dead when it's inactive and didn't get enough deposit on time to get into voting phase.
2022-01-21 03:14:00 -08:00
keeper . IterateInactiveProposalsQueue ( ctx , ctx . BlockHeader ( ) . Time , func ( proposal v1beta2 . Proposal ) bool {
2020-08-14 01:55:54 -07:00
keeper . DeleteProposal ( ctx , proposal . ProposalId )
2022-01-26 10:36:24 -08:00
keeper . RefundAndDeleteDeposits ( ctx , proposal . ProposalId ) // refund deposit if proposal got removed without getting 100% of the proposal
2019-02-08 18:33:06 -08:00
2021-04-21 09:59:30 -07:00
// called when proposal become inactive
keeper . AfterProposalFailedMinDeposit ( ctx , proposal . ProposalId )
2019-06-26 09:03:25 -07:00
ctx . EventManager ( ) . EmitEvent (
sdk . NewEvent (
types . EventTypeInactiveProposal ,
2020-08-14 01:55:54 -07:00
sdk . NewAttribute ( types . AttributeKeyProposalID , fmt . Sprintf ( "%d" , proposal . ProposalId ) ) ,
2019-06-26 09:03:25 -07:00
sdk . NewAttribute ( types . AttributeKeyProposalResult , types . AttributeValueProposalDropped ) ,
) ,
)
2019-02-08 18:33:06 -08:00
logger . Info (
2020-12-03 15:17:21 -08:00
"proposal did not meet minimum deposit; deleted" ,
"proposal" , proposal . ProposalId ,
2022-01-21 03:14:00 -08:00
"min_deposit" , sdk . NewCoins ( keeper . GetDepositParams ( ctx ) . MinDeposit ... ) . String ( ) ,
"total_deposit" , sdk . NewCoins ( proposal . TotalDeposit ... ) . String ( ) ,
2019-02-08 18:33:06 -08:00
)
2020-12-03 15:17:21 -08:00
2019-06-04 11:38:11 -07:00
return false
} )
2019-02-08 18:33:06 -08:00
// fetch active proposals whose voting periods have ended (are passed the block time)
2022-01-21 03:14:00 -08:00
keeper . IterateActiveProposalsQueue ( ctx , ctx . BlockHeader ( ) . Time , func ( proposal v1beta2 . Proposal ) bool {
2019-04-30 09:31:38 -07:00
var tagValue , logMsg string
2019-08-08 12:51:18 -07:00
passes , burnDeposits , tallyResults := keeper . Tally ( ctx , proposal )
2019-06-04 11:38:11 -07:00
2019-05-20 07:13:50 -07:00
if burnDeposits {
2021-07-30 10:37:38 -07:00
keeper . DeleteAndBurnDeposits ( ctx , proposal . ProposalId )
2019-05-20 07:13:50 -07:00
} else {
2021-07-30 10:37:38 -07:00
keeper . RefundAndDeleteDeposits ( ctx , proposal . ProposalId )
2019-05-20 07:13:50 -07:00
}
2019-04-30 09:31:38 -07:00
2019-05-20 07:13:50 -07:00
if passes {
2022-01-21 03:14:00 -08:00
var (
idx int
msg sdk . Msg
)
// attempt to execute all messages within the passed proposal
// Messages may mutate state thus we use a cached context. If one of
// the handlers fails, no state mutation is written and the error
// message is logged.
2019-04-30 09:31:38 -07:00
cacheCtx , writeCache := ctx . CacheContext ( )
2022-01-21 03:14:00 -08:00
messages , err := proposal . GetMsgs ( )
if err == nil {
for idx , msg = range messages {
handler := keeper . Router ( ) . Handler ( msg )
_ , err = handler ( cacheCtx , msg )
if err != nil {
break
}
}
}
2019-04-30 09:31:38 -07:00
2022-01-21 03:14:00 -08:00
// `err == nil` when all handlers passed.
// Or else, `idx` and `err` are populated with the msg index and error.
2019-04-30 09:31:38 -07:00
if err == nil {
2022-01-21 03:14:00 -08:00
proposal . Status = v1beta2 . StatusPassed
2019-06-26 09:03:25 -07:00
tagValue = types . AttributeValueProposalPassed
2019-04-30 09:31:38 -07:00
logMsg = "passed"
2020-02-06 13:19:26 -08:00
// The cached context is created with a new EventManager. However, since
// the proposal handler execution was successful, we want to track/keep
// any events emitted, so we re-emit to "merge" the events into the
// original Context's EventManager.
ctx . EventManager ( ) . EmitEvents ( cacheCtx . EventManager ( ) . Events ( ) )
2019-04-30 09:31:38 -07:00
// write state to the underlying multi-store
writeCache ( )
} else {
2022-01-21 03:14:00 -08:00
proposal . Status = v1beta2 . StatusFailed
2019-06-26 09:03:25 -07:00
tagValue = types . AttributeValueProposalFailed
2022-01-21 03:14:00 -08:00
logMsg = fmt . Sprintf ( "passed, but msg %d (%s) failed on execution: %s" , idx , sdk . MsgTypeURL ( msg ) , err )
2019-04-30 09:31:38 -07:00
}
2019-02-08 18:33:06 -08:00
} else {
2022-01-21 03:14:00 -08:00
proposal . Status = v1beta2 . StatusRejected
2019-06-26 09:03:25 -07:00
tagValue = types . AttributeValueProposalRejected
2019-04-30 09:31:38 -07:00
logMsg = "rejected"
2019-02-08 18:33:06 -08:00
}
2022-01-21 03:14:00 -08:00
proposal . FinalTallyResult = & tallyResults
2019-04-30 09:31:38 -07:00
2019-06-04 11:38:11 -07:00
keeper . SetProposal ( ctx , proposal )
2022-01-21 03:14:00 -08:00
keeper . RemoveFromActiveProposalQueue ( ctx , proposal . ProposalId , * proposal . VotingEndTime )
2019-02-08 18:33:06 -08:00
2021-04-21 09:59:30 -07:00
// when proposal become active
keeper . AfterProposalVotingPeriodEnded ( ctx , proposal . ProposalId )
2019-02-08 18:33:06 -08:00
logger . Info (
2020-12-03 15:17:21 -08:00
"proposal tallied" ,
"proposal" , proposal . ProposalId ,
2022-01-21 03:14:00 -08:00
"results" , logMsg ,
2019-02-08 18:33:06 -08:00
)
2019-06-26 09:03:25 -07:00
ctx . EventManager ( ) . EmitEvent (
sdk . NewEvent (
types . EventTypeActiveProposal ,
2020-08-14 01:55:54 -07:00
sdk . NewAttribute ( types . AttributeKeyProposalID , fmt . Sprintf ( "%d" , proposal . ProposalId ) ) ,
2019-06-26 09:03:25 -07:00
sdk . NewAttribute ( types . AttributeKeyProposalResult , tagValue ) ,
) ,
)
2019-06-04 11:38:11 -07:00
return false
} )
2019-02-08 18:33:06 -08:00
}