Skip to content

Commit a27fc85

Browse files
Nikolas De GiorgisgjermundgarabaDimitrisJim
committed
(chore) Refactor code around forwarding validation (#6706)
* Refactor validation * Fixed verification logic, added two tests * Fix check for unwind * removed unneeded indirection * Update modules/apps/transfer/types/msgs.go Co-authored-by: DimitrisJim <d.f.hilliard@gmail.com> * Add docstring. --------- Co-authored-by: Gjermund Garaba <bjaanes@gmail.com> Co-authored-by: DimitrisJim <d.f.hilliard@gmail.com>
1 parent e7a8cfb commit a27fc85

File tree

2 files changed

+39
-35
lines changed

2 files changed

+39
-35
lines changed

modules/apps/transfer/types/msgs.go

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,22 @@ func NewMsgTransfer(
6969
// NOTE: The recipient addresses format is not validated as the format defined by
7070
// the chain is not known to IBC.
7171
func (msg MsgTransfer) ValidateBasic() error {
72-
if err := validateSourcePortAndChannel(msg); err != nil {
73-
return err // The actual error and its message are already wrapped in the called function.
72+
if err := msg.validateForwarding(); err != nil {
73+
return err
7474
}
75+
if !msg.Forwarding.Unwind {
76+
// We verify that portID and channelID are valid IDs only if
77+
// we are not setting unwind to true.
78+
// In that case, validation that they are empty is performed in
79+
// validateForwarding().
80+
if err := host.PortIdentifierValidator(msg.SourcePort); err != nil {
81+
return errorsmod.Wrap(err, "invalid source port ID")
82+
}
7583

84+
if err := host.ChannelIdentifierValidator(msg.SourceChannel); err != nil {
85+
return errorsmod.Wrap(err, "invalid source channel ID")
86+
}
87+
}
7688
if len(msg.Tokens) == 0 && !isValidIBCCoin(msg.Token) {
7789
return errorsmod.Wrap(ibcerrors.ErrInvalidCoins, "either token or token array must be filled")
7890
}
@@ -99,30 +111,42 @@ func (msg MsgTransfer) ValidateBasic() error {
99111
return errorsmod.Wrapf(ErrInvalidMemo, "memo must not exceed %d bytes", MaximumMemoLength)
100112
}
101113

114+
for _, coin := range msg.GetCoins() {
115+
if err := validateIBCCoin(coin); err != nil {
116+
return errorsmod.Wrapf(ibcerrors.ErrInvalidCoins, "%s: %s", err.Error(), coin.String())
117+
}
118+
}
119+
120+
return nil
121+
}
122+
123+
// validateForwarding ensures that forwarding is set up correctly.
124+
func (msg MsgTransfer) validateForwarding() error {
125+
if !msg.ShouldBeForwarded() {
126+
return nil
127+
}
102128
if err := msg.Forwarding.Validate(); err != nil {
103129
return err
104130
}
105131

106-
if msg.ShouldBeForwarded() {
132+
if !msg.TimeoutHeight.IsZero() {
107133
// when forwarding, the timeout height must not be set
108-
if !msg.TimeoutHeight.IsZero() {
109-
return errorsmod.Wrapf(ErrInvalidPacketTimeout, "timeout height must not be set if forwarding path hops is not empty: %s, %s", msg.TimeoutHeight, msg.Forwarding.Hops)
110-
}
134+
return errorsmod.Wrapf(ErrInvalidPacketTimeout, "timeout height must be zero if forwarding path hops is not empty: %s, %s", msg.TimeoutHeight, msg.Forwarding.Hops)
111135
}
112136

113137
if msg.Forwarding.Unwind {
114-
// When unwinding, we must have at most one token.
138+
if msg.SourcePort != "" {
139+
return errorsmod.Wrapf(ErrInvalidForwarding, "source port must be empty when unwind is set, got %s instead", msg.SourcePort)
140+
}
141+
if msg.SourceChannel != "" {
142+
return errorsmod.Wrapf(ErrInvalidForwarding, "source channel must be empty when unwind is set, got %s instead", msg.SourceChannel)
143+
}
115144
if len(msg.GetCoins()) > 1 {
145+
// When unwinding, we must have at most one token.
116146
return errorsmod.Wrap(ibcerrors.ErrInvalidCoins, "cannot unwind more than one token")
117147
}
118148
}
119149

120-
for _, coin := range msg.GetCoins() {
121-
if err := validateIBCCoin(coin); err != nil {
122-
return errorsmod.Wrapf(ibcerrors.ErrInvalidCoins, "%s: %s", err.Error(), coin.String())
123-
}
124-
}
125-
126150
return nil
127151
}
128152

@@ -164,25 +188,3 @@ func validateIBCCoin(coin sdk.Coin) error {
164188

165189
return nil
166190
}
167-
168-
func validateSourcePortAndChannel(msg MsgTransfer) error {
169-
// If unwind is set, we want to ensure that port and channel are empty.
170-
if msg.Forwarding.Unwind {
171-
if msg.SourcePort != "" {
172-
return errorsmod.Wrapf(ErrInvalidForwarding, "source port must be empty when unwind is set, got %s instead", msg.SourcePort)
173-
}
174-
if msg.SourceChannel != "" {
175-
return errorsmod.Wrapf(ErrInvalidForwarding, "source channel must be empty when unwind is set, got %s instead", msg.SourceChannel)
176-
}
177-
return nil
178-
}
179-
180-
// Otherwise, we just do the usual validation of the port and channel identifiers.
181-
if err := host.PortIdentifierValidator(msg.SourcePort); err != nil {
182-
return errorsmod.Wrap(err, "invalid source port ID")
183-
}
184-
if err := host.ChannelIdentifierValidator(msg.SourceChannel); err != nil {
185-
return errorsmod.Wrap(err, "invalid source channel ID")
186-
}
187-
return nil
188-
}

modules/apps/transfer/types/msgs_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ func TestMsgTransferValidation(t *testing.T) {
8787
{"invalid forwarding info port", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, types.Hop{PortId: invalidPort, ChannelId: validChannel})), types.ErrInvalidForwarding},
8888
{"invalid forwarding info channel", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, types.Hop{PortId: validPort, ChannelId: invalidChannel})), types.ErrInvalidForwarding},
8989
{"invalid forwarding info too many hops", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, generateHops(types.MaximumNumberOfForwardingHops+1)...)), types.ErrInvalidForwarding},
90+
{"invalid portID when forwarding is set but unwind is not", types.NewMsgTransfer("", validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, validHop)), host.ErrInvalidID},
91+
{"invalid channelID when forwarding is set but unwind is not", types.NewMsgTransfer(validPort, "", coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, validHop)), host.ErrInvalidID},
9092
{"unwind specified but source port is not empty", types.NewMsgTransfer(validPort, "", coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(true)), types.ErrInvalidForwarding},
9193
{"unwind specified but source channel is not empty", types.NewMsgTransfer("", validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(true)), types.ErrInvalidForwarding},
9294
{"unwind specified but more than one coin in the message", types.NewMsgTransfer("", "", coins.Add(sdk.NewCoin("atom", ibctesting.TestCoin.Amount)), sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(true)), ibcerrors.ErrInvalidCoins},

0 commit comments

Comments
 (0)