From d1fcea5c4847de2b37b670e7cb0d8ce6d6a83b39 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Wed, 30 Jun 2021 17:01:36 +0200 Subject: [PATCH 1/7] writeup simple antedecorator --- modules/core/04-channel/ante.go | 55 +++++++++++++++++++++++++ modules/core/04-channel/types/errors.go | 3 ++ 2 files changed, 58 insertions(+) create mode 100644 modules/core/04-channel/ante.go diff --git a/modules/core/04-channel/ante.go b/modules/core/04-channel/ante.go new file mode 100644 index 00000000000..75bd71cd229 --- /dev/null +++ b/modules/core/04-channel/ante.go @@ -0,0 +1,55 @@ +package channel + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/ibc-go/modules/core/04-channel/keeper" + "github.com/cosmos/ibc-go/modules/core/04-channel/types" +) + +type ChannelAnteDecorator struct { + k keeper.Keeper +} + +func NewChannelAnteDecorator(k keeper.Keeper) ChannelAnteDecorator { + return ChannelAnteDecorator{k: k} +} + +func (cad ChannelAnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { + // do not run redundancy check on simulate + if !simulate { + // keep track of total packet messages and number of redundancies across `RecvPacket`, `AcknowledgePacket`, and `TimeoutPacket/OnClose` + msgs := 0 + redundancies := 0 + for _, m := range tx.GetMsgs() { + if msg, ok := m.(*types.MsgRecvPacket); ok { + if _, found := cad.k.GetPacketReceipt(ctx, msg.Packet.GetDestPort(), msg.Packet.GetDestChannel(), msg.Packet.GetSequence()); found { + redundancies += 1 + } + msgs += 1 + } + if msg, ok := m.(*types.MsgAcknowledgement); ok { + if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + redundancies += 1 + } + msgs += 1 + } + if msg, ok := m.(*types.MsgTimeout); ok { + if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + redundancies += 1 + } + msgs += 1 + } + if msg, ok := m.(*types.MsgTimeoutOnClose); ok { + if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + redundancies += 1 + } + msgs += 1 + } + } + // return error if all packet messages are redundant + if redundancies == msgs && msgs > 0 { + return ctx, types.ErrRedundantTx + } + } + return next(ctx, tx, simulate) +} diff --git a/modules/core/04-channel/types/errors.go b/modules/core/04-channel/types/errors.go index 30293eddf07..74043730bf0 100644 --- a/modules/core/04-channel/types/errors.go +++ b/modules/core/04-channel/types/errors.go @@ -30,4 +30,7 @@ var ( // ORDERED channel error ErrPacketSequenceOutOfOrder = sdkerrors.Register(SubModuleName, 21, "packet sequence is out of order") + + // Antehandler error + ErrRedundantTx = sdkerrors.Register(SubModuleName, 22, "packet messages are redundant") ) From e92bcc4bfd1e503c9bf002a74165dacf799dba88 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Thu, 8 Jul 2021 12:02:34 +0200 Subject: [PATCH 2/7] only do antehandler on checkTx --- modules/core/04-channel/ante.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/core/04-channel/ante.go b/modules/core/04-channel/ante.go index 75bd71cd229..5d6c1482f0d 100644 --- a/modules/core/04-channel/ante.go +++ b/modules/core/04-channel/ante.go @@ -15,8 +15,8 @@ func NewChannelAnteDecorator(k keeper.Keeper) ChannelAnteDecorator { } func (cad ChannelAnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { - // do not run redundancy check on simulate - if !simulate { + // do not run redundancy check on DeliverTx or simulate + if (ctx.IsCheckTx() || ctx.IsReCheckTx()) && !simulate { // keep track of total packet messages and number of redundancies across `RecvPacket`, `AcknowledgePacket`, and `TimeoutPacket/OnClose` msgs := 0 redundancies := 0 From 689f49e9e70084c0aa04984817ff19e71310ed7c Mon Sep 17 00:00:00 2001 From: Aditya Date: Tue, 13 Jul 2021 12:31:59 +0200 Subject: [PATCH 3/7] Update modules/core/04-channel/ante.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: colin axnér <25233464+colin-axner@users.noreply.github.com> --- modules/core/04-channel/ante.go | 50 +++++++++++++++++---------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/modules/core/04-channel/ante.go b/modules/core/04-channel/ante.go index 5d6c1482f0d..d6d8d1ed997 100644 --- a/modules/core/04-channel/ante.go +++ b/modules/core/04-channel/ante.go @@ -21,30 +21,32 @@ func (cad ChannelAnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate msgs := 0 redundancies := 0 for _, m := range tx.GetMsgs() { - if msg, ok := m.(*types.MsgRecvPacket); ok { - if _, found := cad.k.GetPacketReceipt(ctx, msg.Packet.GetDestPort(), msg.Packet.GetDestChannel(), msg.Packet.GetSequence()); found { - redundancies += 1 - } - msgs += 1 - } - if msg, ok := m.(*types.MsgAcknowledgement); ok { - if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { - redundancies += 1 - } - msgs += 1 - } - if msg, ok := m.(*types.MsgTimeout); ok { - if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { - redundancies += 1 - } - msgs += 1 - } - if msg, ok := m.(*types.MsgTimeoutOnClose); ok { - if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { - redundancies += 1 - } - msgs += 1 - } + switch msg := m.(type) { + case *types.MsgRecvPacket: + if _, found := cad.k.GetPacketReceipt(ctx, msg.Packet.GetDestPort(), msg.Packet.GetDestChannel(), msg.Packet.GetSequence()); found { + redundancies += 1 + } + + case *types.MsgAcknowledgement: + if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + redundancies += 1 + } + + case *types.MsgTimeout: + if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + redundancies += 1 + } + + case *types.MsgTimeoutOnClose: + if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + redundancies += 1 + } + default: + continue + } + + msgs += 1 + } // return error if all packet messages are redundant if redundancies == msgs && msgs > 0 { From 3287553f1efee55a734407e3c51f6bc0ffaaffd6 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Fri, 16 Jul 2021 17:33:43 +0200 Subject: [PATCH 4/7] enable 2 antehandler strategies, and write tests --- modules/core/04-channel/ante.go | 63 ++--- modules/core/04-channel/ante_test.go | 332 ++++++++++++++++++++++++ modules/core/04-channel/channel_test.go | 37 +++ 3 files changed, 403 insertions(+), 29 deletions(-) create mode 100644 modules/core/04-channel/ante_test.go create mode 100644 modules/core/04-channel/channel_test.go diff --git a/modules/core/04-channel/ante.go b/modules/core/04-channel/ante.go index d6d8d1ed997..2675b649021 100644 --- a/modules/core/04-channel/ante.go +++ b/modules/core/04-channel/ante.go @@ -7,11 +7,12 @@ import ( ) type ChannelAnteDecorator struct { - k keeper.Keeper + k keeper.Keeper + strict bool } -func NewChannelAnteDecorator(k keeper.Keeper) ChannelAnteDecorator { - return ChannelAnteDecorator{k: k} +func NewChannelAnteDecorator(k keeper.Keeper, strict bool) ChannelAnteDecorator { + return ChannelAnteDecorator{k: k, strict: strict} } func (cad ChannelAnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { @@ -22,34 +23,38 @@ func (cad ChannelAnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate redundancies := 0 for _, m := range tx.GetMsgs() { switch msg := m.(type) { - case *types.MsgRecvPacket: - if _, found := cad.k.GetPacketReceipt(ctx, msg.Packet.GetDestPort(), msg.Packet.GetDestChannel(), msg.Packet.GetSequence()); found { - redundancies += 1 - } - - case *types.MsgAcknowledgement: - if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { - redundancies += 1 - } - - case *types.MsgTimeout: - if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { - redundancies += 1 - } - - case *types.MsgTimeoutOnClose: - if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { - redundancies += 1 - } - default: - continue - } - - msgs += 1 + case *types.MsgRecvPacket: + if _, found := cad.k.GetPacketReceipt(ctx, msg.Packet.GetDestPort(), msg.Packet.GetDestChannel(), msg.Packet.GetSequence()); found { + redundancies += 1 + } + + case *types.MsgAcknowledgement: + if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + redundancies += 1 + } + + case *types.MsgTimeout: + if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + redundancies += 1 + } + + case *types.MsgTimeoutOnClose: + if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + redundancies += 1 + } + default: + continue + } + + msgs += 1 } - // return error if all packet messages are redundant - if redundancies == msgs && msgs > 0 { + + if cad.strict && redundancies > 1 { + // if strict, return error on single redundancy + return ctx, types.ErrRedundantTx + } else if redundancies == msgs && msgs > 0 { + // if not strict, only return error if all packet messages are redundant return ctx, types.ErrRedundantTx } } diff --git a/modules/core/04-channel/ante_test.go b/modules/core/04-channel/ante_test.go new file mode 100644 index 00000000000..c51765ef993 --- /dev/null +++ b/modules/core/04-channel/ante_test.go @@ -0,0 +1,332 @@ +package channel_test + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" + channel "github.com/cosmos/ibc-go/modules/core/04-channel" + "github.com/cosmos/ibc-go/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/testing/mock" +) + +func (suite *ChannelTestSuite) TestAnteDecorator() { + testCases := []struct { + name string + malleate func(suite *ChannelTestSuite) []sdk.Msg + expPass bool + expStrictPass bool + }{ + { + "success on single msg", + func(suite *ChannelTestSuite) []sdk.Msg { + packet := types.NewPacket([]byte(mock.MockPacketData), 1, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + return []sdk.Msg{types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")} + }, + true, + true, + }, + { + "success on multiple msgs", + func(suite *ChannelTestSuite) []sdk.Msg { + var msgs []sdk.Msg + + for i := 1; i <= 5; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + return msgs + }, + true, + true, + }, + { + "success on multiple msgs on non-strict decorator: 1 fresh recv packet", + func(suite *ChannelTestSuite) []sdk.Msg { + var msgs []sdk.Msg + + for i := 1; i <= 5; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + err := suite.path.EndpointA.SendPacket(packet) + suite.Require().NoError(err) + + // receive all sequences except packet 3 + if i != 3 { + err = suite.path.EndpointB.RecvPacket(packet) + suite.Require().NoError(err) + } + + msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + + return msgs + }, + true, + false, + }, + { + "success on multiple mixed msgs", + func(suite *ChannelTestSuite) []sdk.Msg { + var msgs []sdk.Msg + + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + err := suite.path.EndpointA.SendPacket(packet) + suite.Require().NoError(err) + + msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + clienttypes.NewHeight(1, 0), 0) + err := suite.path.EndpointB.SendPacket(packet) + suite.Require().NoError(err) + + msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 4; i <= 6; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + clienttypes.NewHeight(1, 0), 0) + err := suite.path.EndpointB.SendPacket(packet) + suite.Require().NoError(err) + + msgs = append(msgs, types.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + return msgs + }, + true, + true, + }, + { + "success on multiple mixed msgs on non strict decorator: 1 fresh packet of each type", + func(suite *ChannelTestSuite) []sdk.Msg { + var msgs []sdk.Msg + + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + err := suite.path.EndpointA.SendPacket(packet) + suite.Require().NoError(err) + + // receive all sequences except packet 3 + if i != 3 { + + err := suite.path.EndpointB.RecvPacket(packet) + suite.Require().NoError(err) + } + + msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + clienttypes.NewHeight(1, 0), 0) + err := suite.path.EndpointB.SendPacket(packet) + suite.Require().NoError(err) + + // receive all acks except ack 2 + if i != 2 { + err = suite.path.EndpointA.RecvPacket(packet) + suite.Require().NoError(err) + err = suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) + suite.Require().NoError(err) + } + + msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 4; i <= 6; i++ { + height := suite.chainA.LastHeader.GetHeight() + timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + timeoutHeight, 0) + err := suite.path.EndpointB.SendPacket(packet) + suite.Require().NoError(err) + + // timeout packet + suite.coordinator.CommitNBlocks(suite.chainA, 3) + + // timeout packets except sequence 5 + if i != 5 { + suite.path.EndpointB.UpdateClient() + err = suite.path.EndpointB.TimeoutPacket(packet) + suite.Require().NoError(err) + } + + msgs = append(msgs, types.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + return msgs + }, + true, + false, + }, + { + "success on multiple mixed msgs on non strict decorator: only 1 fresh msg in total", + func(suite *ChannelTestSuite) []sdk.Msg { + var msgs []sdk.Msg + + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + // receive all packets + suite.path.EndpointA.SendPacket(packet) + suite.path.EndpointB.RecvPacket(packet) + + msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + // receive all acks + suite.path.EndpointB.SendPacket(packet) + suite.path.EndpointA.RecvPacket(packet) + suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) + + msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 4; i < 5; i++ { + height := suite.chainA.LastHeader.GetHeight() + timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + timeoutHeight, 0) + + // do not timeout packet, timeout msg is fresh + suite.path.EndpointB.SendPacket(packet) + + msgs = append(msgs, types.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + return msgs + }, + true, + false, + }, + { + "no success on multiple mixed message: all are redundant", + func(suite *ChannelTestSuite) []sdk.Msg { + var msgs []sdk.Msg + + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + // receive all packets + suite.path.EndpointA.SendPacket(packet) + suite.path.EndpointB.RecvPacket(packet) + + msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + // receive all acks + suite.path.EndpointB.SendPacket(packet) + suite.path.EndpointA.RecvPacket(packet) + suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) + + msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 4; i < 6; i++ { + height := suite.chainA.LastHeader.GetHeight() + timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + timeoutHeight, 0) + + err := suite.path.EndpointB.SendPacket(packet) + suite.Require().NoError(err) + + // timeout packet + suite.coordinator.CommitNBlocks(suite.chainA, 3) + + suite.path.EndpointB.UpdateClient() + suite.path.EndpointB.TimeoutPacket(packet) + + msgs = append(msgs, types.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) + } + return msgs + }, + false, + false, + }, + } + + for _, tc := range testCases { + tc := tc + + suite.Run(tc.name, func() { + // reset suite + suite.SetupTest() + + k := suite.chainB.App.GetIBCKeeper().ChannelKeeper + strictDecorator := channel.NewChannelAnteDecorator(k, true) + decorator := channel.NewChannelAnteDecorator(k, false) + + msgs := tc.malleate(suite) + + deliverCtx := suite.chainB.GetContext().WithIsCheckTx(false) + checkCtx := suite.chainB.GetContext().WithIsCheckTx(true) + + // create multimsg tx + txBuilder := suite.chainB.TxConfig.NewTxBuilder() + err := txBuilder.SetMsgs(msgs...) + suite.Require().NoError(err) + tx := txBuilder.GetTx() + + next := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { return ctx, nil } + + _, err = decorator.AnteHandle(deliverCtx, tx, false, next) + suite.Require().NoError(err, "antedecorator should not error on DeliverTx") + _, err = strictDecorator.AnteHandle(deliverCtx, tx, false, next) + suite.Require().NoError(err, "antedecorator should not error on DeliverTx") + + _, err = decorator.AnteHandle(checkCtx, tx, false, next) + if tc.expPass { + suite.Require().NoError(err, "non-strict decorator did not pass as expected") + } else { + suite.Require().Error(err, "non-strict antehandler did not return error as expected") + } + + _, err = strictDecorator.AnteHandle(checkCtx, tx, false, next) + if tc.expStrictPass { + suite.Require().NoError(err, "strict decorator returned unexpected error") + } else { + suite.Require().Error(err, "strict decorator did not return error as expected") + } + }) + } +} diff --git a/modules/core/04-channel/channel_test.go b/modules/core/04-channel/channel_test.go new file mode 100644 index 00000000000..bc5b5043404 --- /dev/null +++ b/modules/core/04-channel/channel_test.go @@ -0,0 +1,37 @@ +package channel_test + +import ( + "testing" + + ibctesting "github.com/cosmos/ibc-go/testing" + "github.com/stretchr/testify/suite" +) + +type ChannelTestSuite struct { + suite.Suite + + coordinator *ibctesting.Coordinator + + // testing chains used for convenience and readability + chainA *ibctesting.TestChain + chainB *ibctesting.TestChain + + path *ibctesting.Path +} + +// SetupTest creates a coordinator with 2 test chains. +func (suite *ChannelTestSuite) SetupTest() { + suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) + suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) + suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) + // commit some blocks so that QueryProof returns valid proof (cannot return valid query if height <= 1) + suite.coordinator.CommitNBlocks(suite.chainA, 2) + suite.coordinator.CommitNBlocks(suite.chainB, 2) + suite.path = ibctesting.NewPath(suite.chainA, suite.chainB) + suite.coordinator.Setup(suite.path) +} + +// TestChannelTestSuite runs all the tests within this package. +func TestChannelTestSuite(t *testing.T) { + suite.Run(t, new(ChannelTestSuite)) +} From 4a2799b0d27b557b85f21d460a5b5bcad7d1a7ee Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Mon, 19 Jul 2021 13:55:23 +0200 Subject: [PATCH 5/7] remove strict decorator and pass on non-packet/update type --- modules/core/04-channel/ante.go | 36 +++--- modules/core/04-channel/ante_test.go | 168 +++++++++++++++++++++++---- 2 files changed, 167 insertions(+), 37 deletions(-) diff --git a/modules/core/04-channel/ante.go b/modules/core/04-channel/ante.go index 2675b649021..66cac1fa377 100644 --- a/modules/core/04-channel/ante.go +++ b/modules/core/04-channel/ante.go @@ -2,59 +2,69 @@ package channel import ( sdk "github.com/cosmos/cosmos-sdk/types" + clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" "github.com/cosmos/ibc-go/modules/core/04-channel/keeper" "github.com/cosmos/ibc-go/modules/core/04-channel/types" ) type ChannelAnteDecorator struct { - k keeper.Keeper - strict bool + k keeper.Keeper } -func NewChannelAnteDecorator(k keeper.Keeper, strict bool) ChannelAnteDecorator { - return ChannelAnteDecorator{k: k, strict: strict} +func NewChannelAnteDecorator(k keeper.Keeper) ChannelAnteDecorator { + return ChannelAnteDecorator{k: k} } +// ChannelAnteDecorator returns an error if a multiMsg tx only contains packet messages (Recv, Ack, Timeout) and additional update messages and all packet messages +// are redundant. If the transaction is just a single UpdateClient message, or the multimsg transaction contains some other message type, then the antedecorator returns no error +// and continues processing to ensure these transactions are included. +// This will ensure that relayers do not waste fees on multiMsg transactions when another relayer has already submitted all packets, by rejecting the tx at the mempool layer. func (cad ChannelAnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { // do not run redundancy check on DeliverTx or simulate if (ctx.IsCheckTx() || ctx.IsReCheckTx()) && !simulate { // keep track of total packet messages and number of redundancies across `RecvPacket`, `AcknowledgePacket`, and `TimeoutPacket/OnClose` - msgs := 0 redundancies := 0 + packetMsgs := 0 for _, m := range tx.GetMsgs() { switch msg := m.(type) { case *types.MsgRecvPacket: if _, found := cad.k.GetPacketReceipt(ctx, msg.Packet.GetDestPort(), msg.Packet.GetDestChannel(), msg.Packet.GetSequence()); found { redundancies += 1 } + packetMsgs += 1 case *types.MsgAcknowledgement: if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { redundancies += 1 } + packetMsgs += 1 case *types.MsgTimeout: if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { redundancies += 1 } + packetMsgs += 1 case *types.MsgTimeoutOnClose: if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { redundancies += 1 } + packetMsgs += 1 + + case *clienttypes.MsgUpdateClient: + // do nothing here, as we want to avoid updating clients if it is batched with only redundant messages + default: - continue + // if the multiMsg tx has a msg that is not a packet msg or update msg, then we will not return error + // regardless of if all packet messages are redundant. This ensures that non-packet messages get processed + // even if they get batched with redundant packet messages. + return next(ctx, tx, simulate) } - msgs += 1 - } - if cad.strict && redundancies > 1 { - // if strict, return error on single redundancy - return ctx, types.ErrRedundantTx - } else if redundancies == msgs && msgs > 0 { - // if not strict, only return error if all packet messages are redundant + // only return error if all packet messages are redundant + if redundancies == packetMsgs && packetMsgs > 0 { return ctx, types.ErrRedundantTx } } diff --git a/modules/core/04-channel/ante_test.go b/modules/core/04-channel/ante_test.go index c51765ef993..e9aafb9e433 100644 --- a/modules/core/04-channel/ante_test.go +++ b/modules/core/04-channel/ante_test.go @@ -10,10 +10,9 @@ import ( func (suite *ChannelTestSuite) TestAnteDecorator() { testCases := []struct { - name string - malleate func(suite *ChannelTestSuite) []sdk.Msg - expPass bool - expStrictPass bool + name string + malleate func(suite *ChannelTestSuite) []sdk.Msg + expPass bool }{ { "success on single msg", @@ -26,7 +25,6 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { return []sdk.Msg{types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")} }, true, - true, }, { "success on multiple msgs", @@ -44,10 +42,9 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { return msgs }, true, - true, }, { - "success on multiple msgs on non-strict decorator: 1 fresh recv packet", + "success on multiple msgs: 1 fresh recv packet", func(suite *ChannelTestSuite) []sdk.Msg { var msgs []sdk.Msg @@ -72,7 +69,6 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { return msgs }, true, - false, }, { "success on multiple mixed msgs", @@ -112,10 +108,9 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { return msgs }, true, - true, }, { - "success on multiple mixed msgs on non strict decorator: 1 fresh packet of each type", + "success on multiple mixed msgs: 1 fresh packet of each type", func(suite *ChannelTestSuite) []sdk.Msg { var msgs []sdk.Msg @@ -179,10 +174,9 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { return msgs }, true, - false, }, { - "success on multiple mixed msgs on non strict decorator: only 1 fresh msg in total", + "success on multiple mixed msgs: only 1 fresh msg in total", func(suite *ChannelTestSuite) []sdk.Msg { var msgs []sdk.Msg @@ -227,7 +221,91 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { return msgs }, true, - false, + }, + { + "success on single update client msg", + func(suite *ChannelTestSuite) []sdk.Msg { + return []sdk.Msg{&clienttypes.MsgUpdateClient{}} + }, + true, + }, + { + "success on multiple update clients", + func(suite *ChannelTestSuite) []sdk.Msg { + return []sdk.Msg{&clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}} + }, + true, + }, + { + "success on multiple update clients and fresh packet message", + func(suite *ChannelTestSuite) []sdk.Msg { + msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}} + + packet := types.NewPacket([]byte(mock.MockPacketData), 1, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + return append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + }, + true, + }, + { + "success of tx with different msg type even if all packet messages are redundant", + func(suite *ChannelTestSuite) []sdk.Msg { + msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}} + + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + // receive all packets + suite.path.EndpointA.SendPacket(packet) + suite.path.EndpointB.RecvPacket(packet) + + msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + // receive all acks + suite.path.EndpointB.SendPacket(packet) + suite.path.EndpointA.RecvPacket(packet) + suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) + + msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 4; i < 6; i++ { + height := suite.chainA.LastHeader.GetHeight() + timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + timeoutHeight, 0) + + err := suite.path.EndpointB.SendPacket(packet) + suite.Require().NoError(err) + + // timeout packet + suite.coordinator.CommitNBlocks(suite.chainA, 3) + + suite.path.EndpointB.UpdateClient() + suite.path.EndpointB.TimeoutPacket(packet) + + msgs = append(msgs, types.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) + } + + // append non packet and update message to msgs to ensure multimsg tx should pass + msgs = append(msgs, &clienttypes.MsgSubmitMisbehaviour{}) + + return msgs + }, + true, }, { "no success on multiple mixed message: all are redundant", @@ -281,6 +359,58 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { return msgs }, false, + }, + { + "no success if msgs contain update clients and redundant packet messages", + func(suite *ChannelTestSuite) []sdk.Msg { + msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}} + + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + // receive all packets + suite.path.EndpointA.SendPacket(packet) + suite.path.EndpointB.RecvPacket(packet) + + msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 1; i <= 3; i++ { + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + clienttypes.NewHeight(1, 0), 0) + + // receive all acks + suite.path.EndpointB.SendPacket(packet) + suite.path.EndpointA.RecvPacket(packet) + suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) + + msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + } + for i := 4; i < 6; i++ { + height := suite.chainA.LastHeader.GetHeight() + timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) + packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + timeoutHeight, 0) + + err := suite.path.EndpointB.SendPacket(packet) + suite.Require().NoError(err) + + // timeout packet + suite.coordinator.CommitNBlocks(suite.chainA, 3) + + suite.path.EndpointB.UpdateClient() + suite.path.EndpointB.TimeoutPacket(packet) + + msgs = append(msgs, types.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) + } + return msgs + }, false, }, } @@ -293,8 +423,7 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.SetupTest() k := suite.chainB.App.GetIBCKeeper().ChannelKeeper - strictDecorator := channel.NewChannelAnteDecorator(k, true) - decorator := channel.NewChannelAnteDecorator(k, false) + decorator := channel.NewChannelAnteDecorator(k) msgs := tc.malleate(suite) @@ -311,8 +440,6 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { _, err = decorator.AnteHandle(deliverCtx, tx, false, next) suite.Require().NoError(err, "antedecorator should not error on DeliverTx") - _, err = strictDecorator.AnteHandle(deliverCtx, tx, false, next) - suite.Require().NoError(err, "antedecorator should not error on DeliverTx") _, err = decorator.AnteHandle(checkCtx, tx, false, next) if tc.expPass { @@ -320,13 +447,6 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { } else { suite.Require().Error(err, "non-strict antehandler did not return error as expected") } - - _, err = strictDecorator.AnteHandle(checkCtx, tx, false, next) - if tc.expStrictPass { - suite.Require().NoError(err, "strict decorator returned unexpected error") - } else { - suite.Require().Error(err, "strict decorator did not return error as expected") - } }) } } From eec42608d8526e7796aa87279ba0b171082b5c09 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Mon, 19 Jul 2021 14:04:02 +0200 Subject: [PATCH 6/7] move ante logic into its own package --- modules/core/04-channel/channel_test.go | 37 ----- modules/core/{04-channel => ante}/ante.go | 36 ++-- .../core/{04-channel => ante}/ante_test.go | 157 +++++++++++------- 3 files changed, 113 insertions(+), 117 deletions(-) delete mode 100644 modules/core/04-channel/channel_test.go rename modules/core/{04-channel => ante}/ante.go (55%) rename modules/core/{04-channel => ante}/ante_test.go (66%) diff --git a/modules/core/04-channel/channel_test.go b/modules/core/04-channel/channel_test.go deleted file mode 100644 index bc5b5043404..00000000000 --- a/modules/core/04-channel/channel_test.go +++ /dev/null @@ -1,37 +0,0 @@ -package channel_test - -import ( - "testing" - - ibctesting "github.com/cosmos/ibc-go/testing" - "github.com/stretchr/testify/suite" -) - -type ChannelTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - // testing chains used for convenience and readability - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain - - path *ibctesting.Path -} - -// SetupTest creates a coordinator with 2 test chains. -func (suite *ChannelTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - // commit some blocks so that QueryProof returns valid proof (cannot return valid query if height <= 1) - suite.coordinator.CommitNBlocks(suite.chainA, 2) - suite.coordinator.CommitNBlocks(suite.chainB, 2) - suite.path = ibctesting.NewPath(suite.chainA, suite.chainB) - suite.coordinator.Setup(suite.path) -} - -// TestChannelTestSuite runs all the tests within this package. -func TestChannelTestSuite(t *testing.T) { - suite.Run(t, new(ChannelTestSuite)) -} diff --git a/modules/core/04-channel/ante.go b/modules/core/ante/ante.go similarity index 55% rename from modules/core/04-channel/ante.go rename to modules/core/ante/ante.go index 66cac1fa377..aa579027d7f 100644 --- a/modules/core/04-channel/ante.go +++ b/modules/core/ante/ante.go @@ -1,25 +1,25 @@ -package channel +package ante import ( sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" - "github.com/cosmos/ibc-go/modules/core/04-channel/keeper" - "github.com/cosmos/ibc-go/modules/core/04-channel/types" + channelkeeper "github.com/cosmos/ibc-go/modules/core/04-channel/keeper" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" ) -type ChannelAnteDecorator struct { - k keeper.Keeper +type AnteDecorator struct { + k channelkeeper.Keeper } -func NewChannelAnteDecorator(k keeper.Keeper) ChannelAnteDecorator { - return ChannelAnteDecorator{k: k} +func NewAnteDecorator(k channelkeeper.Keeper) AnteDecorator { + return AnteDecorator{k: k} } -// ChannelAnteDecorator returns an error if a multiMsg tx only contains packet messages (Recv, Ack, Timeout) and additional update messages and all packet messages +// AnteDecorator returns an error if a multiMsg tx only contains packet messages (Recv, Ack, Timeout) and additional update messages and all packet messages // are redundant. If the transaction is just a single UpdateClient message, or the multimsg transaction contains some other message type, then the antedecorator returns no error // and continues processing to ensure these transactions are included. // This will ensure that relayers do not waste fees on multiMsg transactions when another relayer has already submitted all packets, by rejecting the tx at the mempool layer. -func (cad ChannelAnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { +func (ad AnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { // do not run redundancy check on DeliverTx or simulate if (ctx.IsCheckTx() || ctx.IsReCheckTx()) && !simulate { // keep track of total packet messages and number of redundancies across `RecvPacket`, `AcknowledgePacket`, and `TimeoutPacket/OnClose` @@ -27,26 +27,26 @@ func (cad ChannelAnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate packetMsgs := 0 for _, m := range tx.GetMsgs() { switch msg := m.(type) { - case *types.MsgRecvPacket: - if _, found := cad.k.GetPacketReceipt(ctx, msg.Packet.GetDestPort(), msg.Packet.GetDestChannel(), msg.Packet.GetSequence()); found { + case *channeltypes.MsgRecvPacket: + if _, found := ad.k.GetPacketReceipt(ctx, msg.Packet.GetDestPort(), msg.Packet.GetDestChannel(), msg.Packet.GetSequence()); found { redundancies += 1 } packetMsgs += 1 - case *types.MsgAcknowledgement: - if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + case *channeltypes.MsgAcknowledgement: + if commitment := ad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { redundancies += 1 } packetMsgs += 1 - case *types.MsgTimeout: - if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + case *channeltypes.MsgTimeout: + if commitment := ad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { redundancies += 1 } packetMsgs += 1 - case *types.MsgTimeoutOnClose: - if commitment := cad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { + case *channeltypes.MsgTimeoutOnClose: + if commitment := ad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { redundancies += 1 } packetMsgs += 1 @@ -65,7 +65,7 @@ func (cad ChannelAnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate // only return error if all packet messages are redundant if redundancies == packetMsgs && packetMsgs > 0 { - return ctx, types.ErrRedundantTx + return ctx, channeltypes.ErrRedundantTx } } return next(ctx, tx, simulate) diff --git a/modules/core/04-channel/ante_test.go b/modules/core/ante/ante_test.go similarity index 66% rename from modules/core/04-channel/ante_test.go rename to modules/core/ante/ante_test.go index e9aafb9e433..0b997685285 100644 --- a/modules/core/04-channel/ante_test.go +++ b/modules/core/ante/ante_test.go @@ -1,43 +1,76 @@ -package channel_test +package ante_test import ( + "testing" + sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/ibc-go/modules/core/02-client/types" - channel "github.com/cosmos/ibc-go/modules/core/04-channel" - "github.com/cosmos/ibc-go/modules/core/04-channel/types" + channeltypes "github.com/cosmos/ibc-go/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/modules/core/ante" + ibctesting "github.com/cosmos/ibc-go/testing" "github.com/cosmos/ibc-go/testing/mock" + "github.com/stretchr/testify/suite" ) -func (suite *ChannelTestSuite) TestAnteDecorator() { +type AnteTestSuite struct { + suite.Suite + + coordinator *ibctesting.Coordinator + + // testing chains used for convenience and readability + chainA *ibctesting.TestChain + chainB *ibctesting.TestChain + + path *ibctesting.Path +} + +// SetupTest creates a coordinator with 2 test chains. +func (suite *AnteTestSuite) SetupTest() { + suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) + suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) + suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) + // commit some blocks so that QueryProof returns valid proof (cannot return valid query if height <= 1) + suite.coordinator.CommitNBlocks(suite.chainA, 2) + suite.coordinator.CommitNBlocks(suite.chainB, 2) + suite.path = ibctesting.NewPath(suite.chainA, suite.chainB) + suite.coordinator.Setup(suite.path) +} + +// TestAnteTestSuite runs all the tests within this package. +func TestAnteTestSuite(t *testing.T) { + suite.Run(t, new(AnteTestSuite)) +} + +func (suite *AnteTestSuite) TestAnteDecorator() { testCases := []struct { name string - malleate func(suite *ChannelTestSuite) []sdk.Msg + malleate func(suite *AnteTestSuite) []sdk.Msg expPass bool }{ { "success on single msg", - func(suite *ChannelTestSuite) []sdk.Msg { - packet := types.NewPacket([]byte(mock.MockPacketData), 1, + func(suite *AnteTestSuite) []sdk.Msg { + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), 1, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(1, 0), 0) - return []sdk.Msg{types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")} + return []sdk.Msg{channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")} }, true, }, { "success on multiple msgs", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { var msgs []sdk.Msg for i := 1; i <= 5; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(1, 0), 0) - msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } return msgs }, @@ -45,11 +78,11 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { }, { "success on multiple msgs: 1 fresh recv packet", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { var msgs []sdk.Msg for i := 1; i <= 5; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -63,7 +96,7 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.Require().NoError(err) } - msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } return msgs @@ -72,38 +105,38 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { }, { "success on multiple mixed msgs", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { var msgs []sdk.Msg for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(1, 0), 0) err := suite.path.EndpointA.SendPacket(packet) suite.Require().NoError(err) - msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, clienttypes.NewHeight(1, 0), 0) err := suite.path.EndpointB.SendPacket(packet) suite.Require().NoError(err) - msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 4; i <= 6; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, clienttypes.NewHeight(1, 0), 0) err := suite.path.EndpointB.SendPacket(packet) suite.Require().NoError(err) - msgs = append(msgs, types.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } return msgs }, @@ -111,11 +144,11 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { }, { "success on multiple mixed msgs: 1 fresh packet of each type", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { var msgs []sdk.Msg for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -129,10 +162,10 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.Require().NoError(err) } - msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -147,12 +180,12 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.Require().NoError(err) } - msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 4; i <= 6; i++ { height := suite.chainA.LastHeader.GetHeight() timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, timeoutHeight, 0) @@ -169,7 +202,7 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.Require().NoError(err) } - msgs = append(msgs, types.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } return msgs }, @@ -177,11 +210,11 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { }, { "success on multiple mixed msgs: only 1 fresh msg in total", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { var msgs []sdk.Msg for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -190,10 +223,10 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointA.SendPacket(packet) suite.path.EndpointB.RecvPacket(packet) - msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -203,12 +236,12 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointA.RecvPacket(packet) suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) - msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 4; i < 5; i++ { height := suite.chainA.LastHeader.GetHeight() timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, timeoutHeight, 0) @@ -216,7 +249,7 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { // do not timeout packet, timeout msg is fresh suite.path.EndpointB.SendPacket(packet) - msgs = append(msgs, types.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgTimeout(packet, uint64(i), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } return msgs }, @@ -224,39 +257,39 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { }, { "success on single update client msg", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { return []sdk.Msg{&clienttypes.MsgUpdateClient{}} }, true, }, { "success on multiple update clients", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { return []sdk.Msg{&clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}} }, true, }, { "success on multiple update clients and fresh packet message", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}} - packet := types.NewPacket([]byte(mock.MockPacketData), 1, + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), 1, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(1, 0), 0) - return append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + return append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) }, true, }, { "success of tx with different msg type even if all packet messages are redundant", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}} for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -265,10 +298,10 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointA.SendPacket(packet) suite.path.EndpointB.RecvPacket(packet) - msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -278,12 +311,12 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointA.RecvPacket(packet) suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) - msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 4; i < 6; i++ { height := suite.chainA.LastHeader.GetHeight() timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, timeoutHeight, 0) @@ -297,7 +330,7 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointB.UpdateClient() suite.path.EndpointB.TimeoutPacket(packet) - msgs = append(msgs, types.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) } // append non packet and update message to msgs to ensure multimsg tx should pass @@ -309,11 +342,11 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { }, { "no success on multiple mixed message: all are redundant", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { var msgs []sdk.Msg for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -322,10 +355,10 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointA.SendPacket(packet) suite.path.EndpointB.RecvPacket(packet) - msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -335,12 +368,12 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointA.RecvPacket(packet) suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) - msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 4; i < 6; i++ { height := suite.chainA.LastHeader.GetHeight() timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, timeoutHeight, 0) @@ -354,7 +387,7 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointB.UpdateClient() suite.path.EndpointB.TimeoutPacket(packet) - msgs = append(msgs, types.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) } return msgs }, @@ -362,11 +395,11 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { }, { "no success if msgs contain update clients and redundant packet messages", - func(suite *ChannelTestSuite) []sdk.Msg { + func(suite *AnteTestSuite) []sdk.Msg { msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}, &clienttypes.MsgUpdateClient{}} for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -375,10 +408,10 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointA.SendPacket(packet) suite.path.EndpointB.RecvPacket(packet) - msgs = append(msgs, types.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 1; i <= 3; i++ { - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, clienttypes.NewHeight(1, 0), 0) @@ -388,12 +421,12 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointA.RecvPacket(packet) suite.path.EndpointB.AcknowledgePacket(packet, mock.MockAcknowledgement.Acknowledgement()) - msgs = append(msgs, types.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgAcknowledgement(packet, []byte("ack"), []byte("proof"), clienttypes.NewHeight(0, 1), "signer")) } for i := 4; i < 6; i++ { height := suite.chainA.LastHeader.GetHeight() timeoutHeight := clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+1) - packet := types.NewPacket([]byte(mock.MockPacketData), uint64(i), + packet := channeltypes.NewPacket([]byte(mock.MockPacketData), uint64(i), suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, timeoutHeight, 0) @@ -407,7 +440,7 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.path.EndpointB.UpdateClient() suite.path.EndpointB.TimeoutPacket(packet) - msgs = append(msgs, types.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) + msgs = append(msgs, channeltypes.NewMsgTimeoutOnClose(packet, uint64(i), []byte("proof"), []byte("channelProof"), clienttypes.NewHeight(0, 1), "signer")) } return msgs }, @@ -423,7 +456,7 @@ func (suite *ChannelTestSuite) TestAnteDecorator() { suite.SetupTest() k := suite.chainB.App.GetIBCKeeper().ChannelKeeper - decorator := channel.NewChannelAnteDecorator(k) + decorator := ante.NewAnteDecorator(k) msgs := tc.malleate(suite) From 3942eace8438b6ed0d3f19afcd33f485c6f08f05 Mon Sep 17 00:00:00 2001 From: Aditya Sripal Date: Mon, 19 Jul 2021 17:37:06 +0200 Subject: [PATCH 7/7] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4420fb805b..8be6f9bea96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (core/04-channel) [\#197](https://github.com/cosmos/ibc-go/pull/197) Introduced a `packet_ack_hex` attribute to emit the hex-encoded acknowledgement in events. This allows for raw binary (proto-encoded message) to be sent over events and decoded correctly on relayer. Original `packet_ack` is DEPRECATED. All relayers and IBC event consumers are encouraged to switch to `packet_ack_hex` as soon as possible. * (modules/light-clients/07-tendermint) [\#125](https://github.com/cosmos/ibc-go/pull/125) Implement efficient iteration of consensus states and pruning of earliest expired consensus state on UpdateClient. * (modules/light-clients/07-tendermint) [\#141](https://github.com/cosmos/ibc-go/pull/141) Return early in case there's a duplicate update call to save Gas. +* (modules/core/ante) [\#235](https://github.com/cosmos/ibc-go/pull/235) Introduces a new IBC Antedecorator that will reject transactions that only contain redundant packet messages (and accompany UpdateClient msgs). This will prevent relayers from wasting fees by submitting messages for packets that have already been processed by previous relayer(s). The Antedecorator is only applied on CheckTx and RecheckTx and is therefore optional for each node. ### Features