/
msg_server.go
138 lines (109 loc) · 4.28 KB
/
msg_server.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
package keeper
import (
"context"
"fmt"
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/settlus/chain/x/oracle/types"
)
type msgServer struct {
Keeper
}
// NewMsgServerImpl returns an implementation of the MsgServer interface
// for the provided Keeper.
func NewMsgServerImpl(keeper Keeper) types.MsgServer {
return &msgServer{Keeper: keeper}
}
var _ types.MsgServer = msgServer{}
func (m msgServer) Prevote(goCtx context.Context, prevote *types.MsgPrevote) (*types.MsgPrevoteResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
roundInfo := m.GetCurrentRoundInfo(ctx)
if roundInfo == nil || roundInfo.Id != prevote.RoundId {
return nil, errorsmod.Wrapf(types.ErrPrevotesNotAccepted, "round info not found for the round id (%d)", prevote.RoundId)
}
if ctx.BlockHeight() > roundInfo.PrevoteEnd {
return nil, errorsmod.Wrapf(types.ErrPrevotesNotAccepted, "prevote period is over")
}
// validator and feeder addresses are validated in the ValidateBasic()
if v, err := m.ValidateFeeder(ctx, prevote.Feeder, prevote.Validator); err != nil && v {
return nil, err
}
aggregatePrevote := types.AggregatePrevote{
Hash: prevote.Hash,
Voter: prevote.Validator,
}
m.SetAggregatePrevote(ctx, aggregatePrevote)
if err := ctx.EventManager().EmitTypedEvent(&types.EventPrevote{
Feeder: prevote.Feeder,
Validator: prevote.Validator,
Hash: prevote.Hash,
}); err != nil {
return nil, fmt.Errorf("failed to emit event (%s)", err)
}
return &types.MsgPrevoteResponse{}, nil
}
func (m msgServer) Vote(goCtx context.Context, vote *types.MsgVote) (*types.MsgVoteResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
roundInfo := m.GetCurrentRoundInfo(ctx)
if roundInfo == nil || roundInfo.Id != vote.RoundId {
return nil, errorsmod.Wrapf(types.ErrPrevotesNotAccepted, "round info not found for the round id (%d)", vote.RoundId)
}
if ctx.BlockHeight() > roundInfo.VoteEnd {
return nil, errorsmod.Wrapf(types.ErrPrevotesNotAccepted, "vote period is over")
}
if !types.ValidateVoteData(vote.VoteData, m.GetParams(ctx).GetWhitelistChainIds()) {
return nil, errorsmod.Wrapf(types.ErrInvalidVote, "invalid vote data")
}
// validator and feeder addresses are validated in the ValidateBasic()
if v, err := m.ValidateFeeder(ctx, vote.Feeder, vote.Validator); err != nil && v {
return nil, err
}
// Check if the prevote exists
aggregatePrevote := m.GetAggregatePrevote(ctx, vote.Validator)
if aggregatePrevote == nil {
return nil, fmt.Errorf("aggregate prevote not found")
}
// Check if the vote matches the aggregate prevote hash
hash, err := types.GetAggregateVoteHash(vote.VoteData, vote.Salt)
if err != nil {
return nil, fmt.Errorf("failed to get aggregate vote hash (%s)", err)
}
if aggregatePrevote.Hash != hash {
return nil, errorsmod.Wrapf(types.ErrInvalidVote, "hash submitted in prevote (%s) does not match the hash of the vote (%s)", aggregatePrevote.Hash, hash)
}
aggregateVote := types.AggregateVote{
VoteData: vote.VoteData,
Voter: vote.Validator,
}
m.SetAggregateVote(ctx, aggregateVote)
m.DeleteAggregatePrevote(ctx, vote.Validator)
err = ctx.EventManager().EmitTypedEvent(&types.EventVote{
Feeder: vote.Feeder,
Validator: vote.Validator,
VoteData: vote.VoteData,
})
if err != nil {
return nil, fmt.Errorf("failed to emit event (%s)", err)
}
return &types.MsgVoteResponse{}, nil
}
func (m msgServer) FeederDelegationConsent(goCtx context.Context, consent *types.MsgFeederDelegationConsent) (*types.MsgFeederDelegationConsentResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// validator and feeder addresses are validated in the ValidateBasic()
validator, _ := sdk.ValAddressFromBech32(consent.Validator)
if val, found := m.StakingKeeper.GetValidator(ctx, validator); !found || !val.IsBonded() {
return nil, errorsmod.Wrapf(types.ErrValidatorNotFound, "validator %s is not active", validator.String())
}
err := m.SetFeederDelegation(ctx, consent.Validator, consent.FeederAddress)
if err != nil {
return nil, err
}
err = ctx.EventManager().EmitTypedEvent(&types.EventFeederDelegationConsent{
Feeder: consent.FeederAddress,
Validator: consent.Validator,
})
if err != nil {
return nil, fmt.Errorf("failed to emit event (%s)", err)
}
return &types.MsgFeederDelegationConsentResponse{}, nil
}