From 6c49b23cf203ed7613c23d41ccd5d7661e1ed14b Mon Sep 17 00:00:00 2001 From: bznein Date: Wed, 23 Oct 2024 12:29:37 +0100 Subject: [PATCH 1/2] chore: add redundant checks for V2 Msgs --- modules/core/ante/ante.go | 31 ++ modules/core/ante/ante_test.go | 750 +++++++++++++++++++-------------- 2 files changed, 466 insertions(+), 315 deletions(-) diff --git a/modules/core/ante/ante.go b/modules/core/ante/ante.go index 243a25f7442..1798df63566 100644 --- a/modules/core/ante/ante.go +++ b/modules/core/ante/ante.go @@ -7,6 +7,7 @@ import ( clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" + channeltypesv2 "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types" "github.com/cosmos/ibc-go/v9/modules/core/exported" "github.com/cosmos/ibc-go/v9/modules/core/keeper" ) @@ -89,6 +90,36 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula return ctx, err } + case *channeltypesv2.MsgTimeout: + response, err := rrd.k.ChannelKeeperV2.Timeout(ctx, msg) + if err != nil { + return ctx, err + } + + if response.Result == channeltypes.NOOP { + redundancies++ + } + packetMsgs++ + case *channeltypesv2.MsgAcknowledgement: + response, err := rrd.k.ChannelKeeperV2.Acknowledgement(ctx, msg) + if err != nil { + return ctx, err + } + + if response.Result == channeltypes.NOOP { + redundancies++ + } + packetMsgs++ + case *channeltypesv2.MsgRecvPacket: + response, err := rrd.k.ChannelKeeperV2.RecvPacket(ctx, msg) + if err != nil { + return ctx, err + } + + if response.Result == channeltypes.NOOP { + redundancies++ + } + packetMsgs++ default: // 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 diff --git a/modules/core/ante/ante_test.go b/modules/core/ante/ante_test.go index 1543e5803f4..4a84d210b4a 100644 --- a/modules/core/ante/ante_test.go +++ b/modules/core/ante/ante_test.go @@ -8,17 +8,17 @@ import ( "github.com/stretchr/testify/require" testifysuite "github.com/stretchr/testify/suite" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" - commitmenttypes "github.com/cosmos/ibc-go/v9/modules/core/23-commitment/types" + channeltypesv2 "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types" host "github.com/cosmos/ibc-go/v9/modules/core/24-host" + hostv2 "github.com/cosmos/ibc-go/v9/modules/core/24-host/v2" "github.com/cosmos/ibc-go/v9/modules/core/ante" "github.com/cosmos/ibc-go/v9/modules/core/exported" - ibctm "github.com/cosmos/ibc-go/v9/modules/light-clients/07-tendermint" ibctesting "github.com/cosmos/ibc-go/v9/testing" + "github.com/cosmos/ibc-go/v9/testing/mock/v2" ) type AnteTestSuite struct { @@ -74,6 +74,25 @@ func (suite *AnteTestSuite) createRecvPacketMessage(isRedundant bool) *channelty return channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String()) } +// createRecvPacketMessageV2 creates a V2 RecvPacket message for a packet sent from chain A to chain B. +func (suite *AnteTestSuite) createRecvPacketMessageV2(isRedundant bool) *channeltypesv2.MsgRecvPacket { + packet, err := suite.path.EndpointA.MsgSendPacket(suite.chainA.GetTimeoutTimestamp(), mock.NewMockPayload(mock.ModuleNameA, mock.ModuleNameB)) + suite.Require().NoError(err) + + if isRedundant { + err = suite.path.EndpointB.MsgRecvPacket(packet) + suite.Require().NoError(err) + } + + err = suite.path.EndpointB.UpdateClient() + suite.Require().NoError(err) + + packetKey := hostv2.PacketCommitmentKey(packet.SourceChannel, packet.Sequence) + proof, proofHeight := suite.chainA.QueryProof(packetKey) + + return channeltypesv2.NewMsgRecvPacket(packet, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String()) +} + // createAcknowledgementMessage creates an Acknowledgement message for a packet sent from chain B to chain A. func (suite *AnteTestSuite) createAcknowledgementMessage(isRedundant bool) sdk.Msg { sequence, err := suite.path.EndpointB.SendPacket(clienttypes.NewHeight(2, 0), 0, ibctesting.MockPacketData) @@ -97,6 +116,33 @@ func (suite *AnteTestSuite) createAcknowledgementMessage(isRedundant bool) sdk.M return channeltypes.NewMsgAcknowledgement(packet, ibctesting.MockAcknowledgement, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String()) } +// createAcknowledgementMessageV2 creates a V2 Acknowledgement message for a packet sent from chain B to chain A. +func (suite *AnteTestSuite) createAcknowledgementMessageV2(isRedundant bool) *channeltypesv2.MsgAcknowledgement { + packet, err := suite.path.EndpointB.MsgSendPacket(suite.chainB.GetTimeoutTimestamp(), mock.NewMockPayload(mock.ModuleNameA, mock.ModuleNameB)) + suite.Require().NoError(err) + + err = suite.path.EndpointA.MsgRecvPacket(packet) + suite.Require().NoError(err) + + ack := channeltypesv2.Acknowledgement{ + AcknowledgementResults: []channeltypesv2.AcknowledgementResult{ + { + AppName: mock.ModuleNameB, + RecvPacketResult: mock.MockRecvPacketResult, + }, + }, + } + if isRedundant { + err = suite.path.EndpointB.MsgAcknowledgePacket(packet, ack) + suite.Require().NoError(err) + } + + packetKey := hostv2.PacketAcknowledgementKey(packet.DestinationChannel, packet.Sequence) + proof, proofHeight := suite.chainA.QueryProof(packetKey) + + return channeltypesv2.NewMsgAcknowledgement(packet, ack, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String()) +} + // createTimeoutMessage creates an Timeout message for a packet sent from chain B to chain A. func (suite *AnteTestSuite) createTimeoutMessage(isRedundant bool) sdk.Msg { height := suite.chainA.LatestCommittedHeader.GetHeight() @@ -126,6 +172,28 @@ func (suite *AnteTestSuite) createTimeoutMessage(isRedundant bool) sdk.Msg { return channeltypes.NewMsgTimeout(packet, sequence, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String()) } +// createTimeoutMessageV2 creates a V2 Timeout message for a packet sent from chain B to chain A. +func (suite *AnteTestSuite) createTimeoutMessageV2(isRedundant bool) *channeltypesv2.MsgTimeout { + timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Unix()) + packet, err := suite.path.EndpointB.MsgSendPacket(timeoutTimestamp, mock.NewMockPayload(mock.ModuleNameA, mock.ModuleNameB)) + suite.Require().NoError(err) + + // suite.coordinator.IncrementTimeBy(-1 * time.Hour) + + err = suite.path.EndpointB.UpdateClient() + suite.Require().NoError(err) + + if isRedundant { + err = suite.path.EndpointB.MsgTimeoutPacket(packet) + suite.Require().NoError(err) + } + + packetKey := hostv2.PacketReceiptKey(packet.SourceChannel, packet.Sequence) + proof, proofHeight := suite.chainA.QueryProof(packetKey) + + return channeltypesv2.NewMsgTimeout(packet, proof, proofHeight, suite.path.EndpointA.Chain.SenderAccount.GetAddress().String()) +} + // createTimeoutOnCloseMessage creates an TimeoutOnClose message for a packet sent from chain B to chain A. func (suite *AnteTestSuite) createTimeoutOnCloseMessage(isRedundant bool) sdk.Msg { height := suite.chainA.LatestCommittedHeader.GetHeight() @@ -185,324 +253,359 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() { malleate func(suite *AnteTestSuite) []sdk.Msg expError error }{ + // { + // "success on one new RecvPacket message", + // func(suite *AnteTestSuite) []sdk.Msg { + // // the RecvPacket message has not been submitted to the chain yet, so it will succeed + // return []sdk.Msg{suite.createRecvPacketMessage(false)} + // }, + // nil, + // }, + // { + // "success on one new V2 RecvPacket message", + // func(suite *AnteTestSuite) []sdk.Msg { + // suite.path.SetupV2() + // // the RecvPacket message has not been submitted to the chain yet, so it will succeed + // return []sdk.Msg{suite.createRecvPacketMessageV2(false)} + // }, + // nil, + // }, + // { + // "success on one new Acknowledgement message", + // func(suite *AnteTestSuite) []sdk.Msg { + // // the Acknowledgement message has not been submitted to the chain yet, so it will succeed + // return []sdk.Msg{suite.createAcknowledgementMessage(false)} + // }, + // nil, + // }, + // { + // "success on one new V2 Acknowledgement message", + // func(suite *AnteTestSuite) []sdk.Msg { + // suite.path.SetupV2() + // // the Acknowledgement message has not been submitted to the chain yet, so it will succeed + // return []sdk.Msg{suite.createAcknowledgementMessageV2(false)} + // }, + // nil, + // }, + // { + // "success on one new Timeout message", + // func(suite *AnteTestSuite) []sdk.Msg { + // // the Timeout message has not been submitted to the chain yet, so it will succeed + // return []sdk.Msg{suite.createTimeoutMessage(false)} + // }, + // nil, + // }, { - "success on one new RecvPacket message", - func(suite *AnteTestSuite) []sdk.Msg { - // the RecvPacket message has not been submitted to the chain yet, so it will succeed - return []sdk.Msg{suite.createRecvPacketMessage(false)} - }, - nil, - }, - { - "success on one new Acknowledgement message", - func(suite *AnteTestSuite) []sdk.Msg { - // the Acknowledgement message has not been submitted to the chain yet, so it will succeed - return []sdk.Msg{suite.createAcknowledgementMessage(false)} - }, - nil, - }, - { - "success on one new Timeout message", + "success on one new Timeout V2 message", func(suite *AnteTestSuite) []sdk.Msg { + suite.path.SetupV2() // the Timeout message has not been submitted to the chain yet, so it will succeed - return []sdk.Msg{suite.createTimeoutMessage(false)} - }, - nil, - }, - { - "success on one new TimeoutOnClose message", - func(suite *AnteTestSuite) []sdk.Msg { - // the TimeoutOnClose message has not been submitted to the chain yet, so it will succeed - return []sdk.Msg{suite.createTimeoutOnCloseMessage(false)} - }, - nil, - }, - { - "success on three new messages of each type", - func(suite *AnteTestSuite) []sdk.Msg { - var msgs []sdk.Msg - - // none of the messages of each type has been submitted to the chain yet, - // the first message is succeed and the next two of each type will be rejected - // because they are redundant. - - // from A to B - for i := 1; i <= 3; i++ { - msgs = append(msgs, suite.createRecvPacketMessage(false)) - } - - // from B to A - for i := 1; i <= 9; i++ { - switch { - case i >= 1 && i <= 3: - msgs = append(msgs, suite.createAcknowledgementMessage(false)) - case i >= 4 && i <= 6: - msgs = append(msgs, suite.createTimeoutMessage(false)) - case i >= 7 && i <= 9: - msgs = append(msgs, suite.createTimeoutOnCloseMessage(false)) - } - } - return msgs - }, - nil, - }, - { - "success on three redundant messages of RecvPacket, Acknowledgement and TimeoutOnClose, and one new Timeout message", - func(suite *AnteTestSuite) []sdk.Msg { - var msgs []sdk.Msg - - // we pass three messages of RecvPacket, Acknowledgement and TimeoutOnClose that - // are all redundant (i.e. those messages have already been submitted and - // processed by the chain). But these messages will not be rejected because the - // Timeout message is new. - - // from A to B - for i := 1; i <= 3; i++ { - msgs = append(msgs, suite.createRecvPacketMessage(true)) - } - - // from B to A - for i := 1; i <= 7; i++ { - switch { - case i >= 1 && i <= 3: - msgs = append(msgs, suite.createAcknowledgementMessage(true)) - case i == 4: - msgs = append(msgs, suite.createTimeoutMessage(false)) - case i >= 5 && i <= 7: - msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) - } - } - return msgs - }, - nil, - }, - { - "success on one new message and two redundant messages of each type", - func(suite *AnteTestSuite) []sdk.Msg { - var msgs []sdk.Msg - - // For each type there is a new message and two messages that are redundant - // (i.e. they have been already submitted and processed by the chain). But all - // the redundant messages will not be rejected because there is a new message - // of each type. - - // from A to B - for i := 1; i <= 3; i++ { - msgs = append(msgs, suite.createRecvPacketMessage(i != 2)) - } - - // from B to A - for i := 1; i <= 9; i++ { - switch { - case i >= 1 && i <= 3: - msgs = append(msgs, suite.createAcknowledgementMessage(i != 2)) - case i >= 4 && i <= 6: - msgs = append(msgs, suite.createTimeoutMessage(i != 5)) - case i >= 7 && i <= 9: - msgs = append(msgs, suite.createTimeoutOnCloseMessage(i != 8)) - } - } - return msgs - }, - nil, - }, - { - "success on one new UpdateClient message", - func(suite *AnteTestSuite) []sdk.Msg { - return []sdk.Msg{suite.createUpdateClientMessage()} - }, - nil, - }, - { - "success on three new UpdateClient messages", - func(suite *AnteTestSuite) []sdk.Msg { - return []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} - }, - nil, - }, - { - "success on three new Updateclient messages and one new RecvPacket message", - func(suite *AnteTestSuite) []sdk.Msg { - return []sdk.Msg{ - suite.createUpdateClientMessage(), - suite.createUpdateClientMessage(), - suite.createUpdateClientMessage(), - suite.createRecvPacketMessage(false), - } - }, - nil, - }, - { - "success on three redundant RecvPacket messages and one SubmitMisbehaviour message", - func(suite *AnteTestSuite) []sdk.Msg { - msgs := []sdk.Msg{suite.createUpdateClientMessage()} - - for i := 1; i <= 3; i++ { - msgs = append(msgs, suite.createRecvPacketMessage(true)) - } - - // append non packet and update message to msgs to ensure multimsg tx should pass - msgs = append(msgs, &clienttypes.MsgSubmitMisbehaviour{}) //nolint:staticcheck // we're using the deprecated message for testing - return msgs - }, - nil, - }, - { - "success on app callback error, app callbacks are skipped for performance", - func(suite *AnteTestSuite) []sdk.Msg { - suite.chainB.GetSimApp().IBCMockModule.IBCApp.OnRecvPacket = func( - ctx context.Context, channelVersion string, packet channeltypes.Packet, relayer sdk.AccAddress, - ) exported.Acknowledgement { - panic(fmt.Errorf("failed OnRecvPacket mock callback")) - } - - // the RecvPacket message has not been submitted to the chain yet, so it will succeed - return []sdk.Msg{suite.createRecvPacketMessage(false)} + return []sdk.Msg{suite.createTimeoutMessageV2(false)} }, nil, }, - { - "no success on one redundant RecvPacket message", - func(suite *AnteTestSuite) []sdk.Msg { - return []sdk.Msg{suite.createRecvPacketMessage(true)} - }, - channeltypes.ErrRedundantTx, - }, - { - "no success on three redundant messages of each type", - func(suite *AnteTestSuite) []sdk.Msg { - var msgs []sdk.Msg - - // from A to B - for i := 1; i <= 3; i++ { - msgs = append(msgs, suite.createRecvPacketMessage(true)) - } - - // from B to A - for i := 1; i <= 9; i++ { - switch { - case i >= 1 && i <= 3: - msgs = append(msgs, suite.createAcknowledgementMessage(true)) - case i >= 4 && i <= 6: - msgs = append(msgs, suite.createTimeoutMessage(true)) - case i >= 7 && i <= 9: - msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) - } - } - return msgs - }, - channeltypes.ErrRedundantTx, - }, - { - "no success on one new UpdateClient message and three redundant RecvPacket messages", - func(suite *AnteTestSuite) []sdk.Msg { - msgs := []sdk.Msg{suite.createUpdateClientMessage()} - - for i := 1; i <= 3; i++ { - msgs = append(msgs, suite.createRecvPacketMessage(true)) - } - - return msgs - }, - channeltypes.ErrRedundantTx, - }, - { - "no success on one new UpdateClient message: invalid client identifier", - func(suite *AnteTestSuite) []sdk.Msg { - clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{}) - suite.Require().NoError(err) - - msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: ibctesting.InvalidID, ClientMessage: clientMsg}} - return msgs - }, - clienttypes.ErrClientNotActive, - }, - { - "no success on one new UpdateClient message: client module not found", - func(suite *AnteTestSuite) []sdk.Msg { - clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{}) - suite.Require().NoError(err) - - msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: clienttypes.FormatClientIdentifier("08-wasm", 1), ClientMessage: clientMsg}} - return msgs - }, - clienttypes.ErrClientNotActive, - }, - { - "no success on one new UpdateClient message: no consensus state for trusted height", - func(suite *AnteTestSuite) []sdk.Msg { - clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{TrustedHeight: clienttypes.NewHeight(1, 10000)}) - suite.Require().NoError(err) - - msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: suite.path.EndpointA.ClientID, ClientMessage: clientMsg}} - return msgs - }, - clienttypes.ErrConsensusStateNotFound, - }, - { - "no success on three new UpdateClient messages and three redundant messages of each type", - func(suite *AnteTestSuite) []sdk.Msg { - msgs := []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} - - // from A to B - for i := 1; i <= 3; i++ { - msgs = append(msgs, suite.createRecvPacketMessage(true)) - } - - // from B to A - for i := 1; i <= 9; i++ { - switch { - case i >= 1 && i <= 3: - msgs = append(msgs, suite.createAcknowledgementMessage(true)) - case i >= 4 && i <= 6: - msgs = append(msgs, suite.createTimeoutMessage(true)) - case i >= 7 && i <= 9: - msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) - } - } - return msgs - }, - channeltypes.ErrRedundantTx, - }, - { - "no success on one new message and one invalid message", - func(suite *AnteTestSuite) []sdk.Msg { - packet := channeltypes.NewPacket(ibctesting.MockPacketData, 2, - suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - clienttypes.NewHeight(2, 0), 0) - - return []sdk.Msg{ - suite.createRecvPacketMessage(false), - channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(1, 1), "signer"), - } - }, - commitmenttypes.ErrInvalidProof, - }, - { - "no success on one new message and one redundant message in the same block", - func(suite *AnteTestSuite) []sdk.Msg { - msg := suite.createRecvPacketMessage(false) - - // We want to be able to run check tx with the non-redundant message without - // committing it to a block, so that the when check tx runs with the redundant - // message they are both in the same block - k := suite.chainB.App.GetIBCKeeper() - decorator := ante.NewRedundantRelayDecorator(k) - checkCtx := suite.chainB.GetContext().WithIsCheckTx(true) - next := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { return ctx, nil } - txBuilder := suite.chainB.TxConfig.NewTxBuilder() - err := txBuilder.SetMsgs([]sdk.Msg{msg}...) - suite.Require().NoError(err) - tx := txBuilder.GetTx() - - _, err = decorator.AnteHandle(checkCtx, tx, false, next) - suite.Require().NoError(err) - - return []sdk.Msg{msg} - }, - channeltypes.ErrRedundantTx, - }, + // { + // "success on one new TimeoutOnClose message", + // func(suite *AnteTestSuite) []sdk.Msg { + // // the TimeoutOnClose message has not been submitted to the chain yet, so it will succeed + // return []sdk.Msg{suite.createTimeoutOnCloseMessage(false)} + // }, + // nil, + // }, + // { + // "success on three new messages of each type", + // func(suite *AnteTestSuite) []sdk.Msg { + // var msgs []sdk.Msg + + // // none of the messages of each type has been submitted to the chain yet, + // // the first message is succeed and the next two of each type will be rejected + // // because they are redundant. + + // // from A to B + // for i := 1; i <= 3; i++ { + // msgs = append(msgs, suite.createRecvPacketMessage(false)) + // } + + // // from B to A + // for i := 1; i <= 9; i++ { + // switch { + // case i >= 1 && i <= 3: + // msgs = append(msgs, suite.createAcknowledgementMessage(false)) + // case i >= 4 && i <= 6: + // msgs = append(msgs, suite.createTimeoutMessage(false)) + // case i >= 7 && i <= 9: + // msgs = append(msgs, suite.createTimeoutOnCloseMessage(false)) + // } + // } + // return msgs + // }, + // nil, + // }, + // { + // "success on three redundant messages of RecvPacket, Acknowledgement and TimeoutOnClose, and one new Timeout message", + // func(suite *AnteTestSuite) []sdk.Msg { + // var msgs []sdk.Msg + + // // we pass three messages of RecvPacket, Acknowledgement and TimeoutOnClose that + // // are all redundant (i.e. those messages have already been submitted and + // // processed by the chain). But these messages will not be rejected because the + // // Timeout message is new. + + // // from A to B + // for i := 1; i <= 3; i++ { + // msgs = append(msgs, suite.createRecvPacketMessage(true)) + // } + + // // from B to A + // for i := 1; i <= 7; i++ { + // switch { + // case i >= 1 && i <= 3: + // msgs = append(msgs, suite.createAcknowledgementMessage(true)) + // case i == 4: + // msgs = append(msgs, suite.createTimeoutMessage(false)) + // case i >= 5 && i <= 7: + // msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) + // } + // } + // return msgs + // }, + // nil, + // }, + // { + // "success on one new message and two redundant messages of each type", + // func(suite *AnteTestSuite) []sdk.Msg { + // var msgs []sdk.Msg + + // // For each type there is a new message and two messages that are redundant + // // (i.e. they have been already submitted and processed by the chain). But all + // // the redundant messages will not be rejected because there is a new message + // // of each type. + + // // from A to B + // for i := 1; i <= 3; i++ { + // msgs = append(msgs, suite.createRecvPacketMessage(i != 2)) + // } + + // // from B to A + // for i := 1; i <= 9; i++ { + // switch { + // case i >= 1 && i <= 3: + // msgs = append(msgs, suite.createAcknowledgementMessage(i != 2)) + // case i >= 4 && i <= 6: + // msgs = append(msgs, suite.createTimeoutMessage(i != 5)) + // case i >= 7 && i <= 9: + // msgs = append(msgs, suite.createTimeoutOnCloseMessage(i != 8)) + // } + // } + // return msgs + // }, + // nil, + // }, + // { + // "success on one new UpdateClient message", + // func(suite *AnteTestSuite) []sdk.Msg { + // return []sdk.Msg{suite.createUpdateClientMessage()} + // }, + // nil, + // }, + // { + // "success on three new UpdateClient messages", + // func(suite *AnteTestSuite) []sdk.Msg { + // return []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} + // }, + // nil, + // }, + // { + // "success on three new Updateclient messages and one new RecvPacket message", + // func(suite *AnteTestSuite) []sdk.Msg { + // return []sdk.Msg{ + // suite.createUpdateClientMessage(), + // suite.createUpdateClientMessage(), + // suite.createUpdateClientMessage(), + // suite.createRecvPacketMessage(false), + // } + // }, + // nil, + // }, + // { + // "success on three redundant RecvPacket messages and one SubmitMisbehaviour message", + // func(suite *AnteTestSuite) []sdk.Msg { + // msgs := []sdk.Msg{suite.createUpdateClientMessage()} + + // for i := 1; i <= 3; i++ { + // msgs = append(msgs, suite.createRecvPacketMessage(true)) + // } + + // // append non packet and update message to msgs to ensure multimsg tx should pass + // msgs = append(msgs, &clienttypes.MsgSubmitMisbehaviour{}) //nolint:staticcheck // we're using the deprecated message for testing + // return msgs + // }, + // nil, + // }, + // { + // "success on app callback error, app callbacks are skipped for performance", + // func(suite *AnteTestSuite) []sdk.Msg { + // suite.chainB.GetSimApp().IBCMockModule.IBCApp.OnRecvPacket = func( + // ctx context.Context, channelVersion string, packet channeltypes.Packet, relayer sdk.AccAddress, + // ) exported.Acknowledgement { + // panic(fmt.Errorf("failed OnRecvPacket mock callback")) + // } + + // // the RecvPacket message has not been submitted to the chain yet, so it will succeed + // return []sdk.Msg{suite.createRecvPacketMessage(false)} + // }, + // nil, + // }, + // { + // "no success on one redundant RecvPacket message", + // func(suite *AnteTestSuite) []sdk.Msg { + // return []sdk.Msg{suite.createRecvPacketMessage(true)} + // }, + // channeltypes.ErrRedundantTx, + // }, + // { + // "no success on one redundant V2 RecvPacket message", + // func(suite *AnteTestSuite) []sdk.Msg { + // suite.path.SetupV2() + // return []sdk.Msg{suite.createRecvPacketMessageV2(true)} + // }, + // channeltypes.ErrRedundantTx, + // }, + // { + // "no success on three redundant messages of each type", + // func(suite *AnteTestSuite) []sdk.Msg { + // var msgs []sdk.Msg + + // // from A to B + // for i := 1; i <= 3; i++ { + // msgs = append(msgs, suite.createRecvPacketMessage(true)) + // } + + // // from B to A + // for i := 1; i <= 9; i++ { + // switch { + // case i >= 1 && i <= 3: + // msgs = append(msgs, suite.createAcknowledgementMessage(true)) + // case i >= 4 && i <= 6: + // msgs = append(msgs, suite.createTimeoutMessage(true)) + // case i >= 7 && i <= 9: + // msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) + // } + // } + // return msgs + // }, + // channeltypes.ErrRedundantTx, + // }, + // { + // "no success on one new UpdateClient message and three redundant RecvPacket messages", + // func(suite *AnteTestSuite) []sdk.Msg { + // msgs := []sdk.Msg{suite.createUpdateClientMessage()} + + // for i := 1; i <= 3; i++ { + // msgs = append(msgs, suite.createRecvPacketMessage(true)) + // } + + // return msgs + // }, + // channeltypes.ErrRedundantTx, + // }, + // { + // "no success on one new UpdateClient message: invalid client identifier", + // func(suite *AnteTestSuite) []sdk.Msg { + // clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{}) + // suite.Require().NoError(err) + + // msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: ibctesting.InvalidID, ClientMessage: clientMsg}} + // return msgs + // }, + // clienttypes.ErrClientNotActive, + // }, + // { + // "no success on one new UpdateClient message: client module not found", + // func(suite *AnteTestSuite) []sdk.Msg { + // clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{}) + // suite.Require().NoError(err) + + // msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: clienttypes.FormatClientIdentifier("08-wasm", 1), ClientMessage: clientMsg}} + // return msgs + // }, + // clienttypes.ErrClientNotActive, + // }, + // { + // "no success on one new UpdateClient message: no consensus state for trusted height", + // func(suite *AnteTestSuite) []sdk.Msg { + // clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{TrustedHeight: clienttypes.NewHeight(1, 10000)}) + // suite.Require().NoError(err) + + // msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: suite.path.EndpointA.ClientID, ClientMessage: clientMsg}} + // return msgs + // }, + // clienttypes.ErrConsensusStateNotFound, + // }, + // { + // "no success on three new UpdateClient messages and three redundant messages of each type", + // func(suite *AnteTestSuite) []sdk.Msg { + // msgs := []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} + + // // from A to B + // for i := 1; i <= 3; i++ { + // msgs = append(msgs, suite.createRecvPacketMessage(true)) + // } + + // // from B to A + // for i := 1; i <= 9; i++ { + // switch { + // case i >= 1 && i <= 3: + // msgs = append(msgs, suite.createAcknowledgementMessage(true)) + // case i >= 4 && i <= 6: + // msgs = append(msgs, suite.createTimeoutMessage(true)) + // case i >= 7 && i <= 9: + // msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) + // } + // } + // return msgs + // }, + // channeltypes.ErrRedundantTx, + // }, + // { + // "no success on one new message and one invalid message", + // func(suite *AnteTestSuite) []sdk.Msg { + // packet := channeltypes.NewPacket(ibctesting.MockPacketData, 2, + // suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + // suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + // clienttypes.NewHeight(2, 0), 0) + + // return []sdk.Msg{ + // suite.createRecvPacketMessage(false), + // channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(1, 1), "signer"), + // } + // }, + // commitmenttypes.ErrInvalidProof, + // }, + // { + // "no success on one new message and one redundant message in the same block", + // func(suite *AnteTestSuite) []sdk.Msg { + // msg := suite.createRecvPacketMessage(false) + + // // We want to be able to run check tx with the non-redundant message without + // // committing it to a block, so that the when check tx runs with the redundant + // // message they are both in the same block + // k := suite.chainB.App.GetIBCKeeper() + // decorator := ante.NewRedundantRelayDecorator(k) + // checkCtx := suite.chainB.GetContext().WithIsCheckTx(true) + // next := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { return ctx, nil } + // txBuilder := suite.chainB.TxConfig.NewTxBuilder() + // err := txBuilder.SetMsgs([]sdk.Msg{msg}...) + // suite.Require().NoError(err) + // tx := txBuilder.GetTx() + + // _, err = decorator.AnteHandle(checkCtx, tx, false, next) + // suite.Require().NoError(err) + + // return []sdk.Msg{msg} + // }, + // channeltypes.ErrRedundantTx, + // }, } for _, tc := range testCases { @@ -555,6 +658,15 @@ func (suite *AnteTestSuite) TestAnteDecoratorReCheckTx() { }, nil, }, + { + "success on one new V2 RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + suite.path.SetupV2() + // the RecvPacket message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createRecvPacketMessageV2(false)} + }, + nil, + }, { "success on one redundant and one new RecvPacket message", func(suite *AnteTestSuite) []sdk.Msg { @@ -595,6 +707,14 @@ func (suite *AnteTestSuite) TestAnteDecoratorReCheckTx() { }, channeltypes.ErrRedundantTx, }, + { + "no success on one redundant V2 RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + suite.path.SetupV2() + return []sdk.Msg{suite.createRecvPacketMessageV2(true)} + }, + channeltypes.ErrRedundantTx, + }, } for _, tc := range testCases { From efd13f2898eab04e90c498971fd9de3f9a0e3b78 Mon Sep 17 00:00:00 2001 From: bznein Date: Wed, 23 Oct 2024 13:45:42 +0100 Subject: [PATCH 2/2] reintroduce tests --- modules/core/ante/ante_test.go | 695 +++++++++++++++++---------------- 1 file changed, 349 insertions(+), 346 deletions(-) diff --git a/modules/core/ante/ante_test.go b/modules/core/ante/ante_test.go index 4a84d210b4a..5fb941c6532 100644 --- a/modules/core/ante/ante_test.go +++ b/modules/core/ante/ante_test.go @@ -4,19 +4,23 @@ import ( "context" "fmt" "testing" + "time" "github.com/stretchr/testify/require" testifysuite "github.com/stretchr/testify/suite" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" channeltypesv2 "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types" + commitmenttypes "github.com/cosmos/ibc-go/v9/modules/core/23-commitment/types" host "github.com/cosmos/ibc-go/v9/modules/core/24-host" hostv2 "github.com/cosmos/ibc-go/v9/modules/core/24-host/v2" "github.com/cosmos/ibc-go/v9/modules/core/ante" "github.com/cosmos/ibc-go/v9/modules/core/exported" + ibctm "github.com/cosmos/ibc-go/v9/modules/light-clients/07-tendermint" ibctesting "github.com/cosmos/ibc-go/v9/testing" "github.com/cosmos/ibc-go/v9/testing/mock/v2" ) @@ -178,8 +182,7 @@ func (suite *AnteTestSuite) createTimeoutMessageV2(isRedundant bool) *channeltyp packet, err := suite.path.EndpointB.MsgSendPacket(timeoutTimestamp, mock.NewMockPayload(mock.ModuleNameA, mock.ModuleNameB)) suite.Require().NoError(err) - // suite.coordinator.IncrementTimeBy(-1 * time.Hour) - + suite.coordinator.IncrementTimeBy(time.Hour) err = suite.path.EndpointB.UpdateClient() suite.Require().NoError(err) @@ -253,48 +256,48 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() { malleate func(suite *AnteTestSuite) []sdk.Msg expError error }{ - // { - // "success on one new RecvPacket message", - // func(suite *AnteTestSuite) []sdk.Msg { - // // the RecvPacket message has not been submitted to the chain yet, so it will succeed - // return []sdk.Msg{suite.createRecvPacketMessage(false)} - // }, - // nil, - // }, - // { - // "success on one new V2 RecvPacket message", - // func(suite *AnteTestSuite) []sdk.Msg { - // suite.path.SetupV2() - // // the RecvPacket message has not been submitted to the chain yet, so it will succeed - // return []sdk.Msg{suite.createRecvPacketMessageV2(false)} - // }, - // nil, - // }, - // { - // "success on one new Acknowledgement message", - // func(suite *AnteTestSuite) []sdk.Msg { - // // the Acknowledgement message has not been submitted to the chain yet, so it will succeed - // return []sdk.Msg{suite.createAcknowledgementMessage(false)} - // }, - // nil, - // }, - // { - // "success on one new V2 Acknowledgement message", - // func(suite *AnteTestSuite) []sdk.Msg { - // suite.path.SetupV2() - // // the Acknowledgement message has not been submitted to the chain yet, so it will succeed - // return []sdk.Msg{suite.createAcknowledgementMessageV2(false)} - // }, - // nil, - // }, - // { - // "success on one new Timeout message", - // func(suite *AnteTestSuite) []sdk.Msg { - // // the Timeout message has not been submitted to the chain yet, so it will succeed - // return []sdk.Msg{suite.createTimeoutMessage(false)} - // }, - // nil, - // }, + { + "success on one new RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + // the RecvPacket message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createRecvPacketMessage(false)} + }, + nil, + }, + { + "success on one new V2 RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + suite.path.SetupV2() + // the RecvPacket message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createRecvPacketMessageV2(false)} + }, + nil, + }, + { + "success on one new Acknowledgement message", + func(suite *AnteTestSuite) []sdk.Msg { + // the Acknowledgement message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createAcknowledgementMessage(false)} + }, + nil, + }, + { + "success on one new V2 Acknowledgement message", + func(suite *AnteTestSuite) []sdk.Msg { + suite.path.SetupV2() + // the Acknowledgement message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createAcknowledgementMessageV2(false)} + }, + nil, + }, + { + "success on one new Timeout message", + func(suite *AnteTestSuite) []sdk.Msg { + // the Timeout message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createTimeoutMessage(false)} + }, + nil, + }, { "success on one new Timeout V2 message", func(suite *AnteTestSuite) []sdk.Msg { @@ -304,308 +307,308 @@ func (suite *AnteTestSuite) TestAnteDecoratorCheckTx() { }, nil, }, - // { - // "success on one new TimeoutOnClose message", - // func(suite *AnteTestSuite) []sdk.Msg { - // // the TimeoutOnClose message has not been submitted to the chain yet, so it will succeed - // return []sdk.Msg{suite.createTimeoutOnCloseMessage(false)} - // }, - // nil, - // }, - // { - // "success on three new messages of each type", - // func(suite *AnteTestSuite) []sdk.Msg { - // var msgs []sdk.Msg - - // // none of the messages of each type has been submitted to the chain yet, - // // the first message is succeed and the next two of each type will be rejected - // // because they are redundant. - - // // from A to B - // for i := 1; i <= 3; i++ { - // msgs = append(msgs, suite.createRecvPacketMessage(false)) - // } - - // // from B to A - // for i := 1; i <= 9; i++ { - // switch { - // case i >= 1 && i <= 3: - // msgs = append(msgs, suite.createAcknowledgementMessage(false)) - // case i >= 4 && i <= 6: - // msgs = append(msgs, suite.createTimeoutMessage(false)) - // case i >= 7 && i <= 9: - // msgs = append(msgs, suite.createTimeoutOnCloseMessage(false)) - // } - // } - // return msgs - // }, - // nil, - // }, - // { - // "success on three redundant messages of RecvPacket, Acknowledgement and TimeoutOnClose, and one new Timeout message", - // func(suite *AnteTestSuite) []sdk.Msg { - // var msgs []sdk.Msg - - // // we pass three messages of RecvPacket, Acknowledgement and TimeoutOnClose that - // // are all redundant (i.e. those messages have already been submitted and - // // processed by the chain). But these messages will not be rejected because the - // // Timeout message is new. - - // // from A to B - // for i := 1; i <= 3; i++ { - // msgs = append(msgs, suite.createRecvPacketMessage(true)) - // } - - // // from B to A - // for i := 1; i <= 7; i++ { - // switch { - // case i >= 1 && i <= 3: - // msgs = append(msgs, suite.createAcknowledgementMessage(true)) - // case i == 4: - // msgs = append(msgs, suite.createTimeoutMessage(false)) - // case i >= 5 && i <= 7: - // msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) - // } - // } - // return msgs - // }, - // nil, - // }, - // { - // "success on one new message and two redundant messages of each type", - // func(suite *AnteTestSuite) []sdk.Msg { - // var msgs []sdk.Msg - - // // For each type there is a new message and two messages that are redundant - // // (i.e. they have been already submitted and processed by the chain). But all - // // the redundant messages will not be rejected because there is a new message - // // of each type. - - // // from A to B - // for i := 1; i <= 3; i++ { - // msgs = append(msgs, suite.createRecvPacketMessage(i != 2)) - // } - - // // from B to A - // for i := 1; i <= 9; i++ { - // switch { - // case i >= 1 && i <= 3: - // msgs = append(msgs, suite.createAcknowledgementMessage(i != 2)) - // case i >= 4 && i <= 6: - // msgs = append(msgs, suite.createTimeoutMessage(i != 5)) - // case i >= 7 && i <= 9: - // msgs = append(msgs, suite.createTimeoutOnCloseMessage(i != 8)) - // } - // } - // return msgs - // }, - // nil, - // }, - // { - // "success on one new UpdateClient message", - // func(suite *AnteTestSuite) []sdk.Msg { - // return []sdk.Msg{suite.createUpdateClientMessage()} - // }, - // nil, - // }, - // { - // "success on three new UpdateClient messages", - // func(suite *AnteTestSuite) []sdk.Msg { - // return []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} - // }, - // nil, - // }, - // { - // "success on three new Updateclient messages and one new RecvPacket message", - // func(suite *AnteTestSuite) []sdk.Msg { - // return []sdk.Msg{ - // suite.createUpdateClientMessage(), - // suite.createUpdateClientMessage(), - // suite.createUpdateClientMessage(), - // suite.createRecvPacketMessage(false), - // } - // }, - // nil, - // }, - // { - // "success on three redundant RecvPacket messages and one SubmitMisbehaviour message", - // func(suite *AnteTestSuite) []sdk.Msg { - // msgs := []sdk.Msg{suite.createUpdateClientMessage()} - - // for i := 1; i <= 3; i++ { - // msgs = append(msgs, suite.createRecvPacketMessage(true)) - // } - - // // append non packet and update message to msgs to ensure multimsg tx should pass - // msgs = append(msgs, &clienttypes.MsgSubmitMisbehaviour{}) //nolint:staticcheck // we're using the deprecated message for testing - // return msgs - // }, - // nil, - // }, - // { - // "success on app callback error, app callbacks are skipped for performance", - // func(suite *AnteTestSuite) []sdk.Msg { - // suite.chainB.GetSimApp().IBCMockModule.IBCApp.OnRecvPacket = func( - // ctx context.Context, channelVersion string, packet channeltypes.Packet, relayer sdk.AccAddress, - // ) exported.Acknowledgement { - // panic(fmt.Errorf("failed OnRecvPacket mock callback")) - // } - - // // the RecvPacket message has not been submitted to the chain yet, so it will succeed - // return []sdk.Msg{suite.createRecvPacketMessage(false)} - // }, - // nil, - // }, - // { - // "no success on one redundant RecvPacket message", - // func(suite *AnteTestSuite) []sdk.Msg { - // return []sdk.Msg{suite.createRecvPacketMessage(true)} - // }, - // channeltypes.ErrRedundantTx, - // }, - // { - // "no success on one redundant V2 RecvPacket message", - // func(suite *AnteTestSuite) []sdk.Msg { - // suite.path.SetupV2() - // return []sdk.Msg{suite.createRecvPacketMessageV2(true)} - // }, - // channeltypes.ErrRedundantTx, - // }, - // { - // "no success on three redundant messages of each type", - // func(suite *AnteTestSuite) []sdk.Msg { - // var msgs []sdk.Msg - - // // from A to B - // for i := 1; i <= 3; i++ { - // msgs = append(msgs, suite.createRecvPacketMessage(true)) - // } - - // // from B to A - // for i := 1; i <= 9; i++ { - // switch { - // case i >= 1 && i <= 3: - // msgs = append(msgs, suite.createAcknowledgementMessage(true)) - // case i >= 4 && i <= 6: - // msgs = append(msgs, suite.createTimeoutMessage(true)) - // case i >= 7 && i <= 9: - // msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) - // } - // } - // return msgs - // }, - // channeltypes.ErrRedundantTx, - // }, - // { - // "no success on one new UpdateClient message and three redundant RecvPacket messages", - // func(suite *AnteTestSuite) []sdk.Msg { - // msgs := []sdk.Msg{suite.createUpdateClientMessage()} - - // for i := 1; i <= 3; i++ { - // msgs = append(msgs, suite.createRecvPacketMessage(true)) - // } - - // return msgs - // }, - // channeltypes.ErrRedundantTx, - // }, - // { - // "no success on one new UpdateClient message: invalid client identifier", - // func(suite *AnteTestSuite) []sdk.Msg { - // clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{}) - // suite.Require().NoError(err) - - // msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: ibctesting.InvalidID, ClientMessage: clientMsg}} - // return msgs - // }, - // clienttypes.ErrClientNotActive, - // }, - // { - // "no success on one new UpdateClient message: client module not found", - // func(suite *AnteTestSuite) []sdk.Msg { - // clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{}) - // suite.Require().NoError(err) - - // msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: clienttypes.FormatClientIdentifier("08-wasm", 1), ClientMessage: clientMsg}} - // return msgs - // }, - // clienttypes.ErrClientNotActive, - // }, - // { - // "no success on one new UpdateClient message: no consensus state for trusted height", - // func(suite *AnteTestSuite) []sdk.Msg { - // clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{TrustedHeight: clienttypes.NewHeight(1, 10000)}) - // suite.Require().NoError(err) - - // msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: suite.path.EndpointA.ClientID, ClientMessage: clientMsg}} - // return msgs - // }, - // clienttypes.ErrConsensusStateNotFound, - // }, - // { - // "no success on three new UpdateClient messages and three redundant messages of each type", - // func(suite *AnteTestSuite) []sdk.Msg { - // msgs := []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} - - // // from A to B - // for i := 1; i <= 3; i++ { - // msgs = append(msgs, suite.createRecvPacketMessage(true)) - // } - - // // from B to A - // for i := 1; i <= 9; i++ { - // switch { - // case i >= 1 && i <= 3: - // msgs = append(msgs, suite.createAcknowledgementMessage(true)) - // case i >= 4 && i <= 6: - // msgs = append(msgs, suite.createTimeoutMessage(true)) - // case i >= 7 && i <= 9: - // msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) - // } - // } - // return msgs - // }, - // channeltypes.ErrRedundantTx, - // }, - // { - // "no success on one new message and one invalid message", - // func(suite *AnteTestSuite) []sdk.Msg { - // packet := channeltypes.NewPacket(ibctesting.MockPacketData, 2, - // suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, - // suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, - // clienttypes.NewHeight(2, 0), 0) - - // return []sdk.Msg{ - // suite.createRecvPacketMessage(false), - // channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(1, 1), "signer"), - // } - // }, - // commitmenttypes.ErrInvalidProof, - // }, - // { - // "no success on one new message and one redundant message in the same block", - // func(suite *AnteTestSuite) []sdk.Msg { - // msg := suite.createRecvPacketMessage(false) - - // // We want to be able to run check tx with the non-redundant message without - // // committing it to a block, so that the when check tx runs with the redundant - // // message they are both in the same block - // k := suite.chainB.App.GetIBCKeeper() - // decorator := ante.NewRedundantRelayDecorator(k) - // checkCtx := suite.chainB.GetContext().WithIsCheckTx(true) - // next := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { return ctx, nil } - // txBuilder := suite.chainB.TxConfig.NewTxBuilder() - // err := txBuilder.SetMsgs([]sdk.Msg{msg}...) - // suite.Require().NoError(err) - // tx := txBuilder.GetTx() - - // _, err = decorator.AnteHandle(checkCtx, tx, false, next) - // suite.Require().NoError(err) - - // return []sdk.Msg{msg} - // }, - // channeltypes.ErrRedundantTx, - // }, + { + "success on one new TimeoutOnClose message", + func(suite *AnteTestSuite) []sdk.Msg { + // the TimeoutOnClose message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createTimeoutOnCloseMessage(false)} + }, + nil, + }, + { + "success on three new messages of each type", + func(suite *AnteTestSuite) []sdk.Msg { + var msgs []sdk.Msg + + // none of the messages of each type has been submitted to the chain yet, + // the first message is succeed and the next two of each type will be rejected + // because they are redundant. + + // from A to B + for i := 1; i <= 3; i++ { + msgs = append(msgs, suite.createRecvPacketMessage(false)) + } + + // from B to A + for i := 1; i <= 9; i++ { + switch { + case i >= 1 && i <= 3: + msgs = append(msgs, suite.createAcknowledgementMessage(false)) + case i >= 4 && i <= 6: + msgs = append(msgs, suite.createTimeoutMessage(false)) + case i >= 7 && i <= 9: + msgs = append(msgs, suite.createTimeoutOnCloseMessage(false)) + } + } + return msgs + }, + nil, + }, + { + "success on three redundant messages of RecvPacket, Acknowledgement and TimeoutOnClose, and one new Timeout message", + func(suite *AnteTestSuite) []sdk.Msg { + var msgs []sdk.Msg + + // we pass three messages of RecvPacket, Acknowledgement and TimeoutOnClose that + // are all redundant (i.e. those messages have already been submitted and + // processed by the chain). But these messages will not be rejected because the + // Timeout message is new. + + // from A to B + for i := 1; i <= 3; i++ { + msgs = append(msgs, suite.createRecvPacketMessage(true)) + } + + // from B to A + for i := 1; i <= 7; i++ { + switch { + case i >= 1 && i <= 3: + msgs = append(msgs, suite.createAcknowledgementMessage(true)) + case i == 4: + msgs = append(msgs, suite.createTimeoutMessage(false)) + case i >= 5 && i <= 7: + msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) + } + } + return msgs + }, + nil, + }, + { + "success on one new message and two redundant messages of each type", + func(suite *AnteTestSuite) []sdk.Msg { + var msgs []sdk.Msg + + // For each type there is a new message and two messages that are redundant + // (i.e. they have been already submitted and processed by the chain). But all + // the redundant messages will not be rejected because there is a new message + // of each type. + + // from A to B + for i := 1; i <= 3; i++ { + msgs = append(msgs, suite.createRecvPacketMessage(i != 2)) + } + + // from B to A + for i := 1; i <= 9; i++ { + switch { + case i >= 1 && i <= 3: + msgs = append(msgs, suite.createAcknowledgementMessage(i != 2)) + case i >= 4 && i <= 6: + msgs = append(msgs, suite.createTimeoutMessage(i != 5)) + case i >= 7 && i <= 9: + msgs = append(msgs, suite.createTimeoutOnCloseMessage(i != 8)) + } + } + return msgs + }, + nil, + }, + { + "success on one new UpdateClient message", + func(suite *AnteTestSuite) []sdk.Msg { + return []sdk.Msg{suite.createUpdateClientMessage()} + }, + nil, + }, + { + "success on three new UpdateClient messages", + func(suite *AnteTestSuite) []sdk.Msg { + return []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} + }, + nil, + }, + { + "success on three new Updateclient messages and one new RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + return []sdk.Msg{ + suite.createUpdateClientMessage(), + suite.createUpdateClientMessage(), + suite.createUpdateClientMessage(), + suite.createRecvPacketMessage(false), + } + }, + nil, + }, + { + "success on three redundant RecvPacket messages and one SubmitMisbehaviour message", + func(suite *AnteTestSuite) []sdk.Msg { + msgs := []sdk.Msg{suite.createUpdateClientMessage()} + + for i := 1; i <= 3; i++ { + msgs = append(msgs, suite.createRecvPacketMessage(true)) + } + + // append non packet and update message to msgs to ensure multimsg tx should pass + msgs = append(msgs, &clienttypes.MsgSubmitMisbehaviour{}) //nolint:staticcheck // we're using the deprecated message for testing + return msgs + }, + nil, + }, + { + "success on app callback error, app callbacks are skipped for performance", + func(suite *AnteTestSuite) []sdk.Msg { + suite.chainB.GetSimApp().IBCMockModule.IBCApp.OnRecvPacket = func( + ctx context.Context, channelVersion string, packet channeltypes.Packet, relayer sdk.AccAddress, + ) exported.Acknowledgement { + panic(fmt.Errorf("failed OnRecvPacket mock callback")) + } + + // the RecvPacket message has not been submitted to the chain yet, so it will succeed + return []sdk.Msg{suite.createRecvPacketMessage(false)} + }, + nil, + }, + { + "no success on one redundant RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + return []sdk.Msg{suite.createRecvPacketMessage(true)} + }, + channeltypes.ErrRedundantTx, + }, + { + "no success on one redundant V2 RecvPacket message", + func(suite *AnteTestSuite) []sdk.Msg { + suite.path.SetupV2() + return []sdk.Msg{suite.createRecvPacketMessageV2(true)} + }, + channeltypes.ErrRedundantTx, + }, + { + "no success on three redundant messages of each type", + func(suite *AnteTestSuite) []sdk.Msg { + var msgs []sdk.Msg + + // from A to B + for i := 1; i <= 3; i++ { + msgs = append(msgs, suite.createRecvPacketMessage(true)) + } + + // from B to A + for i := 1; i <= 9; i++ { + switch { + case i >= 1 && i <= 3: + msgs = append(msgs, suite.createAcknowledgementMessage(true)) + case i >= 4 && i <= 6: + msgs = append(msgs, suite.createTimeoutMessage(true)) + case i >= 7 && i <= 9: + msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) + } + } + return msgs + }, + channeltypes.ErrRedundantTx, + }, + { + "no success on one new UpdateClient message and three redundant RecvPacket messages", + func(suite *AnteTestSuite) []sdk.Msg { + msgs := []sdk.Msg{suite.createUpdateClientMessage()} + + for i := 1; i <= 3; i++ { + msgs = append(msgs, suite.createRecvPacketMessage(true)) + } + + return msgs + }, + channeltypes.ErrRedundantTx, + }, + { + "no success on one new UpdateClient message: invalid client identifier", + func(suite *AnteTestSuite) []sdk.Msg { + clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{}) + suite.Require().NoError(err) + + msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: ibctesting.InvalidID, ClientMessage: clientMsg}} + return msgs + }, + clienttypes.ErrClientNotActive, + }, + { + "no success on one new UpdateClient message: client module not found", + func(suite *AnteTestSuite) []sdk.Msg { + clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{}) + suite.Require().NoError(err) + + msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: clienttypes.FormatClientIdentifier("08-wasm", 1), ClientMessage: clientMsg}} + return msgs + }, + clienttypes.ErrClientNotActive, + }, + { + "no success on one new UpdateClient message: no consensus state for trusted height", + func(suite *AnteTestSuite) []sdk.Msg { + clientMsg, err := codectypes.NewAnyWithValue(&ibctm.Header{TrustedHeight: clienttypes.NewHeight(1, 10000)}) + suite.Require().NoError(err) + + msgs := []sdk.Msg{&clienttypes.MsgUpdateClient{ClientId: suite.path.EndpointA.ClientID, ClientMessage: clientMsg}} + return msgs + }, + clienttypes.ErrConsensusStateNotFound, + }, + { + "no success on three new UpdateClient messages and three redundant messages of each type", + func(suite *AnteTestSuite) []sdk.Msg { + msgs := []sdk.Msg{suite.createUpdateClientMessage(), suite.createUpdateClientMessage(), suite.createUpdateClientMessage()} + + // from A to B + for i := 1; i <= 3; i++ { + msgs = append(msgs, suite.createRecvPacketMessage(true)) + } + + // from B to A + for i := 1; i <= 9; i++ { + switch { + case i >= 1 && i <= 3: + msgs = append(msgs, suite.createAcknowledgementMessage(true)) + case i >= 4 && i <= 6: + msgs = append(msgs, suite.createTimeoutMessage(true)) + case i >= 7 && i <= 9: + msgs = append(msgs, suite.createTimeoutOnCloseMessage(true)) + } + } + return msgs + }, + channeltypes.ErrRedundantTx, + }, + { + "no success on one new message and one invalid message", + func(suite *AnteTestSuite) []sdk.Msg { + packet := channeltypes.NewPacket(ibctesting.MockPacketData, 2, + suite.path.EndpointA.ChannelConfig.PortID, suite.path.EndpointA.ChannelID, + suite.path.EndpointB.ChannelConfig.PortID, suite.path.EndpointB.ChannelID, + clienttypes.NewHeight(2, 0), 0) + + return []sdk.Msg{ + suite.createRecvPacketMessage(false), + channeltypes.NewMsgRecvPacket(packet, []byte("proof"), clienttypes.NewHeight(1, 1), "signer"), + } + }, + commitmenttypes.ErrInvalidProof, + }, + { + "no success on one new message and one redundant message in the same block", + func(suite *AnteTestSuite) []sdk.Msg { + msg := suite.createRecvPacketMessage(false) + + // We want to be able to run check tx with the non-redundant message without + // committing it to a block, so that the when check tx runs with the redundant + // message they are both in the same block + k := suite.chainB.App.GetIBCKeeper() + decorator := ante.NewRedundantRelayDecorator(k) + checkCtx := suite.chainB.GetContext().WithIsCheckTx(true) + next := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { return ctx, nil } + txBuilder := suite.chainB.TxConfig.NewTxBuilder() + err := txBuilder.SetMsgs([]sdk.Msg{msg}...) + suite.Require().NoError(err) + tx := txBuilder.GetTx() + + _, err = decorator.AnteHandle(checkCtx, tx, false, next) + suite.Require().NoError(err) + + return []sdk.Msg{msg} + }, + channeltypes.ErrRedundantTx, + }, } for _, tc := range testCases {