/
abci.go
109 lines (89 loc) · 3.06 KB
/
abci.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package membership
import (
"fmt"
"time"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
v1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
"github.com/noria-net/module-membership/x/membership/keeper"
"github.com/noria-net/module-membership/x/membership/types"
)
func EndBlocker(ctx sdk.Context, keeper *keeper.Keeper) {
defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyEndBlocker)
// fetch active proposals whose voting periods have ended (are passed the block time)
keeper.IterateActiveProposalsQueue(ctx, ctx.BlockHeader().Time, func(proposal v1.Proposal) (stop bool) {
return processActiveProposal(ctx, keeper, proposal)
})
}
func processActiveProposal(ctx sdk.Context, keeper *keeper.Keeper, proposal v1.Proposal) (stop bool) {
logger := keeper.Logger(ctx)
var tagValue, logMsg string
passes, burnDeposits, tallyResults := keeper.Tally(ctx, proposal)
if burnDeposits {
keeper.DeleteAndBurnDeposits(ctx, proposal.Id)
} else {
keeper.RefundAndDeleteDeposits(ctx, proposal.Id)
}
if passes {
var (
idx int
events sdk.Events
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.
cacheCtx, writeCache := ctx.CacheContext()
messages, err := proposal.GetMsgs()
if err == nil {
for idx, msg = range messages {
handler := keeper.GovRouter().Handler(msg)
var res *sdk.Result
res, err = handler(cacheCtx, msg)
if err != nil {
break
}
events = append(events, res.GetEvents()...)
}
}
// `err == nil` when all handlers passed.
// Or else, `idx` and `err` are populated with the msg index and error.
if err == nil {
proposal.Status = v1.StatusPassed
tagValue = govtypes.AttributeValueProposalPassed
logMsg = "passed"
// write state to the underlying multi-store
writeCache()
// propagate the msg events to the current context
ctx.EventManager().EmitEvents(events)
} else {
proposal.Status = v1.StatusFailed
tagValue = govtypes.AttributeValueProposalFailed
logMsg = fmt.Sprintf("passed, but msg %d (%s) failed on execution: %s", idx, sdk.MsgTypeURL(msg), err)
}
} else {
proposal.Status = v1.StatusRejected
tagValue = govtypes.AttributeValueProposalRejected
logMsg = "rejected"
}
proposal.FinalTallyResult = &tallyResults
keeper.SetProposal(ctx, proposal)
keeper.RemoveFromActiveProposalQueue(ctx, proposal.Id, *proposal.VotingEndTime)
// when proposal become active
keeper.GovHooks().AfterProposalVotingPeriodEnded(ctx, proposal.Id)
logger.Info(
"proposal tallied",
"proposal", proposal.Id,
"results", logMsg,
)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
govtypes.EventTypeActiveProposal,
sdk.NewAttribute(govtypes.AttributeKeyProposalID, fmt.Sprintf("%d", proposal.Id)),
sdk.NewAttribute(govtypes.AttributeKeyProposalResult, tagValue),
),
)
return false
}