diff --git a/modules/core/04-channel/v2/keeper/export_test.go b/modules/core/04-channel/v2/keeper/export_test.go new file mode 100644 index 00000000000..6cb135f2ea5 --- /dev/null +++ b/modules/core/04-channel/v2/keeper/export_test.go @@ -0,0 +1,70 @@ +package keeper + +/* + This file is to allow for unexported functions to be accessible to the testing package. +*/ + +import ( + "context" + + channeltypesv2 "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types" + "github.com/cosmos/ibc-go/v9/modules/core/exported" +) + +func (k *Keeper) SendPacketTest( + ctx context.Context, + sourceChannel string, + timeoutTimestamp uint64, + data []channeltypesv2.PacketData, +) (uint64, string, error) { + return k.sendPacket( + ctx, + sourceChannel, + timeoutTimestamp, + data, + ) +} + +func (k *Keeper) RecvPacketTest( + ctx context.Context, + packet channeltypesv2.Packet, + proof []byte, + proofHeight exported.Height, +) error { + return k.recvPacket( + ctx, + packet, + proof, + proofHeight, + ) +} + +func (k *Keeper) AcknowledgePacketTest( + ctx context.Context, + packet channeltypesv2.Packet, + acknowledgement channeltypesv2.Acknowledgement, + proof []byte, + proofHeight exported.Height, +) error { + return k.acknowledgePacket( + ctx, + packet, + acknowledgement, + proof, + proofHeight, + ) +} + +func (k *Keeper) TimeoutPacketTest( + ctx context.Context, + packet channeltypesv2.Packet, + proof []byte, + proofHeight exported.Height, +) error { + return k.timeoutPacket( + ctx, + packet, + proof, + proofHeight, + ) +} diff --git a/modules/core/04-channel/v2/keeper/msg_server_test.go b/modules/core/04-channel/v2/keeper/msg_server_test.go index e9cd0e562cb..2ebb99ca341 100644 --- a/modules/core/04-channel/v2/keeper/msg_server_test.go +++ b/modules/core/04-channel/v2/keeper/msg_server_test.go @@ -61,11 +61,11 @@ func (suite *KeeperTestSuite) TestMsgSendPacket() { expError: mock.MockApplicationCallbackError, }, { - name: "failure: counterparty not found", + name: "failure: channel not found", malleate: func() { path.EndpointA.ChannelID = ibctesting.InvalidID }, - expError: channeltypesv1.ErrChannelNotFound, + expError: channeltypesv2.ErrChannelNotFound, }, { name: "failure: route to non existing app", @@ -212,11 +212,8 @@ func (suite *KeeperTestSuite) TestMsgRecvPacket() { expectedAck = channeltypesv2.Acknowledgement{ AcknowledgementResults: []channeltypesv2.AcknowledgementResult{ { - AppName: mockv2.ModuleNameB, - RecvPacketResult: channeltypesv2.RecvPacketResult{ - Status: channeltypesv2.PacketStatus_Success, - Acknowledgement: mock.MockPacketData, - }, + AppName: mockv2.ModuleNameB, + RecvPacketResult: mockv2.MockRecvPacketResult, }, }, } @@ -411,11 +408,8 @@ func (suite *KeeperTestSuite) TestMsgAcknowledgement() { ack = channeltypesv2.Acknowledgement{ AcknowledgementResults: []channeltypesv2.AcknowledgementResult{ { - AppName: mockv2.ModuleNameB, - RecvPacketResult: channeltypesv2.RecvPacketResult{ - Status: channeltypesv2.PacketStatus_Success, - Acknowledgement: mock.MockPacketData, - }, + AppName: mockv2.ModuleNameB, + RecvPacketResult: mockv2.MockRecvPacketResult, }, }, } diff --git a/modules/core/04-channel/v2/keeper/packet.go b/modules/core/04-channel/v2/keeper/packet.go index 5caa94b9772..dccb5da46c8 100644 --- a/modules/core/04-channel/v2/keeper/packet.go +++ b/modules/core/04-channel/v2/keeper/packet.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "strconv" + "time" errorsmod "cosmossdk.io/errors" @@ -11,7 +12,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/04-channel/v2/types" hostv2 "github.com/cosmos/ibc-go/v9/modules/core/24-host/v2" "github.com/cosmos/ibc-go/v9/modules/core/exported" ) @@ -22,7 +23,7 @@ func (k *Keeper) sendPacket( ctx context.Context, sourceChannel string, timeoutTimestamp uint64, - data []channeltypesv2.PacketData, + data []types.PacketData, ) (uint64, string, error) { // Lookup channel associated with our source channel to retrieve the destination channel channel, ok := k.GetChannel(ctx, sourceChannel) @@ -30,7 +31,7 @@ func (k *Keeper) sendPacket( // TODO: figure out how aliasing will work when more than one packet data is sent. channel, ok = k.convertV1Channel(ctx, data[0].SourcePort, sourceChannel) if !ok { - return 0, "", errorsmod.Wrap(channeltypesv2.ErrChannelNotFound, sourceChannel) + return 0, "", errorsmod.Wrap(types.ErrChannelNotFound, sourceChannel) } } @@ -40,13 +41,13 @@ func (k *Keeper) sendPacket( sequence, found := k.GetNextSequenceSend(ctx, sourceChannel) if !found { return 0, "", errorsmod.Wrapf( - channeltypesv2.ErrSequenceSendNotFound, + types.ErrSequenceSendNotFound, "source channel: %s", sourceChannel, ) } // construct packet from given fields and channel state - packet := channeltypesv2.NewPacket(sequence, sourceChannel, destChannel, timeoutTimestamp, data...) + packet := types.NewPacket(sequence, sourceChannel, destChannel, timeoutTimestamp, data...) if err := packet.ValidateBasic(); err != nil { return 0, "", errorsmod.Wrapf(channeltypes.ErrInvalidPacket, "constructed packet failed basic validation: %v", err) @@ -68,12 +69,14 @@ func (k *Keeper) sendPacket( return 0, "", err } // check if packet is timed out on the receiving chain - timeout := channeltypes.NewTimeoutWithTimestamp(timeoutTimestamp) + // convert packet timeout to nanoseconds for now to use existing helper function + // TODO: Remove this workaround with Issue #7414: https://github.com/cosmos/ibc-go/issues/7414 + timeout := channeltypes.NewTimeoutWithTimestamp(uint64(time.Unix(int64(packet.GetTimeoutTimestamp()), 0).UnixNano())) if timeout.TimestampElapsed(latestTimestamp) { return 0, "", errorsmod.Wrap(timeout.ErrTimeoutElapsed(latestHeight, latestTimestamp), "invalid packet timeout") } - commitment := channeltypesv2.CommitPacket(packet) + commitment := types.CommitPacket(packet) // bump the sequence and set the packet commitment, so it is provable by the counterparty k.SetNextSequenceSend(ctx, sourceChannel, sequence+1) @@ -95,7 +98,7 @@ func (k *Keeper) sendPacket( // to indicate to the counterparty successful delivery. func (k *Keeper) recvPacket( ctx context.Context, - packet channeltypesv2.Packet, + packet types.Packet, proof []byte, proofHeight exported.Height, ) error { @@ -107,7 +110,7 @@ func (k *Keeper) recvPacket( // TODO: figure out how aliasing will work when more than one packet data is sent. channel, ok = k.convertV1Channel(ctx, packet.Data[0].DestinationPort, packet.DestinationChannel) if !ok { - return errorsmod.Wrap(channeltypesv2.ErrChannelNotFound, packet.DestinationChannel) + return errorsmod.Wrap(types.ErrChannelNotFound, packet.DestinationChannel) } } if channel.CounterpartyChannelId != packet.SourceChannel { @@ -118,7 +121,9 @@ func (k *Keeper) recvPacket( // check if packet timed out by comparing it with the latest height of the chain sdkCtx := sdk.UnwrapSDKContext(ctx) selfHeight, selfTimestamp := clienttypes.GetSelfHeight(ctx), uint64(sdkCtx.BlockTime().UnixNano()) - timeout := channeltypes.NewTimeoutWithTimestamp(packet.GetTimeoutTimestamp()) + // convert packet timeout to nanoseconds for now to use existing helper function + // TODO: Remove this workaround with Issue #7414: https://github.com/cosmos/ibc-go/issues/7414 + timeout := channeltypes.NewTimeoutWithTimestamp(uint64(time.Unix(int64(packet.GetTimeoutTimestamp()), 0).UnixNano())) if timeout.Elapsed(selfHeight, selfTimestamp) { return errorsmod.Wrap(timeout.ErrTimeoutElapsed(selfHeight, selfTimestamp), "packet timeout elapsed") } @@ -135,9 +140,9 @@ func (k *Keeper) recvPacket( } path := hostv2.PacketCommitmentKey(packet.SourceChannel, packet.Sequence) - merklePath := channeltypesv2.BuildMerklePath(channel.MerklePathPrefix, path) + merklePath := types.BuildMerklePath(channel.MerklePathPrefix, path) - commitment := channeltypesv2.CommitPacket(packet) + commitment := types.CommitPacket(packet) if err := k.ClientKeeper.VerifyMembership( ctx, @@ -164,15 +169,15 @@ func (k *Keeper) recvPacket( // WriteAcknowledgement writes the acknowledgement to the store. func (k Keeper) WriteAcknowledgement( ctx context.Context, - packet channeltypesv2.Packet, - ack channeltypesv2.Acknowledgement, + packet types.Packet, + ack types.Acknowledgement, ) error { // Lookup channel associated with destination channel ID and ensure // that the packet was indeed sent by our counterparty by verifying // packet sender is our channel's counterparty channel id. channel, ok := k.GetChannel(ctx, packet.DestinationChannel) if !ok { - return errorsmod.Wrapf(channeltypesv2.ErrChannelNotFound, "channel (%s) not found", packet.DestinationChannel) + return errorsmod.Wrapf(types.ErrChannelNotFound, "channel (%s) not found", packet.DestinationChannel) } if channel.CounterpartyChannelId != packet.SourceChannel { @@ -190,10 +195,16 @@ func (k Keeper) WriteAcknowledgement( return errorsmod.Wrap(channeltypes.ErrInvalidPacket, "receipt not found for packet") } + // TODO: Validate Acknowledgment more thoroughly here after Issue #7472: https://github.com/cosmos/ibc-go/issues/7472 + + if len(ack.AcknowledgementResults) != len(packet.Data) { + return errorsmod.Wrapf(types.ErrInvalidAcknowledgement, "length of acknowledgement results %d does not match length of packet data %d", len(ack.AcknowledgementResults), len(packet.Data)) + } + // set the acknowledgement so that it can be verified on the other side k.SetPacketAcknowledgement( ctx, packet.DestinationChannel, packet.Sequence, - channeltypesv2.CommitAcknowledgement(ack), + types.CommitAcknowledgement(ack), ) k.Logger(ctx).Info("acknowledgement written", "sequence", strconv.FormatUint(packet.Sequence, 10), "dest-channel", packet.DestinationChannel) @@ -203,12 +214,12 @@ func (k Keeper) WriteAcknowledgement( return nil } -func (k *Keeper) acknowledgePacket(ctx context.Context, packet channeltypesv2.Packet, acknowledgement channeltypesv2.Acknowledgement, proof []byte, proofHeight exported.Height) error { +func (k *Keeper) acknowledgePacket(ctx context.Context, packet types.Packet, acknowledgement types.Acknowledgement, proof []byte, proofHeight exported.Height) error { // Lookup counterparty associated with our channel and ensure // that the packet was indeed sent by our counterparty. channel, ok := k.GetChannel(ctx, packet.SourceChannel) if !ok { - return errorsmod.Wrap(channeltypesv2.ErrChannelNotFound, packet.SourceChannel) + return errorsmod.Wrap(types.ErrChannelNotFound, packet.SourceChannel) } if channel.CounterpartyChannelId != packet.DestinationChannel { @@ -229,7 +240,7 @@ func (k *Keeper) acknowledgePacket(ctx context.Context, packet channeltypesv2.Pa return channeltypes.ErrNoOpMsg } - packetCommitment := channeltypesv2.CommitPacket(packet) + packetCommitment := types.CommitPacket(packet) // verify we sent the packet and haven't cleared it out yet if !bytes.Equal(commitment, packetCommitment) { @@ -237,7 +248,7 @@ func (k *Keeper) acknowledgePacket(ctx context.Context, packet channeltypesv2.Pa } path := hostv2.PacketAcknowledgementKey(packet.DestinationChannel, packet.Sequence) - merklePath := channeltypesv2.BuildMerklePath(channel.MerklePathPrefix, path) + merklePath := types.BuildMerklePath(channel.MerklePathPrefix, path) if err := k.ClientKeeper.VerifyMembership( ctx, @@ -246,7 +257,7 @@ func (k *Keeper) acknowledgePacket(ctx context.Context, packet channeltypesv2.Pa 0, 0, proof, merklePath, - channeltypesv2.CommitAcknowledgement(acknowledgement), + types.CommitAcknowledgement(acknowledgement), ); err != nil { return errorsmod.Wrapf(err, "failed packet acknowledgement verification for client (%s)", clientID) } @@ -269,7 +280,7 @@ func (k *Keeper) acknowledgePacket(ctx context.Context, packet channeltypesv2.Pa // is deleted and the packet has completed its lifecycle. func (k *Keeper) timeoutPacket( ctx context.Context, - packet channeltypesv2.Packet, + packet types.Packet, proof []byte, proofHeight exported.Height, ) error { @@ -280,7 +291,7 @@ func (k *Keeper) timeoutPacket( // TODO: figure out how aliasing will work when more than one packet data is sent. channel, ok = k.convertV1Channel(ctx, packet.Data[0].SourcePort, packet.SourceChannel) if !ok { - return errorsmod.Wrap(channeltypesv2.ErrChannelNotFound, packet.DestinationChannel) + return errorsmod.Wrap(types.ErrChannelNotFound, packet.DestinationChannel) } } if channel.CounterpartyChannelId != packet.DestinationChannel { @@ -294,7 +305,9 @@ func (k *Keeper) timeoutPacket( return err } - timeout := channeltypes.NewTimeoutWithTimestamp(packet.GetTimeoutTimestamp()) + // convert packet timeout to nanoseconds for now to use existing helper function + // TODO: Remove this workaround with Issue #7414: https://github.com/cosmos/ibc-go/issues/7414 + timeout := channeltypes.NewTimeoutWithTimestamp(uint64(time.Unix(int64(packet.GetTimeoutTimestamp()), 0).UnixNano())) if !timeout.Elapsed(clienttypes.ZeroHeight(), proofTimestamp) { return errorsmod.Wrap(timeout.ErrTimeoutNotReached(proofHeight.(clienttypes.Height), proofTimestamp), "packet timeout not reached") } @@ -310,7 +323,7 @@ func (k *Keeper) timeoutPacket( return channeltypes.ErrNoOpMsg } - packetCommitment := channeltypesv2.CommitPacket(packet) + packetCommitment := types.CommitPacket(packet) // verify we sent the packet and haven't cleared it out yet if !bytes.Equal(commitment, packetCommitment) { return errorsmod.Wrapf(channeltypes.ErrInvalidPacket, "packet commitment bytes are not equal: got (%v), expected (%v)", commitment, packetCommitment) @@ -318,7 +331,7 @@ func (k *Keeper) timeoutPacket( // verify packet receipt absence path := hostv2.PacketReceiptKey(packet.SourceChannel, packet.Sequence) - merklePath := channeltypesv2.BuildMerklePath(channel.MerklePathPrefix, path) + merklePath := types.BuildMerklePath(channel.MerklePathPrefix, path) if err := k.ClientKeeper.VerifyNonMembership( ctx, diff --git a/modules/core/04-channel/v2/keeper/packet_test.go b/modules/core/04-channel/v2/keeper/packet_test.go new file mode 100644 index 00000000000..2fb3d926d5d --- /dev/null +++ b/modules/core/04-channel/v2/keeper/packet_test.go @@ -0,0 +1,605 @@ +package keeper_test + +import ( + "fmt" + "time" + + clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types" + commitmenttypes "github.com/cosmos/ibc-go/v9/modules/core/23-commitment/types" + hostv2 "github.com/cosmos/ibc-go/v9/modules/core/24-host/v2" + ibctm "github.com/cosmos/ibc-go/v9/modules/light-clients/07-tendermint" + ibctesting "github.com/cosmos/ibc-go/v9/testing" + mockv2 "github.com/cosmos/ibc-go/v9/testing/mock/v2" +) + +var unusedChannel = "channel-5" + +func (suite *KeeperTestSuite) TestSendPacket() { + var ( + path *ibctesting.Path + packet types.Packet + expSequence uint64 + ) + + testCases := []struct { + name string + malleate func() + expError error + }{ + { + "success", + func() {}, + nil, + }, + { + "success with later packet", + func() { + // send the same packet earlier so next packet send should be sequence 2 + _, _, err := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.SendPacketTest(suite.chainA.GetContext(), packet.SourceChannel, packet.TimeoutTimestamp, packet.Data) + suite.Require().NoError(err) + expSequence = 2 + }, + nil, + }, + { + "channel not found", + func() { + packet.SourceChannel = ibctesting.InvalidID + }, + types.ErrChannelNotFound, + }, + { + "packet failed basic validation", + func() { + // invalid data + packet.Data = nil + }, + channeltypes.ErrInvalidPacket, + }, + { + "client status invalid", + func() { + path.EndpointA.FreezeClient() + }, + clienttypes.ErrClientNotActive, + }, + { + "client state zero height", func() { + clientState := path.EndpointA.GetClientState() + cs, ok := clientState.(*ibctm.ClientState) + suite.Require().True(ok) + + // force a consensus state into the store at height zero to allow client status check to pass. + consensusState := path.EndpointA.GetConsensusState(cs.LatestHeight) + path.EndpointA.SetConsensusState(consensusState, clienttypes.ZeroHeight()) + + cs.LatestHeight = clienttypes.ZeroHeight() + suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, cs) + }, + clienttypes.ErrInvalidHeight, + }, + { + "timeout elapsed", func() { + packet.TimeoutTimestamp = 1 + }, + channeltypes.ErrTimeoutElapsed, + }, + } + + for i, tc := range testCases { + tc := tc + suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.name, i, len(testCases)), func() { + suite.SetupTest() // reset + + // create clients and set counterparties on both chains + path = ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupV2() + + packetData := mockv2.NewMockPacketData(mockv2.ModuleNameA, mockv2.ModuleNameB) + + timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Add(time.Hour).Unix()) + + // create standard packet that can be malleated + packet = types.NewPacket(1, path.EndpointA.ChannelID, path.EndpointB.ChannelID, + timeoutTimestamp, packetData) + expSequence = 1 + + // malleate the test case + tc.malleate() + + // send packet + seq, destChannel, err := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.SendPacketTest(suite.chainA.GetContext(), packet.SourceChannel, packet.TimeoutTimestamp, packet.Data) + + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err) + // verify send packet method instantiated packet with correct sequence and destination channel + suite.Require().Equal(expSequence, seq) + suite.Require().Equal(path.EndpointB.ChannelID, destChannel) + // verify send packet stored the packet commitment correctly + expCommitment := types.CommitPacket(packet) + suite.Require().Equal(expCommitment, suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.GetPacketCommitment(suite.chainA.GetContext(), packet.SourceChannel, seq)) + } else { + suite.Require().Error(err) + suite.Require().ErrorIs(err, tc.expError) + suite.Require().Equal(uint64(0), seq) + suite.Require().Nil(suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.GetPacketCommitment(suite.chainA.GetContext(), packet.SourceChannel, seq)) + + } + }) + } +} + +func (suite *KeeperTestSuite) TestRecvPacket() { + var ( + path *ibctesting.Path + err error + packet types.Packet + ) + + testCases := []struct { + name string + malleate func() + expError error + }{ + { + "success", + func() {}, + nil, + }, + { + "failure: channel not found", + func() { + packet.DestinationChannel = ibctesting.InvalidID + }, + types.ErrChannelNotFound, + }, + { + "failure: client is not active", + func() { + path.EndpointB.FreezeClient() + }, + clienttypes.ErrClientNotActive, + }, + { + "failure: counterparty channel identifier different than source channel", + func() { + packet.SourceChannel = unusedChannel + }, + channeltypes.ErrInvalidChannelIdentifier, + }, + { + "failure: packet has timed out", + func() { + suite.coordinator.IncrementTimeBy(time.Hour * 20) + }, + channeltypes.ErrTimeoutElapsed, + }, + { + "failure: packet already received", + func() { + suite.chainB.App.GetIBCKeeper().ChannelKeeperV2.SetPacketReceipt(suite.chainB.GetContext(), packet.DestinationChannel, packet.Sequence) + }, + channeltypes.ErrNoOpMsg, + }, + { + "failure: verify membership failed", + func() { + suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.SetPacketCommitment(suite.chainA.GetContext(), packet.SourceChannel, packet.Sequence, []byte("")) + suite.coordinator.CommitBlock(path.EndpointA.Chain) + suite.Require().NoError(path.EndpointB.UpdateClient()) + }, + commitmenttypes.ErrInvalidProof, + }, + } + + for _, tc := range testCases { + tc := tc + + suite.Run(tc.name, func() { + suite.SetupTest() + + path = ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupV2() + + packetData := mockv2.NewMockPacketData(mockv2.ModuleNameA, mockv2.ModuleNameB) + + timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Add(time.Hour).Unix()) + + // send packet + packet, err = path.EndpointA.MsgSendPacket(timeoutTimestamp, packetData) + suite.Require().NoError(err) + + tc.malleate() + + // get proof of v2 packet commitment from chainA + packetKey := hostv2.PacketCommitmentKey(packet.GetSourceChannel(), packet.GetSequence()) + proof, proofHeight := path.EndpointA.QueryProof(packetKey) + + err = suite.chainB.App.GetIBCKeeper().ChannelKeeperV2.RecvPacketTest(suite.chainB.GetContext(), packet, proof, proofHeight) + + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err) + + _, found := suite.chainB.App.GetIBCKeeper().ChannelKeeperV2.GetPacketReceipt(suite.chainB.GetContext(), packet.DestinationChannel, packet.Sequence) + suite.Require().True(found) + } else { + suite.Require().Error(err) + suite.Require().ErrorIs(err, tc.expError) + } + }) + } +} + +func (suite *KeeperTestSuite) TestWriteAcknowledgement() { + var ( + packet types.Packet + ack types.Acknowledgement + ) + + testCases := []struct { + name string + malleate func() + expError error + }{ + { + "success", + func() {}, + nil, + }, + { + "failure: channel not found", + func() { + packet.DestinationChannel = ibctesting.InvalidID + }, + types.ErrChannelNotFound, + }, + { + "failure: counterparty channel identifier different than source channel", + func() { + packet.SourceChannel = unusedChannel + }, + channeltypes.ErrInvalidChannelIdentifier, + }, + { + "failure: ack already exists", + func() { + ackBz := types.CommitAcknowledgement(ack) + suite.chainB.App.GetIBCKeeper().ChannelKeeperV2.SetPacketAcknowledgement(suite.chainB.GetContext(), packet.DestinationChannel, packet.Sequence, ackBz) + }, + channeltypes.ErrAcknowledgementExists, + }, + { + "failure: empty ack", + func() { + ack = types.Acknowledgement{ + AcknowledgementResults: []types.AcknowledgementResult{}, + } + }, + types.ErrInvalidAcknowledgement, + }, + { + "failure: receipt not found for packet", + func() { + packet.Sequence = 2 + }, + channeltypes.ErrInvalidPacket, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() // reset + + path := ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupV2() + + packetData := mockv2.NewMockPacketData(mockv2.ModuleNameA, mockv2.ModuleNameB) + + timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Add(time.Hour).Unix()) + + // create standard packet that can be malleated + packet = types.NewPacket(1, path.EndpointA.ChannelID, path.EndpointB.ChannelID, + timeoutTimestamp, packetData) + + // create standard ack that can be malleated + ack = types.Acknowledgement{ + AcknowledgementResults: []types.AcknowledgementResult{ + { + AppName: mockv2.ModuleNameB, + RecvPacketResult: mockv2.MockRecvPacketResult, + }, + }, + } + + suite.chainB.App.GetIBCKeeper().ChannelKeeperV2.SetPacketReceipt(suite.chainB.GetContext(), packet.DestinationChannel, packet.Sequence) + + tc.malleate() + + err := suite.chainB.App.GetIBCKeeper().ChannelKeeperV2.WriteAcknowledgement(suite.chainB.GetContext(), packet, ack) + + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err) + + ackCommitment := suite.chainB.App.GetIBCKeeper().ChannelKeeperV2.GetPacketAcknowledgement(suite.chainB.GetContext(), packet.DestinationChannel, packet.Sequence) + suite.Require().Equal(types.CommitAcknowledgement(ack), ackCommitment) + } else { + suite.Require().Error(err) + suite.Require().ErrorIs(err, tc.expError) + } + }) + } +} + +func (suite *KeeperTestSuite) TestAcknowledgePacket() { + var ( + packet types.Packet + err error + ack = types.Acknowledgement{ + AcknowledgementResults: []types.AcknowledgementResult{{ + AppName: mockv2.ModuleNameB, + RecvPacketResult: mockv2.MockRecvPacketResult, + }}, + } + freezeClient bool + ) + + testCases := []struct { + name string + malleate func() + expError error + }{ + { + "success", + func() {}, + nil, + }, + { + "failure: channel not found", + func() { + packet.SourceChannel = ibctesting.InvalidID + }, + types.ErrChannelNotFound, + }, + { + "failure: counterparty channel identifier different than source channel", + func() { + packet.DestinationChannel = unusedChannel + }, + channeltypes.ErrInvalidChannelIdentifier, + }, + { + "failure: packet commitment doesn't exist.", + func() { + suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.DeletePacketCommitment(suite.chainA.GetContext(), packet.SourceChannel, packet.Sequence) + }, + channeltypes.ErrNoOpMsg, + }, + { + "failure: client status invalid", + func() { + freezeClient = true + }, + clienttypes.ErrClientNotActive, + }, + { + "failure: packet commitment bytes differ", + func() { + // change packet data after send to acknowledge different packet + packet.Data[0].Payload.Value = []byte("different value") + }, + channeltypes.ErrInvalidPacket, + }, + { + "failure: verify membership fails", + func() { + ack.AcknowledgementResults[0].RecvPacketResult = mockv2.MockFailRecvPacketResult + }, + commitmenttypes.ErrInvalidProof, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() // reset + + path := ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupV2() + + freezeClient = false + + packetData := mockv2.NewMockPacketData(mockv2.ModuleNameA, mockv2.ModuleNameB) + + timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Add(time.Hour).Unix()) + + // send packet + packet, err = path.EndpointA.MsgSendPacket(timeoutTimestamp, packetData) + suite.Require().NoError(err) + + err = path.EndpointB.MsgRecvPacket(packet) + suite.Require().NoError(err) + + tc.malleate() + + packetKey := hostv2.PacketAcknowledgementKey(packet.DestinationChannel, packet.Sequence) + proof, proofHeight := path.EndpointB.QueryProof(packetKey) + + if freezeClient { + path.EndpointA.FreezeClient() + } + + err = suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.AcknowledgePacketTest(suite.chainA.GetContext(), packet, ack, proof, proofHeight) + + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err) + + commitment := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.GetPacketCommitment(suite.chainA.GetContext(), packet.SourceChannel, packet.Sequence) + suite.Require().Empty(commitment) + } else { + suite.Require().Error(err) + suite.Require().ErrorIs(err, tc.expError) + } + }) + } +} + +func (suite *KeeperTestSuite) TestTimeoutPacket() { + var ( + path *ibctesting.Path + packet types.Packet + freezeClient bool + ) + + testCases := []struct { + name string + malleate func() + expError error + }{ + { + "success", + func() { + // send packet + _, _, err := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.SendPacketTest(suite.chainA.GetContext(), packet.SourceChannel, + packet.TimeoutTimestamp, packet.Data) + suite.Require().NoError(err, "send packet failed") + }, + nil, + }, + { + "failure: channel not found", + func() { + // send packet + _, _, err := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.SendPacketTest(suite.chainA.GetContext(), packet.SourceChannel, + packet.TimeoutTimestamp, packet.Data) + suite.Require().NoError(err, "send packet failed") + + packet.SourceChannel = ibctesting.InvalidID + }, + types.ErrChannelNotFound, + }, + { + "failure: counterparty channel identifier different than source channel", + func() { + // send packet + _, _, err := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.SendPacketTest(suite.chainA.GetContext(), packet.SourceChannel, + packet.TimeoutTimestamp, packet.Data) + suite.Require().NoError(err, "send packet failed") + + packet.DestinationChannel = unusedChannel + }, + channeltypes.ErrInvalidChannelIdentifier, + }, + { + "failure: packet has not timed out yet", + func() { + packet.TimeoutTimestamp = uint64(suite.chainB.GetContext().BlockTime().Add(time.Hour).Unix()) + + // send packet + _, _, err := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.SendPacketTest(suite.chainA.GetContext(), packet.SourceChannel, + packet.TimeoutTimestamp, packet.Data) + suite.Require().NoError(err, "send packet failed") + }, + channeltypes.ErrTimeoutNotReached, + }, + { + "failure: packet already timed out", + func() {}, // equivalent to not sending packet at all + channeltypes.ErrNoOpMsg, + }, + { + "failure: packet does not match commitment", + func() { + _, _, err := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.SendPacketTest(suite.chainA.GetContext(), packet.SourceChannel, + packet.TimeoutTimestamp, packet.Data) + suite.Require().NoError(err, "send packet failed") + + // try to timeout packet with different data + packet.Data[0].Payload.Value = []byte("different value") + }, + channeltypes.ErrInvalidPacket, + }, + { + "failure: client status invalid", + func() { + // send packet + _, _, err := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.SendPacketTest(suite.chainA.GetContext(), packet.SourceChannel, + packet.TimeoutTimestamp, packet.Data) + suite.Require().NoError(err, "send packet failed") + + freezeClient = true + }, + clienttypes.ErrClientNotActive, + }, + { + "failure: verify non-membership failed", + func() { + // send packet + _, _, err := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.SendPacketTest(suite.chainA.GetContext(), packet.SourceChannel, + packet.TimeoutTimestamp, packet.Data) + suite.Require().NoError(err, "send packet failed") + + // set packet receipt to mock a valid past receive + suite.chainB.App.GetIBCKeeper().ChannelKeeperV2.SetPacketReceipt(suite.chainB.GetContext(), packet.DestinationChannel, packet.Sequence) + }, + commitmenttypes.ErrInvalidProof, + }, + } + + for _, tc := range testCases { + tc := tc + + suite.Run(tc.name, func() { + suite.SetupTest() + // initialize freezeClient to false + freezeClient = false + + path = ibctesting.NewPath(suite.chainA, suite.chainB) + path.SetupV2() + + // create default packet with a timed out timestamp + packetData := mockv2.NewMockPacketData(mockv2.ModuleNameA, mockv2.ModuleNameB) + + timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Unix()) + + // test cases may mutate timeout values + packet = types.NewPacket(1, path.EndpointA.ChannelID, path.EndpointB.ChannelID, + timeoutTimestamp, packetData) + + tc.malleate() + + // need to update chainA's client representing chainB to prove missing ack + // commit the changes and update the clients + suite.coordinator.CommitBlock(path.EndpointA.Chain) + suite.Require().NoError(path.EndpointB.UpdateClient()) + suite.Require().NoError(path.EndpointA.UpdateClient()) + + // get proof of packet receipt absence from chainB + receiptKey := hostv2.PacketReceiptKey(packet.DestinationChannel, packet.Sequence) + proof, proofHeight := path.EndpointB.QueryProof(receiptKey) + + if freezeClient { + path.EndpointA.FreezeClient() + } + + err := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.TimeoutPacketTest(suite.chainA.GetContext(), packet, proof, proofHeight) + + expPass := tc.expError == nil + if expPass { + suite.Require().NoError(err) + + commitment := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.GetPacketCommitment(suite.chainA.GetContext(), packet.DestinationChannel, packet.Sequence) + suite.Require().Nil(commitment, "packet commitment not deleted") + } else { + suite.Require().Error(err) + suite.Require().ErrorIs(err, tc.expError) + } + }) + } +} diff --git a/modules/core/04-channel/v2/types/errors.go b/modules/core/04-channel/v2/types/errors.go index 2873867295b..1cf10763391 100644 --- a/modules/core/04-channel/v2/types/errors.go +++ b/modules/core/04-channel/v2/types/errors.go @@ -5,10 +5,11 @@ import ( ) var ( - ErrInvalidChannel = errorsmod.Register(SubModuleName, 2, "invalid channel") - ErrChannelNotFound = errorsmod.Register(SubModuleName, 3, "channel not found") - ErrInvalidPacket = errorsmod.Register(SubModuleName, 4, "invalid packet") - ErrInvalidPayload = errorsmod.Register(SubModuleName, 5, "invalid payload") - ErrSequenceSendNotFound = errorsmod.Register(SubModuleName, 6, "sequence send not found") - ErrInvalidPacketData = errorsmod.Register(SubModuleName, 7, "invalid packet data") + ErrInvalidChannel = errorsmod.Register(SubModuleName, 2, "invalid channel") + ErrChannelNotFound = errorsmod.Register(SubModuleName, 3, "channel not found") + ErrInvalidPacket = errorsmod.Register(SubModuleName, 4, "invalid packet") + ErrInvalidPayload = errorsmod.Register(SubModuleName, 5, "invalid payload") + ErrSequenceSendNotFound = errorsmod.Register(SubModuleName, 6, "sequence send not found") + ErrInvalidPacketData = errorsmod.Register(SubModuleName, 7, "invalid packet data") + ErrInvalidAcknowledgement = errorsmod.Register(SubModuleName, 8, "invalid acknowledgement") ) diff --git a/modules/core/04-channel/v2/types/packet.go b/modules/core/04-channel/v2/types/packet.go index 81dd8905e14..8bddb98164f 100644 --- a/modules/core/04-channel/v2/types/packet.go +++ b/modules/core/04-channel/v2/types/packet.go @@ -19,6 +19,15 @@ func NewPacket(sequence uint64, sourceChannel, destinationChannel string, timeou } } +// NewPacketData constructs a new PacketData +func NewPacketData(sourcePort, destPort string, payload Payload) PacketData { + return PacketData{ + SourcePort: sourcePort, + DestinationPort: destPort, + Payload: payload, + } +} + // NewPayload constructs a new Payload func NewPayload(version, encoding string, value []byte) Payload { return Payload{ diff --git a/modules/core/04-channel/v2/types/packet_test.go b/modules/core/04-channel/v2/types/packet_test.go index 4f908d54a90..0f695a050d2 100644 --- a/modules/core/04-channel/v2/types/packet_test.go +++ b/modules/core/04-channel/v2/types/packet_test.go @@ -65,6 +65,13 @@ func TestValidateBasic(t *testing.T) { func() {}, nil, }, + { + "failure: packet data is nil", + func() { + packet.Data = nil + }, + types.ErrInvalidPacket, + }, { "failure: empty data", func() { diff --git a/modules/core/keeper/msg_server_test.go b/modules/core/keeper/msg_server_test.go index 547d5702304..693e93d8c50 100644 --- a/modules/core/keeper/msg_server_test.go +++ b/modules/core/keeper/msg_server_test.go @@ -21,7 +21,6 @@ import ( ibcerrors "github.com/cosmos/ibc-go/v9/modules/core/errors" "github.com/cosmos/ibc-go/v9/modules/core/exported" internalerrors "github.com/cosmos/ibc-go/v9/modules/core/internal/errors" - packetservertypes "github.com/cosmos/ibc-go/v9/modules/core/packet-server/types" ibctm "github.com/cosmos/ibc-go/v9/modules/light-clients/07-tendermint" ibctesting "github.com/cosmos/ibc-go/v9/testing" ibcmock "github.com/cosmos/ibc-go/v9/testing/mock" @@ -218,171 +217,171 @@ func (suite *KeeperTestSuite) TestHandleRecvPacket() { } // tests the IBC handler receiving a packet using V2 protocol -func (suite *KeeperTestSuite) TestRecvPacketV2() { - var ( - packet channeltypes.Packet - path *ibctesting.Path - ) - - testCases := []struct { - name string - malleate func() - expErr error - expRevert bool - async bool // indicate no ack written - replay bool // indicate replay (no-op) - }{ - { - "success", - func() { - path.SetupV2() - - sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibctesting.MockPacketData) - suite.Require().NoError(err) - - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) - }, - nil, - false, - false, - false, - }, - { - "success: OnRecvPacket callback returns error acknowledgement", - func() { - path.SetupV2() - - sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibctesting.MockFailPacketData) - suite.Require().NoError(err) - - packet = channeltypes.NewPacketWithVersion(ibctesting.MockFailPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) - }, - nil, - true, - false, - false, - }, - { - "success: async acknowledgement", - func() { - path.SetupV2() - - sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibcmock.MockAsyncPacketData) - suite.Require().NoError(err) - - packet = channeltypes.NewPacketWithVersion(ibcmock.MockAsyncPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) - }, - nil, - false, - true, - false, - }, - { - "success no-op: packet already received (replay)", - func() { - // mock will panic if application callback is called twice on the same packet - path.SetupV2() - - sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibctesting.MockPacketData) - suite.Require().NoError(err) - - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) - err = path.EndpointB.RecvPacket(packet) - suite.Require().NoError(err) - }, - nil, - false, - false, - true, - }, - { - "channel does not exist", - func() { - // any non-nil value of packet is valid - suite.Require().NotNil(packet) - }, - packetservertypes.ErrChannelNotFound, - false, - false, - false, - }, - { - "packet not sent", - func() { - path.SetupV2() - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) - }, - fmt.Errorf("receive packet verification failed"), - false, - false, - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - path = ibctesting.NewPath(suite.chainA, suite.chainB) - - tc.malleate() - - var ( - proof []byte - proofHeight clienttypes.Height - ) - // get proof of packet commitment from chainA - packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - if path.EndpointA.ClientID != "" { - proof, proofHeight = path.EndpointA.QueryProof(packetKey) - } - - ctx := suite.chainB.GetContext() - msg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, suite.chainB.SenderAccount.GetAddress().String()) - res, err := suite.chainB.App.GetIBCKeeper().RecvPacket(ctx, msg) - - events := ctx.EventManager().Events() - - if tc.expErr == nil { - suite.Require().NoError(err) - - // replay should not fail since it will be treated as a no-op - _, err := suite.chainB.App.GetIBCKeeper().RecvPacket(suite.chainB.GetContext(), msg) - suite.Require().NoError(err) - - if tc.expRevert { - // context events should contain error events - suite.Require().Contains(events, internalerrors.ConvertToErrorEvents(sdk.Events{ibcmock.NewMockRecvPacketEvent()})[0]) - suite.Require().NotContains(events, ibcmock.NewMockRecvPacketEvent()) - } else { - if tc.replay { - // context should not contain application events - suite.Require().NotContains(events, ibcmock.NewMockRecvPacketEvent()) - suite.Require().NotContains(events, internalerrors.ConvertToErrorEvents(sdk.Events{ibcmock.NewMockRecvPacketEvent()})[0]) - } else { - // context events should contain application events - suite.Require().Contains(events, ibcmock.NewMockRecvPacketEvent()) - } - } - - // verify if ack was written - ack, found := suite.chainB.App.GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - - if tc.async { - suite.Require().Nil(ack) - suite.Require().False(found) - } else { - suite.Require().NotNil(ack) - suite.Require().True(found) - } - } else { - suite.Require().ErrorContains(err, tc.expErr.Error()) - suite.Require().Nil(res) - } - }) - } -} +// func (suite *KeeperTestSuite) TestRecvPacketV2() { +// var ( +// packet channeltypes.Packet +// path *ibctesting.Path +// ) + +// testCases := []struct { +// name string +// malleate func() +// expErr error +// expRevert bool +// async bool // indicate no ack written +// replay bool // indicate replay (no-op) +// }{ +// { +// "success", +// func() { +// path.SetupV2() + +// sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibctesting.MockPacketData) +// suite.Require().NoError(err) + +// packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) +// }, +// nil, +// false, +// false, +// false, +// }, +// { +// "success: OnRecvPacket callback returns error acknowledgement", +// func() { +// path.SetupV2() + +// sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibctesting.MockFailPacketData) +// suite.Require().NoError(err) + +// packet = channeltypes.NewPacketWithVersion(ibctesting.MockFailPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) +// }, +// nil, +// true, +// false, +// false, +// }, +// { +// "success: async acknowledgement", +// func() { +// path.SetupV2() + +// sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibcmock.MockAsyncPacketData) +// suite.Require().NoError(err) + +// packet = channeltypes.NewPacketWithVersion(ibcmock.MockAsyncPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) +// }, +// nil, +// false, +// true, +// false, +// }, +// { +// "success no-op: packet already received (replay)", +// func() { +// // mock will panic if application callback is called twice on the same packet +// path.SetupV2() + +// sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibctesting.MockPacketData) +// suite.Require().NoError(err) + +// packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) +// err = path.EndpointB.RecvPacket(packet) +// suite.Require().NoError(err) +// }, +// nil, +// false, +// false, +// true, +// }, +// { +// "channel does not exist", +// func() { +// // any non-nil value of packet is valid +// suite.Require().NotNil(packet) +// }, +// packetservertypes.ErrChannelNotFound, +// false, +// false, +// false, +// }, +// { +// "packet not sent", +// func() { +// path.SetupV2() +// packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) +// }, +// fmt.Errorf("receive packet verification failed"), +// false, +// false, +// false, +// }, +// } + +// for _, tc := range testCases { +// tc := tc + +// suite.Run(tc.name, func() { +// suite.SetupTest() // reset +// path = ibctesting.NewPath(suite.chainA, suite.chainB) + +// tc.malleate() + +// var ( +// proof []byte +// proofHeight clienttypes.Height +// ) +// // get proof of packet commitment from chainA +// packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) +// if path.EndpointA.ClientID != "" { +// proof, proofHeight = path.EndpointA.QueryProof(packetKey) +// } + +// ctx := suite.chainB.GetContext() +// msg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, suite.chainB.SenderAccount.GetAddress().String()) +// res, err := suite.chainB.App.GetIBCKeeper().RecvPacket(ctx, msg) + +// events := ctx.EventManager().Events() + +// if tc.expErr == nil { +// suite.Require().NoError(err) + +// // replay should not fail since it will be treated as a no-op +// _, err := suite.chainB.App.GetIBCKeeper().RecvPacket(suite.chainB.GetContext(), msg) +// suite.Require().NoError(err) + +// if tc.expRevert { +// // context events should contain error events +// suite.Require().Contains(events, internalerrors.ConvertToErrorEvents(sdk.Events{ibcmock.NewMockRecvPacketEvent()})[0]) +// suite.Require().NotContains(events, ibcmock.NewMockRecvPacketEvent()) +// } else { +// if tc.replay { +// // context should not contain application events +// suite.Require().NotContains(events, ibcmock.NewMockRecvPacketEvent()) +// suite.Require().NotContains(events, internalerrors.ConvertToErrorEvents(sdk.Events{ibcmock.NewMockRecvPacketEvent()})[0]) +// } else { +// // context events should contain application events +// suite.Require().Contains(events, ibcmock.NewMockRecvPacketEvent()) +// } +// } + +// // verify if ack was written +// ack, found := suite.chainB.App.GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) + +// if tc.async { +// suite.Require().Nil(ack) +// suite.Require().False(found) +// } else { +// suite.Require().NotNil(ack) +// suite.Require().True(found) +// } +// } else { +// suite.Require().ErrorContains(err, tc.expErr.Error()) +// suite.Require().Nil(res) +// } +// }) +// } +// } func (suite *KeeperTestSuite) TestRecoverClient() { var msg *clienttypes.MsgRecoverClient @@ -618,131 +617,131 @@ func (suite *KeeperTestSuite) TestHandleAcknowledgePacket() { } // tests the IBC handler acknowledgement of a packet using protocol version V2 -func (suite *KeeperTestSuite) TestAcknowledgePacketV2() { - var ( - packet channeltypes.Packet - signer string - path *ibctesting.Path - ) - - testCases := []struct { - name string - malleate func() - expError error - replay bool // indicate replay (no-op) - }{ - { - "success", - func() {}, - nil, - false, - }, - { - "invalid signer", - func() { - signer = "invalid-signer" - }, - errors.New("Invalid address for msg Signer"), - false, - }, - { - "port route does not exist", - func() { - packet.SourcePort = "invalid-port" - }, - porttypes.ErrInvalidRoute, - false, - }, - { - "acknowledge packet fails in packet handler", - func() { - packet.SourceChannel = "invalid-client" - }, - packetservertypes.ErrChannelNotFound, - false, - }, - { - "successful no-op: - packet already acknowledged (replay)", - func() { - err := path.EndpointA.AcknowledgePacket(packet, ibctesting.MockAcknowledgement) - suite.Require().NoError(err) - }, - nil, - true, - }, - { - "application callback returns error", - func() { - suite.chainA.GetSimApp().IBCMockModule.IBCApp.OnAcknowledgementPacket = func(ctx context.Context, channelVersion string, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error { - return fmt.Errorf("mock app callback failed") - } - }, - fmt.Errorf("mock app callback failed"), - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - signer = suite.chainA.SenderAccount.GetAddress().String() - - path = ibctesting.NewPath(suite.chainA, suite.chainB) - path.SetupV2() - - sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibctesting.MockPacketData) - suite.Require().NoError(err) - - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) - err = path.EndpointB.RecvPacket(packet) - suite.Require().NoError(err) - - tc.malleate() - - var ( - proof []byte - proofHeight clienttypes.Height - ) - packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight = path.EndpointB.QueryProof(packetKey) - - msg := channeltypes.NewMsgAcknowledgement(packet, ibcmock.MockAcknowledgement.Acknowledgement(), proof, proofHeight, signer) - - ctx := suite.chainA.GetContext() - res, err := suite.chainA.App.GetIBCKeeper().Acknowledgement(ctx, msg) - - events := ctx.EventManager().Events() - - if tc.expError == nil { - suite.Require().NoError(err) - - // verify packet commitment was deleted on source chain - has := suite.chainA.App.GetIBCKeeper().ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - suite.Require().False(has) - - if tc.replay { - // context should not contain application events - suite.Require().NotContains(events, ibcmock.NewMockAckPacketEvent()) - suite.Require().Equal(channeltypes.NOOP, res.Result) - } else { - // context events should contain application events - suite.Require().Contains(events, ibcmock.NewMockAckPacketEvent()) - suite.Require().Equal(channeltypes.SUCCESS, res.Result) - - // replay should not error as it is treated as a no-op - res, err = suite.chainA.App.GetIBCKeeper().Acknowledgement(suite.chainA.GetContext(), msg) - suite.Require().NoError(err) - suite.Require().Equal(channeltypes.NOOP, res.Result) - } - } else { - suite.Require().ErrorContains(err, tc.expError.Error()) - suite.Require().Nil(res) - } - }) - } -} +// func (suite *KeeperTestSuite) TestAcknowledgePacketV2() { +// var ( +// packet channeltypes.Packet +// signer string +// path *ibctesting.Path +// ) + +// testCases := []struct { +// name string +// malleate func() +// expError error +// replay bool // indicate replay (no-op) +// }{ +// { +// "success", +// func() {}, +// nil, +// false, +// }, +// { +// "invalid signer", +// func() { +// signer = "invalid-signer" +// }, +// errors.New("Invalid address for msg Signer"), +// false, +// }, +// { +// "port route does not exist", +// func() { +// packet.SourcePort = "invalid-port" +// }, +// porttypes.ErrInvalidRoute, +// false, +// }, +// { +// "acknowledge packet fails in packet handler", +// func() { +// packet.SourceChannel = "invalid-client" +// }, +// packetservertypes.ErrChannelNotFound, +// false, +// }, +// { +// "successful no-op: - packet already acknowledged (replay)", +// func() { +// err := path.EndpointA.AcknowledgePacket(packet, ibctesting.MockAcknowledgement) +// suite.Require().NoError(err) +// }, +// nil, +// true, +// }, +// { +// "application callback returns error", +// func() { +// suite.chainA.GetSimApp().IBCMockModule.IBCApp.OnAcknowledgementPacket = func(ctx context.Context, channelVersion string, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error { +// return fmt.Errorf("mock app callback failed") +// } +// }, +// fmt.Errorf("mock app callback failed"), +// false, +// }, +// } + +// for _, tc := range testCases { +// tc := tc + +// suite.Run(tc.name, func() { +// suite.SetupTest() // reset +// signer = suite.chainA.SenderAccount.GetAddress().String() + +// path = ibctesting.NewPath(suite.chainA, suite.chainB) +// path.SetupV2() + +// sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibctesting.MockPacketData) +// suite.Require().NoError(err) + +// packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) +// err = path.EndpointB.RecvPacket(packet) +// suite.Require().NoError(err) + +// tc.malleate() + +// var ( +// proof []byte +// proofHeight clienttypes.Height +// ) +// packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) +// proof, proofHeight = path.EndpointB.QueryProof(packetKey) + +// msg := channeltypes.NewMsgAcknowledgement(packet, ibcmock.MockAcknowledgement.Acknowledgement(), proof, proofHeight, signer) + +// ctx := suite.chainA.GetContext() +// res, err := suite.chainA.App.GetIBCKeeper().Acknowledgement(ctx, msg) + +// events := ctx.EventManager().Events() + +// if tc.expError == nil { +// suite.Require().NoError(err) + +// // verify packet commitment was deleted on source chain +// has := suite.chainA.App.GetIBCKeeper().ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) +// suite.Require().False(has) + +// if tc.replay { +// // context should not contain application events +// suite.Require().NotContains(events, ibcmock.NewMockAckPacketEvent()) +// suite.Require().Equal(channeltypes.NOOP, res.Result) +// } else { +// // context events should contain application events +// suite.Require().Contains(events, ibcmock.NewMockAckPacketEvent()) +// suite.Require().Equal(channeltypes.SUCCESS, res.Result) + +// // replay should not error as it is treated as a no-op +// res, err = suite.chainA.App.GetIBCKeeper().Acknowledgement(suite.chainA.GetContext(), msg) +// suite.Require().NoError(err) +// suite.Require().Equal(channeltypes.NOOP, res.Result) +// } +// } else { +// suite.Require().ErrorContains(err, tc.expError.Error()) +// suite.Require().Nil(res) +// } +// }) +// } +// } // tests the IBC handler timing out a packet on ordered and unordered channels. // It verifies that the deletion of a packet commitment occurs. It tests @@ -906,138 +905,138 @@ func (suite *KeeperTestSuite) TestHandleTimeoutPacket() { // It verifies that the deletion of a packet commitment occurs. More // rigorous testing of 'TimeoutPacket' and 'TimeoutExecuted' can be found in // the packet-server/keeper/keeper_test.go. -func (suite *KeeperTestSuite) TestTimeoutPacketV2() { - var ( - packet channeltypes.Packet - packetKey []byte - path *ibctesting.Path - ) - - testCases := []struct { - name string - malleate func() - expErr error - noop bool // indicate no-op - }{ - { - "success", - func() { - path.SetupV2() - - timeoutHeight := clienttypes.GetSelfHeight(suite.chainB.GetContext()) - timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().UnixNano()) - - // create packet commitment - sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, timeoutTimestamp, ibcmock.Version, ibctesting.MockPacketData) - suite.Require().NoError(err) - - // need to update chainA client to prove missing ack - err = path.EndpointA.UpdateClient() - suite.Require().NoError(err) - - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, timeoutTimestamp, ibcmock.Version) - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - }, - nil, - false, - }, - { - "success: timeout out of order packet", - func() { - // setup uses an UNORDERED channel - path.SetupV2() - - // attempts to timeout the last packet sent without timing out the first packet - // packet sequences begin at 1 - for i := uint64(1); i < maxSequence; i++ { - timeoutHeight := clienttypes.GetSelfHeight(suite.chainB.GetContext()) - - // create packet commitment - sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibctesting.MockPacketData) - suite.Require().NoError(err) - - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) - } - - err := path.EndpointA.UpdateClient() - suite.Require().NoError(err) - - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - }, - nil, - false, - }, - { - "success no-op: packet not sent", func() { - path.SetupV2() - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 1), 0, ibcmock.Version) - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - }, - nil, - true, - }, - { - "channel does not exist", - func() { - // any non-nil value of packet is valid - suite.Require().NotNil(packet) - - packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - }, - packetservertypes.ErrChannelNotFound, - false, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() // reset - path = ibctesting.NewPath(suite.chainA, suite.chainB) - - tc.malleate() - - var ( - proof []byte - proofHeight clienttypes.Height - ) - if path.EndpointB.ClientID != "" { - proof, proofHeight = path.EndpointB.QueryProof(packetKey) - } - - ctx := suite.chainA.GetContext() - msg := channeltypes.NewMsgTimeout(packet, 1, proof, proofHeight, suite.chainA.SenderAccount.GetAddress().String()) - res, err := suite.chainA.App.GetIBCKeeper().Timeout(ctx, msg) - - events := ctx.EventManager().Events() - - if tc.expErr == nil { - suite.Require().NoError(err) - - // replay should not return an error as it is treated as a no-op - _, err := suite.chainA.App.GetIBCKeeper().Timeout(suite.chainA.GetContext(), msg) - suite.Require().NoError(err) - - // verify packet commitment was deleted on source chain - has := suite.chainA.App.GetIBCKeeper().ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - suite.Require().False(has) - - if tc.noop { - // context should not contain application events - suite.Require().NotContains(events, ibcmock.NewMockTimeoutPacketEvent()) - } else { - // context should contain application events - suite.Require().Contains(events, ibcmock.NewMockTimeoutPacketEvent()) - } - - } else { - suite.Require().ErrorIs(err, tc.expErr) - suite.Require().Nil(res) - } - }) - } -} +// func (suite *KeeperTestSuite) TestTimeoutPacketV2() { +// var ( +// packet channeltypes.Packet +// packetKey []byte +// path *ibctesting.Path +// ) + +// testCases := []struct { +// name string +// malleate func() +// expErr error +// noop bool // indicate no-op +// }{ +// { +// "success", +// func() { +// path.SetupV2() + +// timeoutHeight := clienttypes.GetSelfHeight(suite.chainB.GetContext()) +// timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().UnixNano()) + +// // create packet commitment +// sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, timeoutTimestamp, ibcmock.Version, ibctesting.MockPacketData) +// suite.Require().NoError(err) + +// // need to update chainA client to prove missing ack +// err = path.EndpointA.UpdateClient() +// suite.Require().NoError(err) + +// packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, timeoutTimestamp, ibcmock.Version) +// packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) +// }, +// nil, +// false, +// }, +// { +// "success: timeout out of order packet", +// func() { +// // setup uses an UNORDERED channel +// path.SetupV2() + +// // attempts to timeout the last packet sent without timing out the first packet +// // packet sequences begin at 1 +// for i := uint64(1); i < maxSequence; i++ { +// timeoutHeight := clienttypes.GetSelfHeight(suite.chainB.GetContext()) + +// // create packet commitment +// sequence, err := path.EndpointA.SendPacketV2(timeoutHeight, 0, ibcmock.Version, ibctesting.MockPacketData) +// suite.Require().NoError(err) + +// packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0, ibcmock.Version) +// } + +// err := path.EndpointA.UpdateClient() +// suite.Require().NoError(err) + +// packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) +// }, +// nil, +// false, +// }, +// { +// "success no-op: packet not sent", func() { +// path.SetupV2() +// packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 1), 0, ibcmock.Version) +// packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) +// }, +// nil, +// true, +// }, +// { +// "channel does not exist", +// func() { +// // any non-nil value of packet is valid +// suite.Require().NotNil(packet) + +// packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) +// }, +// packetservertypes.ErrChannelNotFound, +// false, +// }, +// } + +// for _, tc := range testCases { +// tc := tc + +// suite.Run(tc.name, func() { +// suite.SetupTest() // reset +// path = ibctesting.NewPath(suite.chainA, suite.chainB) + +// tc.malleate() + +// var ( +// proof []byte +// proofHeight clienttypes.Height +// ) +// if path.EndpointB.ClientID != "" { +// proof, proofHeight = path.EndpointB.QueryProof(packetKey) +// } + +// ctx := suite.chainA.GetContext() +// msg := channeltypes.NewMsgTimeout(packet, 1, proof, proofHeight, suite.chainA.SenderAccount.GetAddress().String()) +// res, err := suite.chainA.App.GetIBCKeeper().Timeout(ctx, msg) + +// events := ctx.EventManager().Events() + +// if tc.expErr == nil { +// suite.Require().NoError(err) + +// // replay should not return an error as it is treated as a no-op +// _, err := suite.chainA.App.GetIBCKeeper().Timeout(suite.chainA.GetContext(), msg) +// suite.Require().NoError(err) + +// // verify packet commitment was deleted on source chain +// has := suite.chainA.App.GetIBCKeeper().ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) +// suite.Require().False(has) + +// if tc.noop { +// // context should not contain application events +// suite.Require().NotContains(events, ibcmock.NewMockTimeoutPacketEvent()) +// } else { +// // context should contain application events +// suite.Require().Contains(events, ibcmock.NewMockTimeoutPacketEvent()) +// } + +// } else { +// suite.Require().ErrorIs(err, tc.expErr) +// suite.Require().Nil(res) +// } +// }) +// } +// } // tests the IBC handler timing out a packet via channel closure on ordered // and unordered channels. It verifies that the deletion of a packet diff --git a/modules/core/packet-server/keeper/relay_test.go b/modules/core/packet-server/keeper/relay_test.go deleted file mode 100644 index e2fb7e8458b..00000000000 --- a/modules/core/packet-server/keeper/relay_test.go +++ /dev/null @@ -1,643 +0,0 @@ -package keeper_test - -import ( - "fmt" - "testing" - - testifysuite "github.com/stretchr/testify/suite" - - 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" - host "github.com/cosmos/ibc-go/v9/modules/core/24-host" - "github.com/cosmos/ibc-go/v9/modules/core/exported" - "github.com/cosmos/ibc-go/v9/modules/core/packet-server/types" - 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" -) - -var ( - defaultTimeoutHeight = clienttypes.NewHeight(1, 100) - disabledTimeoutTimestamp = uint64(0) - unusedChannel = "channel-5" -) - -// KeeperTestSuite is a testing suite to test keeper functions. -type KeeperTestSuite struct { - testifysuite.Suite - - coordinator *ibctesting.Coordinator - - // testing chains used for convenience and readability - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain -} - -// TestKeeperTestSuite runs all the tests within this package. -func TestKeeperTestSuite(t *testing.T) { - testifysuite.Run(t, new(KeeperTestSuite)) -} - -// SetupTest creates a coordinator with 2 test chains. -func (suite *KeeperTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(2)) - - // 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) -} - -func (suite *KeeperTestSuite) TestSendPacket() { - var ( - path *ibctesting.Path - packet channeltypes.Packet - ) - - testCases := []struct { - name string - malleate func() - expError error - }{ - { - "success", - func() {}, - nil, - }, - { - "channel not found", - func() { - packet.SourceChannel = ibctesting.InvalidID - }, - types.ErrChannelNotFound, - }, - { - "packet failed basic validation", - func() { - // invalid data - packet.Data = nil - }, - channeltypes.ErrInvalidPacket, - }, - { - "client status invalid", - func() { - path.EndpointA.FreezeClient() - }, - clienttypes.ErrClientNotActive, - }, - { - "client state zero height", func() { - clientState := path.EndpointA.GetClientState() - cs, ok := clientState.(*ibctm.ClientState) - suite.Require().True(ok) - - // force a consensus state into the store at height zero to allow client status check to pass. - consensusState := path.EndpointA.GetConsensusState(cs.LatestHeight) - path.EndpointA.SetConsensusState(consensusState, clienttypes.ZeroHeight()) - - cs.LatestHeight = clienttypes.ZeroHeight() - suite.chainA.App.GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, cs) - }, - clienttypes.ErrInvalidHeight, - }, - { - "timeout elapsed", func() { - packet.TimeoutTimestamp = 1 - }, - channeltypes.ErrTimeoutElapsed, - }, - } - - for i, tc := range testCases { - tc := tc - suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.name, i, len(testCases)), func() { - suite.SetupTest() // reset - - // create clients and set counterparties on both chains - path = ibctesting.NewPath(suite.chainA, suite.chainB) - path.SetupV2() - - // create standard packet that can be malleated - packet = channeltypes.NewPacketWithVersion(mock.MockPacketData, 1, mock.PortID, - path.EndpointA.ChannelID, mock.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(1, 100), 0, mock.Version) - - // malleate the test case - tc.malleate() - - // send packet - seq, err := suite.chainA.App.GetPacketServer().SendPacket(suite.chainA.GetContext(), packet.SourceChannel, packet.SourcePort, - packet.DestinationPort, packet.TimeoutHeight, packet.TimeoutTimestamp, packet.AppVersion, packet.Data) - - expPass := tc.expError == nil - if expPass { - suite.Require().NoError(err) - suite.Require().Equal(uint64(1), seq) - expCommitment := channeltypes.CommitPacket(packet) - suite.Require().Equal(expCommitment, suite.chainA.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.SourcePort, packet.SourceChannel, seq)) - } else { - suite.Require().Error(err) - suite.Require().ErrorIs(err, tc.expError) - suite.Require().Equal(uint64(0), seq) - suite.Require().Nil(suite.chainA.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.SourcePort, packet.SourceChannel, seq)) - - } - }) - } -} - -func (suite *KeeperTestSuite) TestRecvPacket() { - var ( - path *ibctesting.Path - packet channeltypes.Packet - ) - - testCases := []struct { - name string - malleate func() - expError error - }{ - { - "success", - func() {}, - nil, - }, - { - "failure: protocol version is not V2", - func() { - packet.ProtocolVersion = channeltypes.IBC_VERSION_1 - }, - channeltypes.ErrInvalidPacket, - }, - { - "failure: channel not found", - func() { - packet.DestinationChannel = ibctesting.InvalidID - }, - types.ErrChannelNotFound, - }, - { - "failure: client is not active", - func() { - path.EndpointB.FreezeClient() - }, - clienttypes.ErrClientNotActive, - }, - { - "failure: counterparty channel identifier different than source channel", - func() { - packet.SourceChannel = unusedChannel - }, - channeltypes.ErrInvalidChannelIdentifier, - }, - { - "failure: packet has timed out", - func() { - packet.TimeoutHeight = clienttypes.ZeroHeight() - packet.TimeoutTimestamp = uint64(suite.chainB.GetContext().BlockTime().UnixNano()) - }, - channeltypes.ErrTimeoutElapsed, - }, - { - "failure: packet already received", - func() { - suite.chainB.App.GetIBCKeeper().ChannelKeeper.SetPacketReceipt(suite.chainB.GetContext(), packet.DestinationPort, packet.DestinationChannel, packet.Sequence) - }, - channeltypes.ErrNoOpMsg, - }, - { - "failure: verify membership failed", - func() { - suite.chainA.App.GetIBCKeeper().ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), packet.SourcePort, packet.SourceChannel, packet.Sequence, []byte("")) - suite.coordinator.CommitBlock(path.EndpointA.Chain) - suite.Require().NoError(path.EndpointB.UpdateClient()) - }, - commitmenttypes.ErrInvalidProof, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - - path = ibctesting.NewPath(suite.chainA, suite.chainB) - path.SetupV2() - - // send packet - sequence, err := path.EndpointA.SendPacketV2(defaultTimeoutHeight, disabledTimeoutTimestamp, mock.Version, ibctesting.MockPacketData) - suite.Require().NoError(err) - - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, disabledTimeoutTimestamp, mock.Version) - - tc.malleate() - - // get proof of packet commitment from chainA - packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence()) - proof, proofHeight := path.EndpointA.QueryProof(packetKey) - - _, err = suite.chainB.App.GetPacketServer().RecvPacket(suite.chainB.GetContext(), packet, proof, proofHeight) - - expPass := tc.expError == nil - if expPass { - suite.Require().NoError(err) - - _, found := suite.chainB.App.GetIBCKeeper().ChannelKeeper.GetPacketReceipt(suite.chainB.GetContext(), packet.DestinationPort, packet.DestinationChannel, packet.Sequence) - suite.Require().True(found) - } else { - suite.Require().Error(err) - suite.Require().ErrorIs(err, tc.expError) - } - }) - } -} - -func (suite *KeeperTestSuite) TestWriteAcknowledgement() { - var ( - packet channeltypes.Packet - ack exported.Acknowledgement - ) - - testCases := []struct { - name string - malleate func() - expError error - }{ - { - "success", - func() {}, - nil, - }, - { - "failure: protocol version is not IBC_VERSION_2", - func() { - packet.ProtocolVersion = channeltypes.IBC_VERSION_1 - }, - channeltypes.ErrInvalidPacket, - }, - { - "failure: channel not found", - func() { - packet.DestinationChannel = ibctesting.InvalidID - }, - types.ErrChannelNotFound, - }, - { - "failure: counterparty channel identifier different than source channel", - func() { - packet.SourceChannel = unusedChannel - }, - channeltypes.ErrInvalidChannelIdentifier, - }, - { - "failure: ack already exists", - func() { - ackBz := channeltypes.CommitAcknowledgement(ack.Acknowledgement()) - suite.chainB.App.GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(suite.chainB.GetContext(), packet.DestinationPort, packet.DestinationChannel, packet.Sequence, ackBz) - }, - channeltypes.ErrAcknowledgementExists, - }, - { - "failure: ack is nil", - func() { - ack = nil - }, - channeltypes.ErrInvalidAcknowledgement, - }, - { - "failure: empty ack", - func() { - ack = mock.NewEmptyAcknowledgement() - }, - channeltypes.ErrInvalidAcknowledgement, - }, - { - "failure: receipt not found for packet", - func() { - packet.Sequence = 2 - }, - channeltypes.ErrInvalidPacket, - }, - } - - for _, tc := range testCases { - tc := tc - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - path := ibctesting.NewPath(suite.chainA, suite.chainB) - path.SetupV2() - - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, disabledTimeoutTimestamp, mock.Version) - ack = mock.MockAcknowledgement - - suite.chainB.App.GetIBCKeeper().ChannelKeeper.SetPacketReceipt(suite.chainB.GetContext(), packet.DestinationPort, packet.DestinationChannel, packet.Sequence) - - tc.malleate() - - err := suite.chainB.App.GetPacketServer().WriteAcknowledgement(suite.chainB.GetContext(), packet, ack) - - expPass := tc.expError == nil - if expPass { - suite.Require().NoError(err) - - ackCommitment, found := suite.chainB.App.GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(suite.chainB.GetContext(), packet.DestinationPort, packet.DestinationChannel, packet.Sequence) - suite.Require().True(found) - suite.Require().Equal(channeltypes.CommitAcknowledgement(ack.Acknowledgement()), ackCommitment) - } else { - suite.Require().Error(err) - suite.Require().ErrorIs(err, tc.expError) - } - }) - } -} - -func (suite *KeeperTestSuite) TestAcknowledgePacket() { - var ( - packet channeltypes.Packet - ack = mock.MockAcknowledgement - freezeClient bool - ) - - testCases := []struct { - name string - malleate func() - expError error - }{ - { - "success", - func() {}, - nil, - }, - { - "failure: protocol version is not IBC_VERSION_2", - func() { - packet.ProtocolVersion = channeltypes.IBC_VERSION_1 - }, - channeltypes.ErrInvalidPacket, - }, - { - "failure: channel not found", - func() { - packet.SourceChannel = ibctesting.InvalidID - }, - types.ErrChannelNotFound, - }, - { - "failure: counterparty channel identifier different than source channel", - func() { - packet.DestinationChannel = unusedChannel - }, - channeltypes.ErrInvalidChannelIdentifier, - }, - { - "failure: packet commitment doesn't exist.", - func() { - suite.chainA.App.GetIBCKeeper().ChannelKeeper.DeletePacketCommitment(suite.chainA.GetContext(), packet.SourcePort, packet.SourceChannel, packet.Sequence) - }, - channeltypes.ErrNoOpMsg, - }, - { - "failure: client status invalid", - func() { - freezeClient = true - }, - clienttypes.ErrClientNotActive, - }, - { - "failure: packet commitment bytes differ", - func() { - packet.Data = []byte("") - }, - channeltypes.ErrInvalidPacket, - }, - { - "failure: verify membership fails", - func() { - ack = channeltypes.NewResultAcknowledgement([]byte("swapped acknowledgement")) - }, - commitmenttypes.ErrInvalidProof, - }, - } - - for _, tc := range testCases { - tc := tc - suite.Run(tc.name, func() { - suite.SetupTest() // reset - - path := ibctesting.NewPath(suite.chainA, suite.chainB) - path.SetupV2() - - freezeClient = false - - // send packet - sequence, err := path.EndpointA.SendPacketV2(defaultTimeoutHeight, disabledTimeoutTimestamp, mock.Version, ibctesting.MockPacketData) - suite.Require().NoError(err) - - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, sequence, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, disabledTimeoutTimestamp, mock.Version) - - err = path.EndpointB.RecvPacket(packet) - suite.Require().NoError(err) - - tc.malleate() - - packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight := path.EndpointB.QueryProof(packetKey) - - if freezeClient { - path.EndpointA.FreezeClient() - } - - _, err = suite.chainA.App.GetPacketServer().AcknowledgePacket(suite.chainA.GetContext(), packet, ack.Acknowledgement(), proof, proofHeight) - - expPass := tc.expError == nil - if expPass { - suite.Require().NoError(err) - - commitment := suite.chainA.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.SourcePort, packet.SourceChannel, packet.Sequence) - suite.Require().Empty(commitment) - } else { - suite.Require().Error(err) - suite.Require().ErrorIs(err, tc.expError) - } - }) - } -} - -func (suite *KeeperTestSuite) TestTimeoutPacket() { - var ( - path *ibctesting.Path - packet channeltypes.Packet - freezeClient bool - ) - - testCases := []struct { - name string - malleate func() - expError error - }{ - { - "success with timeout height", - func() { - // send packet - _, err := suite.chainA.App.GetPacketServer().SendPacket(suite.chainA.GetContext(), packet.SourceChannel, packet.SourcePort, packet.DestinationPort, - packet.TimeoutHeight, packet.TimeoutTimestamp, packet.AppVersion, packet.Data) - suite.Require().NoError(err, "send packet failed") - }, - nil, - }, - { - "success with timeout timestamp", - func() { - // disable timeout height and set timeout timestamp to a past timestamp - packet.TimeoutHeight = clienttypes.Height{} - packet.TimeoutTimestamp = uint64(suite.chainB.GetContext().BlockTime().UnixNano()) - - // send packet - _, err := suite.chainA.App.GetPacketServer().SendPacket(suite.chainA.GetContext(), packet.SourceChannel, packet.SourcePort, packet.DestinationPort, - packet.TimeoutHeight, packet.TimeoutTimestamp, packet.AppVersion, packet.Data) - suite.Require().NoError(err, "send packet failed") - }, - nil, - }, - { - "failure: invalid protocol version", - func() { - // send packet - _, err := suite.chainA.App.GetPacketServer().SendPacket(suite.chainA.GetContext(), packet.SourceChannel, packet.SourcePort, packet.DestinationPort, - packet.TimeoutHeight, packet.TimeoutTimestamp, packet.AppVersion, packet.Data) - suite.Require().NoError(err, "send packet failed") - - packet.ProtocolVersion = channeltypes.IBC_VERSION_1 - packet.AppVersion = "" - }, - channeltypes.ErrInvalidPacket, - }, - { - "failure: channel not found", - func() { - // send packet - _, err := suite.chainA.App.GetPacketServer().SendPacket(suite.chainA.GetContext(), packet.SourceChannel, packet.SourcePort, packet.DestinationPort, - packet.TimeoutHeight, packet.TimeoutTimestamp, packet.AppVersion, packet.Data) - suite.Require().NoError(err, "send packet failed") - - packet.SourceChannel = ibctesting.InvalidID - }, - types.ErrChannelNotFound, - }, - { - "failure: counterparty channel identifier different than source channel", - func() { - // send packet - _, err := suite.chainA.App.GetPacketServer().SendPacket(suite.chainA.GetContext(), packet.SourceChannel, packet.SourcePort, packet.DestinationPort, - packet.TimeoutHeight, packet.TimeoutTimestamp, packet.AppVersion, packet.Data) - suite.Require().NoError(err, "send packet failed") - - packet.DestinationChannel = unusedChannel - }, - channeltypes.ErrInvalidChannelIdentifier, - }, - { - "failure: packet has not timed out yet", - func() { - packet.TimeoutHeight = defaultTimeoutHeight - - // send packet - _, err := suite.chainA.App.GetPacketServer().SendPacket(suite.chainA.GetContext(), packet.SourceChannel, packet.SourcePort, packet.DestinationPort, - packet.TimeoutHeight, packet.TimeoutTimestamp, packet.AppVersion, packet.Data) - suite.Require().NoError(err, "send packet failed") - }, - channeltypes.ErrTimeoutNotReached, - }, - { - "failure: packet already timed out", - func() {}, // equivalent to not sending packet at all - channeltypes.ErrNoOpMsg, - }, - { - "failure: packet does not match commitment", - func() { - // send a different packet - _, err := suite.chainA.App.GetPacketServer().SendPacket(suite.chainA.GetContext(), packet.SourceChannel, packet.SourcePort, packet.DestinationPort, - packet.TimeoutHeight, packet.TimeoutTimestamp, packet.AppVersion, []byte("different data")) - suite.Require().NoError(err, "send packet failed") - }, - channeltypes.ErrInvalidPacket, - }, - { - "failure: client status invalid", - func() { - // send packet - _, err := suite.chainA.App.GetPacketServer().SendPacket(suite.chainA.GetContext(), packet.SourceChannel, packet.SourcePort, packet.DestinationPort, - packet.TimeoutHeight, packet.TimeoutTimestamp, packet.AppVersion, packet.Data) - suite.Require().NoError(err, "send packet failed") - - freezeClient = true - }, - clienttypes.ErrClientNotActive, - }, - { - "failure: verify non-membership failed", - func() { - // send packet - _, err := suite.chainA.App.GetPacketServer().SendPacket(suite.chainA.GetContext(), packet.SourceChannel, packet.SourcePort, packet.DestinationPort, - packet.TimeoutHeight, packet.TimeoutTimestamp, packet.AppVersion, packet.Data) - suite.Require().NoError(err, "send packet failed") - - // set packet receipt to mock a valid past receive - suite.chainB.App.GetIBCKeeper().ChannelKeeper.SetPacketReceipt(suite.chainB.GetContext(), packet.DestinationPort, packet.DestinationChannel, packet.Sequence) - }, - commitmenttypes.ErrInvalidProof, - }, - } - - for _, tc := range testCases { - tc := tc - - suite.Run(tc.name, func() { - suite.SetupTest() - // initialize freezeClient to false - freezeClient = false - - path = ibctesting.NewPath(suite.chainA, suite.chainB) - path.SetupV2() - - // create default packet with a timed out height - // test cases may mutate timeout values - timeoutHeight := clienttypes.GetSelfHeight(suite.chainB.GetContext()) - packet = channeltypes.NewPacketWithVersion(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp, mock.Version) - - tc.malleate() - - // need to update chainA's client representing chainB to prove missing ack - // commit the changes and update the clients - suite.coordinator.CommitBlock(path.EndpointA.Chain) - suite.Require().NoError(path.EndpointB.UpdateClient()) - suite.Require().NoError(path.EndpointA.UpdateClient()) - - // get proof of packet receipt absence from chainB - receiptKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()) - proof, proofHeight := path.EndpointB.QueryProof(receiptKey) - - if freezeClient { - path.EndpointA.FreezeClient() - } - - _, err := suite.chainA.App.GetPacketServer().TimeoutPacket(suite.chainA.GetContext(), packet, proof, proofHeight, 0) - - expPass := tc.expError == nil - if expPass { - suite.Require().NoError(err) - - commitment := suite.chainA.App.GetIBCKeeper().ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.DestinationPort, packet.DestinationChannel, packet.Sequence) - suite.Require().Nil(commitment, "packet commitment not deleted") - } else { - suite.Require().Error(err) - suite.Require().ErrorIs(err, tc.expError) - } - }) - } -} diff --git a/testing/endpoint.go b/testing/endpoint.go index 82f735ae78e..cf4ade13155 100644 --- a/testing/endpoint.go +++ b/testing/endpoint.go @@ -468,33 +468,6 @@ func (endpoint *Endpoint) ChanCloseInit() error { return endpoint.Chain.sendMsgs(msg) } -// SendPacketV2 sends a packet through the packet server using the associated endpoint -// The counterparty client is updated so proofs can be sent to the counterparty chain. -// The packet sequence generated for the packet to be sent is returned. An error -// is returned if one occurs. -func (endpoint *Endpoint) SendPacketV2( - timeoutHeight clienttypes.Height, - timeoutTimestamp uint64, - version string, - data []byte, -) (uint64, error) { - // no need to send message, acting as a module - sequence, err := endpoint.Chain.App.GetPacketServer().SendPacket(endpoint.Chain.GetContext(), endpoint.ChannelID, endpoint.ChannelConfig.PortID, endpoint.Counterparty.ChannelConfig.PortID, timeoutHeight, timeoutTimestamp, version, data) - if err != nil { - return 0, err - } - - // commit changes since no message was sent - endpoint.Chain.Coordinator.CommitBlock(endpoint.Chain) - - err = endpoint.Counterparty.UpdateClient() - if err != nil { - return 0, err - } - - return sequence, nil -} - // SendPacket sends a packet through the channel keeper using the associated endpoint // The counterparty client is updated so proofs can be sent to the counterparty chain. // The packet sequence generated for the packet to be sent is returned. An error diff --git a/testing/endpoint_v2.go b/testing/endpoint_v2.go index 506ce2b03f2..e486e7a29d2 100644 --- a/testing/endpoint_v2.go +++ b/testing/endpoint_v2.go @@ -1,7 +1,9 @@ package ibctesting import ( - "github.com/stretchr/testify/require" + "github.com/cosmos/gogoproto/proto" + + sdk "github.com/cosmos/cosmos-sdk/types" channeltypesv2 "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types" hostv2 "github.com/cosmos/ibc-go/v9/modules/core/24-host/v2" @@ -11,7 +13,7 @@ import ( func (endpoint *Endpoint) MsgSendPacket(timeoutTimestamp uint64, packetData channeltypesv2.PacketData) (channeltypesv2.Packet, error) { msgSendPacket := channeltypesv2.NewMsgSendPacket(endpoint.ChannelID, timeoutTimestamp, endpoint.Chain.SenderAccount.GetAddress().String(), packetData) - _, err := endpoint.Chain.SendMsgs(msgSendPacket) + res, err := endpoint.Chain.SendMsgs(msgSendPacket) if err != nil { return channeltypesv2.Packet{}, err } @@ -20,10 +22,20 @@ func (endpoint *Endpoint) MsgSendPacket(timeoutTimestamp uint64, packetData chan return channeltypesv2.Packet{}, err } - // TODO: parse the packet from events instead of manually constructing it. https://github.com/cosmos/ibc-go/issues/7459 - nextSequenceSend, ok := endpoint.Chain.GetSimApp().IBCKeeper.ChannelKeeperV2.GetNextSequenceSend(endpoint.Chain.GetContext(), endpoint.ChannelID) - require.True(endpoint.Chain.TB, ok) - packet := channeltypesv2.NewPacket(nextSequenceSend-1, endpoint.ChannelID, endpoint.Counterparty.ChannelID, timeoutTimestamp, packetData) + // TODO: parse the packet from events instead of from the response. https://github.com/cosmos/ibc-go/issues/7459 + // get sequence from msg response + var msgData sdk.TxMsgData + err = proto.Unmarshal(res.Data, &msgData) + if err != nil { + return channeltypesv2.Packet{}, err + } + msgResponse := msgData.MsgResponses[0] + var sendResponse channeltypesv2.MsgSendPacketResponse + err = proto.Unmarshal(msgResponse.Value, &sendResponse) + if err != nil { + return channeltypesv2.Packet{}, err + } + packet := channeltypesv2.NewPacket(sendResponse.Sequence, endpoint.ChannelID, endpoint.Counterparty.ChannelID, timeoutTimestamp, packetData) return packet, nil } diff --git a/testing/mock/v2/ibc_module.go b/testing/mock/v2/ibc_module.go index 871b870bba4..dcf891b2b51 100644 --- a/testing/mock/v2/ibc_module.go +++ b/testing/mock/v2/ibc_module.go @@ -7,7 +7,6 @@ import ( channeltypesv2 "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types" "github.com/cosmos/ibc-go/v9/modules/core/api" - mockv1 "github.com/cosmos/ibc-go/v9/testing/mock" ) var _ api.IBCModule = (*IBCModule)(nil) @@ -43,10 +42,7 @@ func (im IBCModule) OnRecvPacket(ctx context.Context, sourceChannel string, dest if im.IBCApp.OnRecvPacket != nil { return im.IBCApp.OnRecvPacket(ctx, sourceChannel, destinationChannel, data, relayer) } - return channeltypesv2.RecvPacketResult{ - Status: channeltypesv2.PacketStatus_Success, - Acknowledgement: mockv1.MockPacketData, - } + return MockRecvPacketResult } func (im IBCModule) OnAcknowledgementPacket(ctx context.Context, sourceChannel string, destinationChannel string, data channeltypesv2.PacketData, acknowledgement []byte, relayer sdk.AccAddress) error { diff --git a/testing/mock/v2/mock.go b/testing/mock/v2/mock.go index 6ac92899672..c6403b12364 100644 --- a/testing/mock/v2/mock.go +++ b/testing/mock/v2/mock.go @@ -1,22 +1,33 @@ package mock import ( - "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types" - "github.com/cosmos/ibc-go/v9/testing/mock" + channeltypesv2 "github.com/cosmos/ibc-go/v9/modules/core/04-channel/v2/types" + mockv1 "github.com/cosmos/ibc-go/v9/testing/mock" ) const ( ModuleName = "mockv2" ) -func NewMockPacketData(sourcePort, destPort string) types.PacketData { - return types.PacketData{ +var ( + MockRecvPacketResult = channeltypesv2.RecvPacketResult{ + Status: channeltypesv2.PacketStatus_Success, + Acknowledgement: mockv1.MockAcknowledgement.Acknowledgement(), + } + MockFailRecvPacketResult = channeltypesv2.RecvPacketResult{ + Status: channeltypesv2.PacketStatus_Success, + Acknowledgement: mockv1.MockFailAcknowledgement.Acknowledgement(), + } +) + +func NewMockPacketData(sourcePort, destPort string) channeltypesv2.PacketData { + return channeltypesv2.PacketData{ SourcePort: sourcePort, DestinationPort: destPort, - Payload: types.Payload{ + Payload: channeltypesv2.Payload{ Encoding: "json", - Value: mock.MockPacketData, - Version: mock.Version, + Value: mockv1.MockPacketData, + Version: mockv1.Version, }, } }