Skip to content

Commit

Permalink
chore: add packet data validation back (#6704)
Browse files Browse the repository at this point in the history
  • Loading branch information
chatton authored and bznein committed Jun 26, 2024
1 parent eca8b0e commit 05d1d81
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 18 deletions.
2 changes: 2 additions & 0 deletions modules/apps/transfer/ibc_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ func (im IBCModule) OnRecvPacket(

ack := channeltypes.NewResultAcknowledgement([]byte{byte(1)})

// we are explicitly wrapping this emit event call in an anonymous function so that
// the packet data is evaluated after it has been assigned a value.
defer func() {
events.EmitOnRecvPacketEvent(ctx, data, ack, ackErr)
}()
Expand Down
2 changes: 1 addition & 1 deletion modules/apps/transfer/keeper/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ func (k Keeper) UnwindHops(ctx sdk.Context, msg *types.MsgTransfer) (*types.MsgT
}

// CreatePacketDataBytesFromVersion is a wrapper around createPacketDataBytesFromVersion for testing purposes
func CreatePacketDataBytesFromVersion(appVersion, sender, receiver, memo string, tokens types.Tokens, hops []types.Hop) []byte {
func CreatePacketDataBytesFromVersion(appVersion, sender, receiver, memo string, tokens types.Tokens, hops []types.Hop) ([]byte, error) {
return createPacketDataBytesFromVersion(appVersion, sender, receiver, memo, tokens, hops)
}
24 changes: 17 additions & 7 deletions modules/apps/transfer/keeper/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,10 @@ func (k Keeper) sendTransfer(
tokens = append(tokens, token)
}

packetDataBytes := createPacketDataBytesFromVersion(appVersion, sender.String(), receiver, memo, tokens, forwarding.Hops)
packetDataBytes, err := createPacketDataBytesFromVersion(appVersion, sender.String(), receiver, memo, tokens, forwarding.Hops)
if err != nil {
return 0, err
}

sequence, err := k.ics4Wrapper.SendPacket(ctx, channelCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, packetDataBytes)
if err != nil {
Expand Down Expand Up @@ -438,8 +441,7 @@ func (k Keeper) tokenFromCoin(ctx sdk.Context, coin sdk.Coin) (types.Token, erro
}

// createPacketDataBytesFromVersion creates the packet data bytes to be sent based on the application version.
func createPacketDataBytesFromVersion(appVersion, sender, receiver, memo string, tokens types.Tokens, hops []types.Hop) []byte {
var packetDataBytes []byte
func createPacketDataBytesFromVersion(appVersion, sender, receiver, memo string, tokens types.Tokens, hops []types.Hop) ([]byte, error) {
switch appVersion {
case types.V1:
// Sanity check, tokens must always be of length 1 if using app version V1.
Expand All @@ -449,7 +451,12 @@ func createPacketDataBytesFromVersion(appVersion, sender, receiver, memo string,

token := tokens[0]
packetData := types.NewFungibleTokenPacketData(token.Denom.Path(), token.Amount, sender, receiver, memo)
packetDataBytes = packetData.GetBytes()

if err := packetData.ValidateBasic(); err != nil {
return nil, errorsmod.Wrapf(err, "failed to validate %s packet data", types.V1)
}

return packetData.GetBytes(), nil
case types.V2:
// If forwarding is needed, move memo to forwarding packet data and set packet.Memo to empty string.
var forwardingPacketData types.ForwardingPacketData
Expand All @@ -459,12 +466,15 @@ func createPacketDataBytesFromVersion(appVersion, sender, receiver, memo string,
}

packetData := types.NewFungibleTokenPacketDataV2(tokens, sender, receiver, memo, forwardingPacketData)
packetDataBytes = packetData.GetBytes()

if err := packetData.ValidateBasic(); err != nil {
return nil, errorsmod.Wrapf(err, "failed to validate %s packet data", types.V2)
}

return packetData.GetBytes(), nil
default:
panic(fmt.Errorf("app version must be one of %s", types.SupportedVersions))
}

return packetDataBytes
}

// burnCoin sends coins from the account to the transfer module account and then burn them.
Expand Down
61 changes: 51 additions & 10 deletions modules/apps/transfer/keeper/relay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1287,34 +1287,61 @@ func (suite *KeeperTestSuite) TestPacketForwardsCompatibility() {

func (suite *KeeperTestSuite) TestCreatePacketDataBytesFromVersion() {
var (
bz []byte
tokens types.Tokens
bz []byte
tokens types.Tokens
sender, receiver string
)

testCases := []struct {
name string
appVersion string
malleate func()
expResult func(bz []byte)
expResult func(bz []byte, err error)
expPanicErr error
}{
{
"success",
types.V1,
func() {},
func(bz []byte) {
expPacketData := types.NewFungibleTokenPacketData("", "", "", "", "")
func(bz []byte, err error) {
expPacketData := types.NewFungibleTokenPacketData(ibctesting.TestCoin.Denom, ibctesting.TestCoin.Amount.String(), sender, receiver, "")
suite.Require().Equal(bz, expPacketData.GetBytes())
suite.Require().NoError(err)
},
nil,
},
{
"success: version 2",
types.V2,
func() {},
func(bz []byte) {
expPacketData := types.NewFungibleTokenPacketDataV2(types.Tokens{types.Token{}}, "", "", "", emptyForwardingPacketData)
func(bz []byte, err error) {
expPacketData := types.NewFungibleTokenPacketDataV2(tokens, sender, receiver, "", emptyForwardingPacketData)
suite.Require().Equal(bz, expPacketData.GetBytes())
suite.Require().NoError(err)
},
nil,
},
{
"failure: fails v1 validation",
types.V1,
func() {
sender = ""
},
func(bz []byte, err error) {
suite.Require().Nil(bz)
suite.Require().ErrorIs(err, ibcerrors.ErrInvalidAddress)
},
nil,
},
{
"failure: fails v2 validation",
types.V2,
func() {
sender = ""
},
func(bz []byte, err error) {
suite.Require().Nil(bz)
suite.Require().ErrorIs(err, ibcerrors.ErrInvalidAddress)
},
nil,
},
Expand All @@ -1338,20 +1365,34 @@ func (suite *KeeperTestSuite) TestCreatePacketDataBytesFromVersion() {

for _, tc := range testCases {
suite.Run(tc.name, func() {
tokens = types.Tokens{types.Token{}}
suite.SetupTest()

path := ibctesting.NewTransferPath(suite.chainA, suite.chainB)
path.Setup()

tokens = types.Tokens{
{
Amount: ibctesting.TestCoin.Amount.String(),
Denom: types.NewDenom(ibctesting.TestCoin.Denom),
},
}

sender = suite.chainA.SenderAccount.GetAddress().String()
receiver = suite.chainB.SenderAccount.GetAddress().String()

tc.malleate()

var err error
createFunc := func() {
bz = transferkeeper.CreatePacketDataBytesFromVersion(tc.appVersion, "", "", "", tokens, nil)
bz, err = transferkeeper.CreatePacketDataBytesFromVersion(tc.appVersion, sender, receiver, "", tokens, nil)
}

expPanic := tc.expPanicErr != nil
if expPanic {
suite.Require().PanicsWithError(tc.expPanicErr.Error(), createFunc)
} else {
createFunc()
tc.expResult(bz)
tc.expResult(bz, err)
}
})
}
Expand Down

0 comments on commit 05d1d81

Please sign in to comment.