/
acknowledge_bridges.go
139 lines (124 loc) · 4.06 KB
/
acknowledge_bridges.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
package process
import (
"reflect"
gometrics "github.com/armon/go-metrics"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/dydxprotocol/v4-chain/protocol/lib/metrics"
"github.com/dydxprotocol/v4-chain/protocol/x/bridge/types"
)
var (
msgAcknowledgeBridgesType = reflect.TypeOf(types.MsgAcknowledgeBridges{})
)
// AcknowledgeBridgesTx represents `MsgAcknowledgeBridge`s tx that can be validated.
type AcknowledgeBridgesTx struct {
ctx sdk.Context
bridgeKeeper ProcessBridgeKeeper
msg *types.MsgAcknowledgeBridges
}
// DecodeAcknowledgeBridgesTx returns a new `AcknowledgeBridgesTx` after validating the following:
// - decodes the given tx bytes
// - checks the msg is of expected type
//
// If error occurs during any of the checks, returns error.
func DecodeAcknowledgeBridgesTx(
ctx sdk.Context,
bridgeKeeper ProcessBridgeKeeper,
decoder sdk.TxDecoder,
txBytes []byte,
) (*AcknowledgeBridgesTx, error) {
// Decode.
tx, err := decoder(txBytes)
if err != nil {
return nil, getDecodingError(msgAcknowledgeBridgesType, err)
}
// Check msg length.
msgs := tx.GetMsgs()
if len(msgs) != 1 {
return nil, getUnexpectedNumMsgsError(msgAcknowledgeBridgesType, 1, len(msgs))
}
// Check msg type.
acknowledgeBridges, ok := msgs[0].(*types.MsgAcknowledgeBridges)
if !ok {
return nil, getUnexpectedMsgTypeError(msgAcknowledgeBridgesType, msgs[0])
}
return &AcknowledgeBridgesTx{
ctx: ctx,
bridgeKeeper: bridgeKeeper,
msg: acknowledgeBridges,
}, nil
}
// Validate returns an error if:
// - msg fails `ValidateBasic`.
// - bridge events are non empty and bridging is disabled.
// - first bridge event ID is not the one to be next acknowledged.
// - last bridge event ID has not been recognized.
// - a bridge event's content is not the same as in server state.
func (abt *AcknowledgeBridgesTx) Validate() error {
// `ValidateBasic` validates that bridge event IDs are consecutive.
if err := abt.msg.ValidateBasic(); err != nil {
telemetry.IncrCounterWithLabels(
[]string{
ModuleName,
metrics.AcknowledgeBridgesTx,
metrics.Validate,
metrics.Error,
},
1,
[]gometrics.Label{metrics.GetLabelForStringValue(metrics.Error, metrics.ValidateBasic)},
)
return getValidateBasicError(abt.msg, err)
}
if len(abt.msg.Events) == 0 {
// If there is no bridge event, return nil.
return nil
} else if abt.bridgeKeeper.GetSafetyParams(abt.ctx).IsDisabled {
// If there is any bridge event when bridging is disabled, return error.
return types.ErrBridgingDisabled
}
// Validate that first bridge event ID is the one to be next acknowledged.
acknowledgedEventInfo := abt.bridgeKeeper.GetAcknowledgedEventInfo(abt.ctx)
if acknowledgedEventInfo.NextId != abt.msg.Events[0].Id {
telemetry.IncrCounterWithLabels(
[]string{
ModuleName,
metrics.AcknowledgeBridgesTx,
metrics.Validate,
metrics.Error,
},
1,
[]gometrics.Label{metrics.GetLabelForStringValue(metrics.Error, types.ErrBridgeIdNotNextToAcknowledge.Error())},
)
return types.ErrBridgeIdNotNextToAcknowledge
}
// Validate that last bridge event ID has been recognized.
recognizedEventInfo := abt.bridgeKeeper.GetRecognizedEventInfo(abt.ctx)
if recognizedEventInfo.NextId <= abt.msg.Events[len(abt.msg.Events)-1].Id {
telemetry.IncrCounterWithLabels(
[]string{
ModuleName,
metrics.AcknowledgeBridgesTx,
metrics.Validate,
metrics.Error,
},
1,
[]gometrics.Label{metrics.GetLabelForStringValue(metrics.Error, types.ErrBridgeIdNotRecognized.Error())},
)
return types.ErrBridgeIdNotRecognized
}
// Validate that bridge events' content is the same as in server state.
for _, event := range abt.msg.Events {
eventInState, found := abt.bridgeKeeper.GetBridgeEventFromServer(abt.ctx, event.Id)
if !found {
return types.ErrBridgeEventNotFound
}
if !eventInState.Equal(event) {
return types.ErrBridgeEventContentMismatch
}
}
return nil
}
// GetMsg returns the underlying `MsgAcknowledgeBridges`.
func (abt *AcknowledgeBridgesTx) GetMsg() sdk.Msg {
return abt.msg
}