Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: pull out hop validation and consolidate for transfer+packet #6695

45 changes: 26 additions & 19 deletions modules/apps/transfer/types/forwarding.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,8 @@ func NewForwarding(unwind bool, hops ...Hop) Forwarding {

// Validate performs a basic validation of the Forwarding fields.
func (fi Forwarding) Validate() error {
if len(fi.Hops) > MaximumNumberOfForwardingHops {
return errorsmod.Wrapf(ErrInvalidForwarding, "number of hops in forwarding cannot exceed %d", MaximumNumberOfForwardingHops)
}

for _, hop := range fi.Hops {
if err := host.PortIdentifierValidator(hop.PortId); err != nil {
return errorsmod.Wrapf(err, "invalid hop source port ID %s", hop.PortId)
}
if err := host.ChannelIdentifierValidator(hop.ChannelId); err != nil {
return errorsmod.Wrapf(err, "invalid source channel ID %s", hop.ChannelId)
}
if err := ValidateHops(fi.Hops); err != nil {
return errorsmod.Wrapf(ErrInvalidForwarding, "invalid hops in forwarding")
}

return nil
Expand All @@ -44,8 +35,8 @@ func NewForwardingPacketData(destinationMemo string, hops ...Hop) ForwardingPack

// Validate performs a basic validation of the ForwardingPacketData fields.
func (fi ForwardingPacketData) Validate() error {
if len(fi.Hops) > MaximumNumberOfForwardingHops {
return errorsmod.Wrapf(ErrInvalidForwarding, "number of hops in forwarding packet data cannot exceed %d", MaximumNumberOfForwardingHops)
if err := ValidateHops(fi.Hops); err != nil {
return errorsmod.Wrapf(ErrInvalidForwarding, "invalid hops in forwarding packet data")
}

if len(fi.DestinationMemo) > MaximumMemoLength {
Expand All @@ -56,14 +47,30 @@ func (fi ForwardingPacketData) Validate() error {
return errorsmod.Wrap(ErrInvalidForwarding, "memo specified when forwarding packet data hops is empty")
}

for _, hop := range fi.Hops {
if err := host.PortIdentifierValidator(hop.PortId); err != nil {
return errorsmod.Wrapf(err, "invalid source port ID %s", hop.PortId)
}
if err := host.ChannelIdentifierValidator(hop.ChannelId); err != nil {
return errorsmod.Wrapf(err, "invalid source channel ID %s", hop.ChannelId)
return nil
}

func ValidateHops(hops []Hop) error {
gjermundgaraba marked this conversation as resolved.
Show resolved Hide resolved
if len(hops) > MaximumNumberOfForwardingHops {
return errorsmod.Wrapf(ErrInvalidForwarding, "number of hops cannot exceed %d", MaximumNumberOfForwardingHops)
}

for _, hop := range hops {
if err := hop.Validate(); err != nil {
return err
}
}

return nil
}

func (h Hop) Validate() error {
gjermundgaraba marked this conversation as resolved.
Show resolved Hide resolved
if err := host.PortIdentifierValidator(h.PortId); err != nil {
return errorsmod.Wrapf(err, "invalid hop source port ID %s", h.PortId)
}
if err := host.ChannelIdentifierValidator(h.ChannelId); err != nil {
return errorsmod.Wrapf(err, "invalid source channel ID %s", h.ChannelId)
}

return nil
}
159 changes: 147 additions & 12 deletions modules/apps/transfer/types/forwarding_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestForwarding_Validate(t *testing.T) {
ChannelId: ibctesting.FirstChannelID,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"invalid forwarding with too long hop port ID",
Expand All @@ -61,7 +61,7 @@ func TestForwarding_Validate(t *testing.T) {
ChannelId: ibctesting.FirstChannelID,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"invalid forwarding with non-alpha hop port ID",
Expand All @@ -72,7 +72,7 @@ func TestForwarding_Validate(t *testing.T) {
ChannelId: ibctesting.FirstChannelID,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"invalid forwarding with too long hop channel ID",
Expand All @@ -83,7 +83,7 @@ func TestForwarding_Validate(t *testing.T) {
ChannelId: invalidLongChannel,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"invalid forwarding with too short hop channel ID",
Expand All @@ -94,7 +94,7 @@ func TestForwarding_Validate(t *testing.T) {
ChannelId: invalidShortChannel,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"invalid forwarding with non-alpha hop channel ID",
Expand All @@ -105,7 +105,7 @@ func TestForwarding_Validate(t *testing.T) {
ChannelId: invalidChannel,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
}
for _, tc := range tests {
Expand Down Expand Up @@ -179,7 +179,7 @@ func TestForwardingPacketData_Validate(t *testing.T) {
ChannelId: ibctesting.FirstChannelID,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"invalid forwarding with too long hop port ID",
Expand All @@ -190,7 +190,7 @@ func TestForwardingPacketData_Validate(t *testing.T) {
ChannelId: ibctesting.FirstChannelID,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"invalid forwarding with non-alpha hop port ID",
Expand All @@ -201,7 +201,7 @@ func TestForwardingPacketData_Validate(t *testing.T) {
ChannelId: ibctesting.FirstChannelID,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"invalid forwarding with too long hop channel ID",
Expand All @@ -212,7 +212,7 @@ func TestForwardingPacketData_Validate(t *testing.T) {
ChannelId: invalidLongChannel,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"invalid forwarding with too short hop channel ID",
Expand All @@ -223,7 +223,7 @@ func TestForwardingPacketData_Validate(t *testing.T) {
ChannelId: invalidShortChannel,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"invalid forwarding with non-alpha hop channel ID",
Expand All @@ -234,7 +234,7 @@ func TestForwardingPacketData_Validate(t *testing.T) {
ChannelId: invalidChannel,
},
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
}
for _, tc := range tests {
Expand All @@ -253,6 +253,141 @@ func TestForwardingPacketData_Validate(t *testing.T) {
}
}

func TestHop_Validate(t *testing.T) {
gjermundgaraba marked this conversation as resolved.
Show resolved Hide resolved
tests := []struct {
name string
hop types.Hop
expError error
}{
{
"valid hop",
validHop,
nil,
},
{
"invalid hop with too short port ID",
types.Hop{
PortId: invalidShortPort,
ChannelId: ibctesting.FirstChannelID,
},
host.ErrInvalidID,
},
{
"invalid hop with too long port ID",
types.Hop{
PortId: invalidLongPort,
ChannelId: ibctesting.FirstChannelID,
},
host.ErrInvalidID,
},
{
"invalid hop with non-alpha port ID",
types.Hop{
PortId: invalidPort,
ChannelId: ibctesting.FirstChannelID,
},
host.ErrInvalidID,
},
{
"invalid hop with too long channel ID",
types.Hop{
PortId: types.PortID,
ChannelId: invalidLongChannel,
},
host.ErrInvalidID,
},
{
"invalid hop with too short channel ID",
types.Hop{
PortId: types.PortID,
ChannelId: invalidShortChannel,
},
host.ErrInvalidID,
},
{
"invalid hop with non-alpha channel ID",
types.Hop{
PortId: types.PortID,
ChannelId: invalidChannel,
},
host.ErrInvalidID,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
tc := tc

err := tc.hop.Validate()

expPass := tc.expError == nil
if expPass {
require.NoError(t, err)
} else {
require.ErrorIs(t, err, tc.expError)
}
})
}
}

func TestValidateHops(t *testing.T) {
tests := []struct {
name string
hops []types.Hop
expError error
}{
{
"valid hops",
[]types.Hop{validHop},
nil,
},
{
"valid hops with max hops",
generateHops(types.MaximumNumberOfForwardingHops),
nil,
},
{
"invalid hops with too many hops",
generateHops(types.MaximumNumberOfForwardingHops + 1),
types.ErrInvalidForwarding,
},
{
"invalid hops with invalid port",
[]types.Hop{
{
PortId: invalidPort,
ChannelId: ibctesting.FirstChannelID,
},
},
host.ErrInvalidID,
},
{
"invalid hops with invalid channel",
[]types.Hop{
validHop,
{
PortId: types.PortID,
ChannelId: invalidChannel,
},
},
host.ErrInvalidID,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
tc := tc

err := types.ValidateHops(tc.hops)

expPass := tc.expError == nil
if expPass {
require.NoError(t, err)
} else {
require.ErrorIs(t, err, tc.expError)
}
})
}
}

// generateHops generates a slice of n correctly initialized hops.
func generateHops(n int) []types.Hop {
hops := make([]types.Hop, n)
Expand Down
4 changes: 2 additions & 2 deletions modules/apps/transfer/types/msgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ func TestMsgTransferValidation(t *testing.T) {
{"multidenom: too many coins", types.NewMsgTransfer(validPort, validChannel, make([]sdk.Coin, types.MaximumTokensLength+1), sender, receiver, clienttypes.ZeroHeight(), 100, "", emptyForwarding), ibcerrors.ErrInvalidCoins},
{"multidenom: both token and tokens are set", &types.MsgTransfer{validPort, validChannel, coin, sender, receiver, clienttypes.ZeroHeight(), 100, "", coins, emptyForwarding}, ibcerrors.ErrInvalidCoins},
{"timeout height must be zero if forwarding path hops is not empty", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, timeoutHeight, 100, "memo", types.NewForwarding(false, validHop)), types.ErrInvalidPacketTimeout},
{"invalid forwarding info port", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, types.Hop{PortId: invalidPort, ChannelId: validChannel})), host.ErrInvalidID},
{"invalid forwarding info channel", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, types.Hop{PortId: validPort, ChannelId: invalidChannel})), host.ErrInvalidID},
{"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},
{"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},
{"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},
{"unwind specified but source port is not empty", types.NewMsgTransfer(validPort, "", coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(true)), types.ErrInvalidForwarding},
{"unwind specified but source channel is not empty", types.NewMsgTransfer("", validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(true)), types.ErrInvalidForwarding},
Expand Down
5 changes: 2 additions & 3 deletions modules/apps/transfer/types/packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/stretchr/testify/require"

"github.com/cosmos/ibc-go/v8/modules/apps/transfer/types"
host "github.com/cosmos/ibc-go/v8/modules/core/24-host"
ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors"
ibctesting "github.com/cosmos/ibc-go/v8/testing"
)
Expand Down Expand Up @@ -428,7 +427,7 @@ func TestFungibleTokenPacketDataV2ValidateBasic(t *testing.T) {
},
),
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"failure: invalid forwarding path channel ID",
Expand All @@ -450,7 +449,7 @@ func TestFungibleTokenPacketDataV2ValidateBasic(t *testing.T) {
},
),
),
host.ErrInvalidID,
types.ErrInvalidForwarding,
},
{
"failure: invalid forwarding path too many hops",
Expand Down
Loading