github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/04-channel/keeper/packet_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  
     7  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
     8  	capabilitytypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/types"
     9  
    10  	clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
    11  	connectiontypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types"
    12  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types"
    13  	host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host"
    14  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported"
    15  	ibctmtypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/07-tendermint/types"
    16  	ibctesting "github.com/fibonacci-chain/fbc/libs/ibc-go/testing"
    17  	ibcmock "github.com/fibonacci-chain/fbc/libs/ibc-go/testing/mock"
    18  )
    19  
    20  var (
    21  	disabledTimeoutTimestamp = uint64(0)
    22  	disabledTimeoutHeight    = clienttypes.ZeroHeight()
    23  	timeoutHeight            = clienttypes.NewHeight(0, 100)
    24  
    25  	// for when the testing package cannot be used
    26  	clientIDA  = "clientA"
    27  	clientIDB  = "clientB"
    28  	connIDA    = "connA"
    29  	connIDB    = "connB"
    30  	portID     = "portid"
    31  	channelIDA = "channelidA"
    32  	channelIDB = "channelidB"
    33  )
    34  
    35  // TestSendPacket tests SendPacket from chainA to chainB
    36  func (suite *KeeperTestSuite) TestSendPacket() {
    37  	var (
    38  		path       *ibctesting.Path
    39  		packet     exported.PacketI
    40  		channelCap *capabilitytypes.Capability
    41  	)
    42  
    43  	testCases := []testCase{
    44  		{"success: UNORDERED channel", func() {
    45  			suite.coordinator.Setup(path)
    46  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
    47  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
    48  		}, true},
    49  		{"success: ORDERED channel", func() {
    50  			path.SetChannelOrdered()
    51  			suite.coordinator.Setup(path)
    52  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
    53  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
    54  		}, true},
    55  		{"success with solomachine: UNORDERED channel", func() {
    56  			suite.coordinator.Setup(path)
    57  			// swap client with solo machine
    58  			solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec(), "solomachinesingle", "testing", 1)
    59  			path.EndpointA.ClientID = clienttypes.FormatClientIdentifier(exported.Solomachine, 10)
    60  			path.EndpointA.SetClientState(solomachine.ClientState())
    61  			connection := path.EndpointA.GetConnection()
    62  			connection.ClientId = path.EndpointA.ClientID
    63  			path.EndpointA.SetConnection(connection)
    64  
    65  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
    66  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
    67  		}, true},
    68  		{"success with solomachine: ORDERED channel", func() {
    69  			path.SetChannelOrdered()
    70  			suite.coordinator.Setup(path)
    71  			// swap client with solomachine
    72  			solomachine := ibctesting.NewSolomachine(suite.T(), suite.chainA.Codec(), "solomachinesingle", "testing", 1)
    73  			path.EndpointA.ClientID = clienttypes.FormatClientIdentifier(exported.Solomachine, 10)
    74  			path.EndpointA.SetClientState(solomachine.ClientState())
    75  			connection := path.EndpointA.GetConnection()
    76  			connection.ClientId = path.EndpointA.ClientID
    77  			path.EndpointA.SetConnection(connection)
    78  
    79  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
    80  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
    81  		}, true},
    82  		{"sending packet out of order on UNORDERED channel", func() {
    83  			// setup creates an unordered channel
    84  			suite.coordinator.Setup(path)
    85  			packet = types.NewPacket(ibctesting.MockPacketData, 5, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
    86  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
    87  		}, false},
    88  		{"sending packet out of order on ORDERED channel", func() {
    89  			path.SetChannelOrdered()
    90  			suite.coordinator.Setup(path)
    91  			packet = types.NewPacket(ibctesting.MockPacketData, 5, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
    92  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
    93  		}, false},
    94  		{"packet basic validation failed, empty packet data", func() {
    95  			suite.coordinator.Setup(path)
    96  			packet = types.NewPacket([]byte{}, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
    97  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
    98  		}, false},
    99  		{"channel not found", func() {
   100  			// use wrong channel naming
   101  			suite.coordinator.Setup(path)
   102  			packet = types.NewPacket(ibctesting.MockPacketData, 1, ibctesting.InvalidID, ibctesting.InvalidID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   103  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   104  		}, false},
   105  		{"channel closed", func() {
   106  			suite.coordinator.Setup(path)
   107  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   108  
   109  			err := path.EndpointA.SetChannelClosed()
   110  			suite.Require().NoError(err)
   111  		}, false},
   112  		{"packet dest port ≠ channel counterparty port", func() {
   113  			suite.coordinator.Setup(path)
   114  			// use wrong port for dest
   115  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.InvalidID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   116  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   117  		}, false},
   118  		{"packet dest channel ID ≠ channel counterparty channel ID", func() {
   119  			suite.coordinator.Setup(path)
   120  			// use wrong channel for dest
   121  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp)
   122  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   123  		}, false},
   124  		{"connection not found", func() {
   125  			// pass channel check
   126  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetChannel(
   127  				suite.chainA.GetContext(),
   128  				path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID,
   129  				types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID), []string{connIDA}, path.EndpointA.ChannelConfig.Version),
   130  			)
   131  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   132  			suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   133  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   134  		}, false},
   135  		{"client state not found", func() {
   136  			suite.coordinator.Setup(path)
   137  
   138  			// change connection client ID
   139  			connection := path.EndpointA.GetConnection()
   140  			connection.ClientId = ibctesting.InvalidID
   141  			suite.chainA.App().GetIBCKeeper().ConnectionKeeper.SetConnection(suite.chainA.GetContext(), path.EndpointA.ConnectionID, connection)
   142  
   143  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   144  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   145  		}, false},
   146  		{"client state is frozen", func() {
   147  			suite.coordinator.Setup(path)
   148  
   149  			connection := path.EndpointA.GetConnection()
   150  			clientState := path.EndpointA.GetClientState()
   151  			cs, ok := clientState.(*ibctmtypes.ClientState)
   152  			suite.Require().True(ok)
   153  
   154  			// freeze client
   155  			cs.FrozenHeight = clienttypes.NewHeight(0, 1)
   156  			suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), connection.ClientId, cs)
   157  
   158  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   159  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   160  		}, false},
   161  
   162  		{"timeout height passed", func() {
   163  			suite.coordinator.Setup(path)
   164  			// use client state latest height for timeout
   165  			clientState := path.EndpointA.GetClientState()
   166  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clientState.GetLatestHeight().(clienttypes.Height), disabledTimeoutTimestamp)
   167  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   168  		}, false},
   169  		{"timeout timestamp passed", func() {
   170  			suite.coordinator.Setup(path)
   171  			// use latest time on client state
   172  			clientState := path.EndpointA.GetClientState()
   173  			connection := path.EndpointA.GetConnection()
   174  			timestamp, err := suite.chainA.App().GetIBCKeeper().ConnectionKeeper.GetTimestampAtHeight(suite.chainA.GetContext(), connection, clientState.GetLatestHeight())
   175  			suite.Require().NoError(err)
   176  
   177  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, disabledTimeoutHeight, timestamp)
   178  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   179  		}, false},
   180  		{"next sequence send not found", func() {
   181  			path := ibctesting.NewPath(suite.chainA, suite.chainB)
   182  			suite.coordinator.SetupConnections(path)
   183  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   184  			// manually creating channel prevents next sequence from being set
   185  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetChannel(
   186  				suite.chainA.GetContext(),
   187  				path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID,
   188  				types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID), []string{path.EndpointA.ConnectionID}, path.EndpointA.ChannelConfig.Version),
   189  			)
   190  			suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   191  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   192  		}, false},
   193  		{"next sequence wrong", func() {
   194  			suite.coordinator.Setup(path)
   195  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   196  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetNextSequenceSend(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, 5)
   197  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   198  		}, false},
   199  		{"channel capability not found", func() {
   200  			suite.coordinator.Setup(path)
   201  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   202  			channelCap = capabilitytypes.NewCapability(5)
   203  		}, false},
   204  	}
   205  
   206  	for i, tc := range testCases {
   207  		tc := tc
   208  		suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
   209  			suite.SetupTest() // reset
   210  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   211  
   212  			tc.malleate()
   213  
   214  			err := suite.chainA.App().GetIBCKeeper().ChannelKeeper.SendPacket(suite.chainA.GetContext(), channelCap, packet)
   215  
   216  			if tc.expPass {
   217  				suite.Require().NoError(err)
   218  			} else {
   219  				suite.Require().Error(err)
   220  			}
   221  		})
   222  	}
   223  
   224  }
   225  
   226  // TestRecvPacket test RecvPacket on chainB. Since packet commitment verification will always
   227  // occur last (resource instensive), only tests expected to succeed and packet commitment
   228  // verification tests need to simulate sending a packet from chainA to chainB.
   229  func (suite *KeeperTestSuite) TestRecvPacket() {
   230  	var (
   231  		path       *ibctesting.Path
   232  		packet     exported.PacketI
   233  		channelCap *capabilitytypes.Capability
   234  		expError   *sdkerrors.Error
   235  	)
   236  
   237  	testCases := []testCase{
   238  		{"success: ORDERED channel", func() {
   239  			path.SetChannelOrdered()
   240  			suite.coordinator.Setup(path)
   241  
   242  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   243  			err := path.EndpointA.SendPacket(packet)
   244  			suite.Require().NoError(err)
   245  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   246  		}, true},
   247  		{"success UNORDERED channel", func() {
   248  			// setup uses an UNORDERED channel
   249  			suite.coordinator.Setup(path)
   250  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   251  			err := path.EndpointA.SendPacket(packet)
   252  			suite.Require().NoError(err)
   253  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   254  		}, true},
   255  		{"success with out of order packet: UNORDERED channel", func() {
   256  			// setup uses an UNORDERED channel
   257  			suite.coordinator.Setup(path)
   258  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   259  
   260  			// send 2 packets
   261  			err := path.EndpointA.SendPacket(packet)
   262  			suite.Require().NoError(err)
   263  			// set sequence to 2
   264  			packet = types.NewPacket(ibctesting.MockPacketData, 2, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   265  			err = path.EndpointA.SendPacket(packet)
   266  			suite.Require().NoError(err)
   267  			// attempts to receive packet 2 without receiving packet 1
   268  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   269  		}, true},
   270  		{"packet already relayed ORDERED channel (no-op)", func() {
   271  			expError = types.ErrNoOpMsg
   272  
   273  			path.SetChannelOrdered()
   274  			suite.coordinator.Setup(path)
   275  
   276  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   277  			err := path.EndpointA.SendPacket(packet)
   278  			suite.Require().NoError(err)
   279  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   280  
   281  			err = path.EndpointB.RecvPacket(packet.(types.Packet))
   282  			suite.Require().NoError(err)
   283  		}, false},
   284  		{"packet already relayed UNORDERED channel (no-op)", func() {
   285  			expError = types.ErrNoOpMsg
   286  
   287  			// setup uses an UNORDERED channel
   288  			suite.coordinator.Setup(path)
   289  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   290  			err := path.EndpointA.SendPacket(packet)
   291  			suite.Require().NoError(err)
   292  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   293  
   294  			err = path.EndpointB.RecvPacket(packet.(types.Packet))
   295  			suite.Require().NoError(err)
   296  		}, false},
   297  		{"out of order packet failure with ORDERED channel", func() {
   298  			expError = types.ErrPacketSequenceOutOfOrder
   299  
   300  			path.SetChannelOrdered()
   301  			suite.coordinator.Setup(path)
   302  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   303  
   304  			// send 2 packets
   305  			err := path.EndpointA.SendPacket(packet)
   306  			suite.Require().NoError(err)
   307  			// set sequence to 2
   308  			packet = types.NewPacket(ibctesting.MockPacketData, 2, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   309  			err = path.EndpointA.SendPacket(packet)
   310  			suite.Require().NoError(err)
   311  			// attempts to receive packet 2 without receiving packet 1
   312  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   313  		}, false},
   314  		{"channel not found", func() {
   315  			expError = types.ErrChannelNotFound
   316  
   317  			// use wrong channel naming
   318  			suite.coordinator.Setup(path)
   319  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.InvalidID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp)
   320  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   321  		}, false},
   322  		{"channel not open", func() {
   323  			expError = types.ErrInvalidChannelState
   324  
   325  			suite.coordinator.Setup(path)
   326  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   327  
   328  			err := path.EndpointB.SetChannelClosed()
   329  			suite.Require().NoError(err)
   330  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   331  		}, false},
   332  		{"capability cannot authenticate ORDERED", func() {
   333  			expError = types.ErrInvalidChannelCapability
   334  
   335  			path.SetChannelOrdered()
   336  			suite.coordinator.Setup(path)
   337  
   338  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   339  			err := path.EndpointA.SendPacket(packet)
   340  			suite.Require().NoError(err)
   341  			channelCap = capabilitytypes.NewCapability(3)
   342  		}, false},
   343  		{"packet source port ≠ channel counterparty port", func() {
   344  			expError = types.ErrInvalidPacket
   345  			suite.coordinator.Setup(path)
   346  
   347  			// use wrong port for dest
   348  			packet = types.NewPacket(ibctesting.MockPacketData, 1, ibctesting.InvalidID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   349  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   350  		}, false},
   351  		{"packet source channel ID ≠ channel counterparty channel ID", func() {
   352  			expError = types.ErrInvalidPacket
   353  			suite.coordinator.Setup(path)
   354  
   355  			// use wrong port for dest
   356  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, ibctesting.InvalidID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   357  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   358  		}, false},
   359  		{"connection not found", func() {
   360  			expError = connectiontypes.ErrConnectionNotFound
   361  			suite.coordinator.Setup(path)
   362  
   363  			// pass channel check
   364  			suite.chainB.App().GetIBCKeeper().ChannelKeeper.SetChannel(
   365  				suite.chainB.GetContext(),
   366  				path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID,
   367  				types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID), []string{connIDB}, path.EndpointB.ChannelConfig.Version),
   368  			)
   369  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   370  			suite.chainB.CreateChannelCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   371  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   372  		}, false},
   373  		{"connection not OPEN", func() {
   374  			expError = connectiontypes.ErrInvalidConnectionState
   375  			suite.coordinator.SetupClients(path)
   376  
   377  			// connection on chainB is in INIT
   378  			err := path.EndpointB.ConnOpenInit()
   379  			suite.Require().NoError(err)
   380  
   381  			// pass channel check
   382  			suite.chainB.App().GetIBCKeeper().ChannelKeeper.SetChannel(
   383  				suite.chainB.GetContext(),
   384  				path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID,
   385  				types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID), []string{path.EndpointB.ConnectionID}, path.EndpointB.ChannelConfig.Version),
   386  			)
   387  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   388  			suite.chainB.CreateChannelCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   389  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   390  		}, false},
   391  		{"timeout height passed", func() {
   392  			expError = types.ErrPacketTimeout
   393  			suite.coordinator.Setup(path)
   394  
   395  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), disabledTimeoutTimestamp)
   396  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   397  		}, false},
   398  		{"timeout timestamp passed", func() {
   399  			expError = types.ErrPacketTimeout
   400  			suite.coordinator.Setup(path)
   401  
   402  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, disabledTimeoutHeight, 10) //uint64(suite.chainB.GetContextPointer().BlockTime().UnixNano())
   403  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   404  			suite.coordinator.CommitBlock(suite.chainB)
   405  		}, false},
   406  		{"next receive sequence is not found", func() {
   407  			expError = types.ErrSequenceReceiveNotFound
   408  			suite.coordinator.SetupConnections(path)
   409  
   410  			path.EndpointA.ChannelID = ibctesting.FirstChannelID
   411  			path.EndpointB.ChannelID = ibctesting.FirstChannelID
   412  
   413  			// manually creating channel prevents next recv sequence from being set
   414  			suite.chainB.App().GetIBCKeeper().ChannelKeeper.SetChannel(
   415  				suite.chainB.GetContext(),
   416  				path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID,
   417  				types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID), []string{path.EndpointB.ConnectionID}, path.EndpointB.ChannelConfig.Version),
   418  			)
   419  			suite.coordinator.CommitBlock(suite.chainB)
   420  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   421  
   422  			// manually set packet commitment
   423  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, packet.GetSequence(), types.CommitPacket(suite.chainA.App().AppCodec(), packet))
   424  			suite.coordinator.CommitBlock(suite.chainA)
   425  			suite.chainB.CreateChannelCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   426  			suite.coordinator.CommitBlock(suite.chainA)
   427  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   428  
   429  			path.EndpointA.UpdateClient()
   430  			path.EndpointB.UpdateClient()
   431  		}, false},
   432  		{"receipt already stored", func() {
   433  			expError = types.ErrNoOpMsg
   434  			suite.coordinator.Setup(path)
   435  
   436  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   437  			path.EndpointA.SendPacket(packet)
   438  			suite.chainB.App().GetIBCKeeper().ChannelKeeper.SetPacketReceipt(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, 1)
   439  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   440  		}, false},
   441  		{"validation failed", func() {
   442  			// skip error code check, downstream error code is used from light-client implementations
   443  
   444  			// packet commitment not set resulting in invalid proof
   445  			suite.coordinator.Setup(path)
   446  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   447  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   448  		}, false},
   449  	}
   450  
   451  	for i, tc := range testCases {
   452  		tc := tc
   453  		suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
   454  			suite.SetupTest() // reset
   455  			expError = nil    // must explicitly set for failed cases
   456  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   457  
   458  			tc.malleate()
   459  
   460  			// get proof of packet commitment from chainA
   461  			packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
   462  			proof, proofHeight := path.EndpointA.QueryProof(packetKey)
   463  
   464  			suite.coordinator.CommitBlock(suite.chainB)
   465  			err := suite.chainB.App().GetIBCKeeper().ChannelKeeper.RecvPacket(suite.chainB.GetContext(), channelCap, packet, proof, proofHeight)
   466  
   467  			if tc.expPass {
   468  				suite.Require().NoError(err)
   469  				suite.coordinator.CommitBlock(suite.chainB)
   470  				channelB, _ := suite.chainB.App().GetIBCKeeper().ChannelKeeper.GetChannel(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel())
   471  				suite.coordinator.CommitBlock(suite.chainB)
   472  				nextSeqRecv, found := suite.chainB.App().GetIBCKeeper().ChannelKeeper.GetNextSequenceRecv(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel())
   473  				suite.coordinator.CommitBlock(suite.chainB)
   474  				suite.Require().True(found)
   475  				receipt, receiptStored := suite.chainB.App().GetIBCKeeper().ChannelKeeper.GetPacketReceipt(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   476  				suite.coordinator.CommitBlock(suite.chainB)
   477  
   478  				if channelB.Ordering == types.ORDERED {
   479  					suite.Require().Equal(packet.GetSequence()+1, nextSeqRecv, "sequence not incremented in ordered channel")
   480  					suite.Require().False(receiptStored, "packet receipt stored on ORDERED channel")
   481  				} else {
   482  					suite.Require().Equal(uint64(1), nextSeqRecv, "sequence incremented for UNORDERED channel")
   483  					suite.Require().True(receiptStored, "packet receipt not stored after RecvPacket in UNORDERED channel")
   484  					suite.Require().Equal(string([]byte{byte(1)}), receipt, "packet receipt is not empty string")
   485  				}
   486  			} else {
   487  				suite.Require().Error(err)
   488  
   489  				// only check if expError is set, since not all error codes can be known
   490  				if expError != nil {
   491  					suite.Require().True(errors.Is(err, expError))
   492  				}
   493  			}
   494  		})
   495  	}
   496  
   497  }
   498  
   499  func (suite *KeeperTestSuite) TestWriteAcknowledgement() {
   500  	var (
   501  		path       *ibctesting.Path
   502  		ack        exported.Acknowledgement
   503  		packet     exported.PacketI
   504  		channelCap *capabilitytypes.Capability
   505  	)
   506  
   507  	testCases := []testCase{
   508  		{
   509  			"success",
   510  			func() {
   511  				suite.coordinator.Setup(path)
   512  				packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   513  				ack = ibcmock.MockAcknowledgement
   514  				channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   515  			},
   516  			true,
   517  		},
   518  		{"channel not found", func() {
   519  			// use wrong channel naming
   520  			suite.coordinator.Setup(path)
   521  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.InvalidID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp)
   522  			ack = ibcmock.MockAcknowledgement
   523  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   524  		}, false},
   525  		{"channel not open", func() {
   526  			suite.coordinator.Setup(path)
   527  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   528  			ack = ibcmock.MockAcknowledgement
   529  
   530  			err := path.EndpointB.SetChannelClosed()
   531  			suite.Require().NoError(err)
   532  			channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   533  		}, false},
   534  		{
   535  			"capability authentication failed",
   536  			func() {
   537  				suite.coordinator.Setup(path)
   538  				packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   539  				ack = ibcmock.MockAcknowledgement
   540  				channelCap = capabilitytypes.NewCapability(3)
   541  			},
   542  			false,
   543  		},
   544  		{
   545  			"no-op, already acked",
   546  			func() {
   547  				suite.coordinator.Setup(path)
   548  				packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   549  				ack = ibcmock.MockAcknowledgement
   550  				suite.chainB.GetSimApp().GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ack.Acknowledgement())
   551  				channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   552  			},
   553  			false,
   554  		},
   555  		{
   556  			"empty acknowledgement",
   557  			func() {
   558  				suite.coordinator.Setup(path)
   559  				packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   560  				ack = ibcmock.NewMockEmptyAcknowledgement()
   561  				channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   562  			},
   563  			false,
   564  		},
   565  		{
   566  			"acknowledgement is nil",
   567  			func() {
   568  				suite.coordinator.Setup(path)
   569  				packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   570  				ack = nil
   571  				channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   572  			},
   573  			false,
   574  		},
   575  	}
   576  	for i, tc := range testCases {
   577  		tc := tc
   578  		suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
   579  			suite.SetupTest() // reset
   580  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   581  
   582  			tc.malleate()
   583  
   584  			err := suite.chainB.GetSimApp().GetIBCKeeper().ChannelKeeper.WriteAcknowledgement(suite.chainB.GetContext(), channelCap, packet, ack)
   585  
   586  			if tc.expPass {
   587  				suite.Require().NoError(err)
   588  			} else {
   589  				suite.Require().Error(err)
   590  			}
   591  		})
   592  	}
   593  }
   594  
   595  // TestAcknowledgePacket tests the call AcknowledgePacket on chainA.
   596  func (suite *KeeperTestSuite) TestAcknowledgePacket() {
   597  	var (
   598  		path   *ibctesting.Path
   599  		packet types.Packet
   600  		ack    = ibcmock.MockAcknowledgement
   601  
   602  		channelCap *capabilitytypes.Capability
   603  		expError   *sdkerrors.Error
   604  	)
   605  
   606  	testCases := []testCase{
   607  		{"success on ordered channel", func() {
   608  			path.SetChannelOrdered()
   609  			suite.coordinator.Setup(path)
   610  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   611  			// create packet commitment
   612  			err := path.EndpointA.SendPacket(packet)
   613  			suite.Require().NoError(err)
   614  
   615  			// create packet receipt and acknowledgement
   616  			err = path.EndpointB.RecvPacket(packet)
   617  			suite.Require().NoError(err)
   618  
   619  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   620  		}, true},
   621  		{"success on unordered channel", func() {
   622  			// setup uses an UNORDERED channel
   623  			suite.coordinator.Setup(path)
   624  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   625  
   626  			// create packet commitment
   627  			err := path.EndpointA.SendPacket(packet)
   628  			suite.Require().NoError(err)
   629  
   630  			// create packet receipt and acknowledgement
   631  			err = path.EndpointB.RecvPacket(packet)
   632  			suite.Require().NoError(err)
   633  
   634  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   635  		}, true},
   636  		{"packet already acknowledged ordered channel (no-op)", func() {
   637  			expError = types.ErrNoOpMsg
   638  
   639  			path.SetChannelOrdered()
   640  			suite.coordinator.Setup(path)
   641  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   642  			// create packet commitment
   643  			err := path.EndpointA.SendPacket(packet)
   644  			suite.Require().NoError(err)
   645  
   646  			// create packet receipt and acknowledgement
   647  			err = path.EndpointB.RecvPacket(packet)
   648  			suite.Require().NoError(err)
   649  
   650  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   651  
   652  			err = path.EndpointA.AcknowledgePacket(packet, ack.Acknowledgement())
   653  			suite.Require().NoError(err)
   654  		}, false},
   655  		{"packet already acknowledged unordered channel (no-op)", func() {
   656  			expError = types.ErrNoOpMsg
   657  
   658  			// setup uses an UNORDERED channel
   659  			suite.coordinator.Setup(path)
   660  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   661  
   662  			// create packet commitment
   663  			err := path.EndpointA.SendPacket(packet)
   664  			suite.Require().NoError(err)
   665  
   666  			// create packet receipt and acknowledgement
   667  			err = path.EndpointB.RecvPacket(packet)
   668  			suite.Require().NoError(err)
   669  
   670  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   671  
   672  			err = path.EndpointA.AcknowledgePacket(packet, ack.Acknowledgement())
   673  			suite.Require().NoError(err)
   674  		}, false},
   675  		{"channel not found", func() {
   676  			expError = types.ErrChannelNotFound
   677  
   678  			// use wrong channel naming
   679  			suite.coordinator.Setup(path)
   680  			packet = types.NewPacket(ibctesting.MockPacketData, 1, ibctesting.InvalidID, ibctesting.InvalidID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   681  		}, false},
   682  		{"channel not open", func() {
   683  			expError = types.ErrInvalidChannelState
   684  
   685  			suite.coordinator.Setup(path)
   686  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   687  
   688  			err := path.EndpointA.SetChannelClosed()
   689  			suite.Require().NoError(err)
   690  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   691  		}, false},
   692  		{"capability authentication failed ORDERED", func() {
   693  			expError = types.ErrInvalidChannelCapability
   694  
   695  			path.SetChannelOrdered()
   696  			suite.coordinator.Setup(path)
   697  
   698  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   699  			// create packet commitment
   700  			err := path.EndpointA.SendPacket(packet)
   701  			suite.Require().NoError(err)
   702  
   703  			// create packet receipt and acknowledgement
   704  			err = path.EndpointB.RecvPacket(packet)
   705  			suite.Require().NoError(err)
   706  
   707  			channelCap = capabilitytypes.NewCapability(3)
   708  		}, false},
   709  		{"packet destination port ≠ channel counterparty port", func() {
   710  			expError = types.ErrInvalidPacket
   711  			suite.coordinator.Setup(path)
   712  
   713  			// use wrong port for dest
   714  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.InvalidID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   715  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   716  		}, false},
   717  		{"packet destination channel ID ≠ channel counterparty channel ID", func() {
   718  			expError = types.ErrInvalidPacket
   719  			suite.coordinator.Setup(path)
   720  
   721  			// use wrong channel for dest
   722  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp)
   723  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   724  		}, false},
   725  		{"connection not found", func() {
   726  			expError = connectiontypes.ErrConnectionNotFound
   727  			suite.coordinator.Setup(path)
   728  
   729  			// pass channel check
   730  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetChannel(
   731  				suite.chainA.GetContext(),
   732  				path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID,
   733  				types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID), []string{"connection-1000"}, path.EndpointA.ChannelConfig.Version),
   734  			)
   735  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   736  			suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   737  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   738  		}, false},
   739  		{"connection not OPEN", func() {
   740  			expError = connectiontypes.ErrInvalidConnectionState
   741  			suite.coordinator.SetupClients(path)
   742  			// connection on chainA is in INIT
   743  			err := path.EndpointA.ConnOpenInit()
   744  			suite.Require().NoError(err)
   745  
   746  			// pass channel check
   747  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetChannel(
   748  				suite.chainA.GetContext(),
   749  				path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID,
   750  				types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID), []string{path.EndpointA.ConnectionID}, path.EndpointA.ChannelConfig.Version),
   751  			)
   752  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   753  			suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   754  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   755  		}, false},
   756  		{"packet hasn't been sent", func() {
   757  			expError = types.ErrNoOpMsg
   758  
   759  			// packet commitment never written
   760  			suite.coordinator.Setup(path)
   761  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   762  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   763  		}, false},
   764  		{"packet ack verification failed", func() {
   765  			// skip error code check since error occurs in light-clients
   766  
   767  			// ack never written
   768  			suite.coordinator.Setup(path)
   769  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   770  
   771  			// create packet commitment
   772  			path.EndpointA.SendPacket(packet)
   773  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   774  		}, false},
   775  		{"packet commitment bytes do not match", func() {
   776  			expError = types.ErrInvalidPacket
   777  
   778  			// setup uses an UNORDERED channel
   779  			suite.coordinator.Setup(path)
   780  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   781  
   782  			// create packet commitment
   783  			err := path.EndpointA.SendPacket(packet)
   784  			suite.Require().NoError(err)
   785  
   786  			// create packet receipt and acknowledgement
   787  			err = path.EndpointB.RecvPacket(packet)
   788  			suite.Require().NoError(err)
   789  
   790  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   791  
   792  			packet.Data = []byte("invalid packet commitment")
   793  		}, false},
   794  		{"next ack sequence not found", func() {
   795  			expError = types.ErrSequenceAckNotFound
   796  			suite.coordinator.SetupConnections(path)
   797  
   798  			path.EndpointA.ChannelID = ibctesting.FirstChannelID
   799  			path.EndpointB.ChannelID = ibctesting.FirstChannelID
   800  
   801  			// manually creating channel prevents next sequence acknowledgement from being set
   802  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetChannel(
   803  				suite.chainA.GetContext(),
   804  				path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID,
   805  				types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID), []string{path.EndpointA.ConnectionID}, path.EndpointA.ChannelConfig.Version),
   806  			)
   807  
   808  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   809  			// manually set packet commitment
   810  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetPacketCommitment(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, packet.GetSequence(), types.CommitPacket(suite.chainA.App().AppCodec(), packet))
   811  
   812  			// manually set packet acknowledgement and capability
   813  			suite.chainB.App().GetIBCKeeper().ChannelKeeper.SetPacketAcknowledgement(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, packet.GetSequence(), types.CommitAcknowledgement(ack.Acknowledgement()))
   814  
   815  			suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   816  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   817  
   818  			suite.coordinator.CommitBlock(path.EndpointA.Chain, path.EndpointB.Chain)
   819  
   820  			path.EndpointA.UpdateClient()
   821  			path.EndpointB.UpdateClient()
   822  		}, false},
   823  		{"next ack sequence mismatch ORDERED", func() {
   824  			expError = types.ErrPacketSequenceOutOfOrder
   825  			path.SetChannelOrdered()
   826  			suite.coordinator.Setup(path)
   827  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   828  			// create packet commitment
   829  			err := path.EndpointA.SendPacket(packet)
   830  			suite.Require().NoError(err)
   831  
   832  			// create packet acknowledgement
   833  			err = path.EndpointB.RecvPacket(packet)
   834  			suite.Require().NoError(err)
   835  
   836  			// set next sequence ack wrong
   837  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetNextSequenceAck(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, 10)
   838  			channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   839  		}, false},
   840  	}
   841  
   842  	for i, tc := range testCases {
   843  		tc := tc
   844  		suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
   845  			suite.SetupTest() // reset
   846  			expError = nil    // must explcitly set error for failed cases
   847  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   848  
   849  			tc.malleate()
   850  
   851  			packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   852  			proof, proofHeight := path.EndpointB.QueryProof(packetKey)
   853  
   854  			err := suite.chainA.App().GetIBCKeeper().ChannelKeeper.AcknowledgePacket(suite.chainA.GetContext(), channelCap, packet, ack.Acknowledgement(), proof, proofHeight)
   855  			pc := suite.chainA.App().GetIBCKeeper().ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
   856  
   857  			channelA, _ := suite.chainA.App().GetIBCKeeper().ChannelKeeper.GetChannel(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel())
   858  			sequenceAck, _ := suite.chainA.App().GetIBCKeeper().ChannelKeeper.GetNextSequenceAck(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel())
   859  
   860  			if tc.expPass {
   861  				suite.NoError(err)
   862  				suite.Nil(pc)
   863  
   864  				if channelA.Ordering == types.ORDERED {
   865  					suite.Require().Equal(packet.GetSequence()+1, sequenceAck, "sequence not incremented in ordered channel")
   866  				} else {
   867  					suite.Require().Equal(uint64(1), sequenceAck, "sequence incremented for UNORDERED channel")
   868  				}
   869  			} else {
   870  				suite.Error(err)
   871  				// only check if expError is set, since not all error codes can be known
   872  				if expError != nil {
   873  					suite.Require().True(errors.Is(err, expError))
   874  				}
   875  			}
   876  		})
   877  	}
   878  }