-
Notifications
You must be signed in to change notification settings - Fork 11
/
handler.go
157 lines (132 loc) · 4.69 KB
/
handler.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package validator
import (
"fmt"
"github.com/celer-network/sgn/seal"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// NewHandler returns a handler for "validator" type messages.
func NewHandler(keeper Keeper) sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
logEntry := seal.NewMsgLog()
ctx = ctx.WithEventManager(sdk.NewEventManager())
var res *sdk.Result
var err error
switch msg := msg.(type) {
case MsgSetTransactors:
res, err = handleMsgSetTransactors(ctx, keeper, msg, logEntry)
case MsgEditCandidateDescription:
res, err = handleMsgEditCandidateDescription(ctx, keeper, msg, logEntry)
case MsgWithdrawReward:
res, err = handleMsgWithdrawReward(ctx, keeper, msg, logEntry)
case MsgSignReward:
res, err = handleMsgSignReward(ctx, keeper, msg, logEntry)
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg)
}
if err != nil {
logEntry.Error = append(logEntry.Error, err.Error())
}
seal.CommitMsgLog(logEntry)
return res, err
}
}
// Handle a message to set transactors
func handleMsgSetTransactors(ctx sdk.Context, keeper Keeper, msg MsgSetTransactors, logEntry *seal.MsgLog) (*sdk.Result, error) {
logEntry.Type = msg.Type()
logEntry.Sender = msg.Sender.String()
validator, found := keeper.GetValidator(ctx, sdk.ValAddress(msg.Sender))
if !found {
return nil, fmt.Errorf("Sender is not a validator")
}
candidate, found := keeper.GetCandidate(ctx, validator.Description.Identity)
if !found {
return nil, fmt.Errorf("Candidate does not exist")
}
dedup := make(map[string]bool)
oldTransactors := candidate.Transactors
candidate.Transactors = []sdk.AccAddress{}
for _, transactor := range msg.Transactors {
if !transactor.Equals(candidate.ValAccount) {
if _, exist := dedup[transactor.String()]; !exist {
logEntry.Transactor = append(logEntry.Transactor, transactor.String())
candidate.Transactors = append(candidate.Transactors, transactor)
dedup[transactor.String()] = true
keeper.InitAccount(ctx, transactor)
}
}
}
for _, transactor := range oldTransactors {
if _, exist := dedup[transactor.String()]; !exist {
keeper.RemoveAccount(ctx, transactor)
}
}
keeper.SetCandidate(ctx, candidate)
return &sdk.Result{}, nil
}
// Handle a message to edit candidate description
func handleMsgEditCandidateDescription(ctx sdk.Context, keeper Keeper, msg MsgEditCandidateDescription, logEntry *seal.MsgLog) (*sdk.Result, error) {
logEntry.Type = msg.Type()
logEntry.Sender = msg.Sender.String()
logEntry.EthAddress = msg.EthAddress
candidate, found := keeper.GetCandidate(ctx, msg.EthAddress)
if !found {
return nil, fmt.Errorf("Candidate does not exist")
}
description, err := candidate.Description.UpdateDescription(msg.Description)
if err != nil {
return nil, err
}
candidate.Description = description
keeper.SetCandidate(ctx, candidate)
return &sdk.Result{}, nil
}
// Handle a message to withdraw reward
func handleMsgWithdrawReward(ctx sdk.Context, keeper Keeper, msg MsgWithdrawReward, logEntry *seal.MsgLog) (*sdk.Result, error) {
logEntry.Type = msg.Type()
logEntry.Sender = msg.Sender.String()
logEntry.EthAddress = msg.EthAddress
reward, found := keeper.GetReward(ctx, msg.EthAddress)
if !found {
return nil, fmt.Errorf("Reward does not exist")
}
if ctx.BlockTime().Before(reward.LastWithdrawTime.Add(keeper.WithdrawWindow(ctx))) {
logEntry.Warn = append(logEntry.Warn, "Request too fast")
return &sdk.Result{}, nil
}
reward.InitateWithdraw(ctx.BlockTime())
keeper.SetReward(ctx, reward)
ctx.EventManager().EmitEvent(
sdk.NewEvent(
ModuleName,
sdk.NewAttribute(sdk.AttributeKeyAction, ActionInitiateWithdraw),
sdk.NewAttribute(AttributeKeyEthAddress, msg.EthAddress),
),
)
return &sdk.Result{
Events: ctx.EventManager().Events(),
}, nil
}
// Handle a message to sign reward
func handleMsgSignReward(ctx sdk.Context, keeper Keeper, msg MsgSignReward, logEntry *seal.MsgLog) (*sdk.Result, error) {
logEntry.Type = msg.Type()
logEntry.Sender = msg.Sender.String()
logEntry.EthAddress = msg.EthAddress
validator, found := keeper.stakingKeeper.GetValidator(ctx, sdk.ValAddress(msg.Sender))
if !found {
return nil, fmt.Errorf("Sender is not validator")
}
if validator.Status != sdk.Bonded {
return nil, fmt.Errorf("Validator is not bonded")
}
reward, found := keeper.GetReward(ctx, msg.EthAddress)
if !found {
return nil, fmt.Errorf("Reward does not exist")
}
err := reward.AddSig(msg.Sig, validator.Description.Identity)
if err != nil {
return nil, fmt.Errorf("Failed to add sig: %s", err)
}
keeper.SetReward(ctx, reward)
return &sdk.Result{}, nil
}