github.com/Finschia/finschia-sdk@v0.48.1/x/gov/abci.go (about) 1 package gov 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/Finschia/finschia-sdk/telemetry" 8 sdk "github.com/Finschia/finschia-sdk/types" 9 "github.com/Finschia/finschia-sdk/x/gov/keeper" 10 "github.com/Finschia/finschia-sdk/x/gov/types" 11 ) 12 13 // EndBlocker called every block, process inflation, update validator set. 14 func EndBlocker(ctx sdk.Context, keeper keeper.Keeper) { 15 defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker) 16 17 logger := keeper.Logger(ctx) 18 19 // delete inactive proposal from store and its deposits 20 keeper.IterateInactiveProposalsQueue(ctx, ctx.BlockHeader().Time, func(proposal types.Proposal) bool { 21 keeper.DeleteProposal(ctx, proposal.ProposalId) 22 keeper.DeleteDeposits(ctx, proposal.ProposalId) 23 24 // called when proposal become inactive 25 keeper.AfterProposalFailedMinDeposit(ctx, proposal.ProposalId) 26 27 ctx.EventManager().EmitEvent( 28 sdk.NewEvent( 29 types.EventTypeInactiveProposal, 30 sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposal.ProposalId)), 31 sdk.NewAttribute(types.AttributeKeyProposalResult, types.AttributeValueProposalDropped), 32 ), 33 ) 34 35 logger.Info( 36 "proposal did not meet minimum deposit; deleted", 37 "proposal", proposal.ProposalId, 38 "title", proposal.GetTitle(), 39 "min_deposit", keeper.GetDepositParams(ctx).MinDeposit.String(), 40 "total_deposit", proposal.TotalDeposit.String(), 41 ) 42 43 return false 44 }) 45 46 // fetch active proposals whose voting periods have ended (are passed the block time) 47 keeper.IterateActiveProposalsQueue(ctx, ctx.BlockHeader().Time, func(proposal types.Proposal) bool { 48 var tagValue, logMsg string 49 50 passes, burnDeposits, tallyResults := keeper.Tally(ctx, proposal) 51 52 if burnDeposits { 53 keeper.DeleteDeposits(ctx, proposal.ProposalId) 54 } else { 55 keeper.RefundDeposits(ctx, proposal.ProposalId) 56 } 57 58 if passes { 59 handler := keeper.Router().GetRoute(proposal.ProposalRoute()) 60 cacheCtx, writeCache := ctx.CacheContext() 61 62 // The proposal handler may execute state mutating logic depending 63 // on the proposal content. If the handler fails, no state mutation 64 // is written and the error message is logged. 65 err := handler(cacheCtx, proposal.GetContent()) 66 if err == nil { 67 proposal.Status = types.StatusPassed 68 tagValue = types.AttributeValueProposalPassed 69 logMsg = "passed" 70 71 // The cached context is created with a new EventManager. However, since 72 // the proposal handler execution was successful, we want to track/keep 73 // any events emitted, so we re-emit to "merge" the events into the 74 // original Context's EventManager. 75 ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events()) 76 77 // write state to the underlying multi-store 78 writeCache() 79 } else { 80 proposal.Status = types.StatusFailed 81 tagValue = types.AttributeValueProposalFailed 82 logMsg = fmt.Sprintf("passed, but failed on execution: %s", err) 83 } 84 } else { 85 proposal.Status = types.StatusRejected 86 tagValue = types.AttributeValueProposalRejected 87 logMsg = "rejected" 88 } 89 90 proposal.FinalTallyResult = tallyResults 91 92 keeper.SetProposal(ctx, proposal) 93 keeper.RemoveFromActiveProposalQueue(ctx, proposal.ProposalId, proposal.VotingEndTime) 94 95 // when proposal become active 96 keeper.AfterProposalVotingPeriodEnded(ctx, proposal.ProposalId) 97 98 logger.Info( 99 "proposal tallied", 100 "proposal", proposal.ProposalId, 101 "title", proposal.GetTitle(), 102 "result", logMsg, 103 ) 104 105 ctx.EventManager().EmitEvent( 106 sdk.NewEvent( 107 types.EventTypeActiveProposal, 108 sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposal.ProposalId)), 109 sdk.NewAttribute(types.AttributeKeyProposalResult, tagValue), 110 ), 111 ) 112 return false 113 }) 114 }