github.com/okex/exchain@v1.8.0/libs/ibc-go/modules/core/04-channel/keeper/timeout_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	sdkerrors "github.com/okex/exchain/libs/cosmos-sdk/types/errors"
     7  	capabilitytypes "github.com/okex/exchain/libs/cosmos-sdk/x/capability/types"
     8  
     9  	// sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    10  	// capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
    11  
    12  	clienttypes "github.com/okex/exchain/libs/ibc-go/modules/core/02-client/types"
    13  	connectiontypes "github.com/okex/exchain/libs/ibc-go/modules/core/03-connection/types"
    14  	"github.com/okex/exchain/libs/ibc-go/modules/core/04-channel/types"
    15  	host "github.com/okex/exchain/libs/ibc-go/modules/core/24-host"
    16  	"github.com/okex/exchain/libs/ibc-go/modules/core/exported"
    17  	ibctesting "github.com/okex/exchain/libs/ibc-go/testing"
    18  )
    19  
    20  // TestTimeoutPacket test the TimeoutPacket call on chainA by ensuring the timeout has passed
    21  // on chainB, but that no ack has been written yet. Test cases expected to reach proof
    22  // verification must specify which proof to use using the ordered bool.
    23  func (suite *KeeperTestSuite) TestTimeoutPacket() {
    24  	var (
    25  		path        *ibctesting.Path
    26  		packet      types.Packet
    27  		nextSeqRecv uint64
    28  		ordered     bool
    29  		expError    *sdkerrors.Error
    30  	)
    31  
    32  	testCases := []testCase{
    33  		{"success: ORDERED", func() {
    34  			ordered = true
    35  			path.SetChannelOrdered()
    36  
    37  			suite.coordinator.Setup(path)
    38  			tmpCtx := suite.chainB.GetContext()
    39  			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()), uint64(tmpCtx.BlockTime().UnixNano()))
    40  			path.EndpointA.SendPacket(packet)
    41  			// need to update chainA's client representing chainB to prove missing ack
    42  			path.EndpointA.UpdateClient()
    43  		}, true},
    44  		{"success: UNORDERED", func() {
    45  			ordered = false
    46  
    47  			suite.coordinator.Setup(path)
    48  			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)
    49  			path.EndpointA.SendPacket(packet)
    50  			// need to update chainA's client representing chainB to prove missing ack
    51  			path.EndpointA.UpdateClient()
    52  		}, true},
    53  		{"packet already timed out: ORDERED", func() {
    54  			expError = types.ErrNoOpMsg
    55  			ordered = true
    56  			path.SetChannelOrdered()
    57  
    58  			suite.coordinator.Setup(path)
    59  			tmpCtx := suite.chainB.GetContext()
    60  			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()), uint64(tmpCtx.BlockTime().UnixNano()))
    61  			path.EndpointA.SendPacket(packet)
    62  			// need to update chainA's client representing chainB to prove missing ack
    63  			path.EndpointA.UpdateClient()
    64  
    65  			err := path.EndpointA.TimeoutPacket(packet)
    66  			suite.Require().NoError(err)
    67  		}, false},
    68  		{"packet already timed out: UNORDERED", func() {
    69  			expError = types.ErrNoOpMsg
    70  			ordered = false
    71  
    72  			suite.coordinator.Setup(path)
    73  			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)
    74  			path.EndpointA.SendPacket(packet)
    75  			// need to update chainA's client representing chainB to prove missing ack
    76  			path.EndpointA.UpdateClient()
    77  
    78  			err := path.EndpointA.TimeoutPacket(packet)
    79  			suite.Require().NoError(err)
    80  		}, false},
    81  		{"channel not found", func() {
    82  			expError = types.ErrChannelNotFound
    83  			// use wrong channel naming
    84  			suite.coordinator.Setup(path)
    85  			packet = types.NewPacket(ibctesting.MockPacketData, 1, ibctesting.InvalidID, ibctesting.InvalidID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
    86  		}, false},
    87  		{"channel not open", func() {
    88  			expError = types.ErrInvalidChannelState
    89  			suite.coordinator.Setup(path)
    90  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, path.EndpointA.GetClientState().GetLatestHeight().Increment().(clienttypes.Height), disabledTimeoutTimestamp)
    91  			err := path.EndpointA.SendPacket(packet)
    92  			suite.Require().NoError(err)
    93  			// need to update chainA's client representing chainB to prove missing ack
    94  			path.EndpointA.UpdateClient()
    95  
    96  			err = path.EndpointA.SetChannelClosed()
    97  			suite.Require().NoError(err)
    98  		}, false},
    99  		{"packet destination port ≠ channel counterparty port", func() {
   100  			expError = types.ErrInvalidPacket
   101  			suite.coordinator.Setup(path)
   102  			// use wrong port for dest
   103  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.InvalidID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   104  		}, false},
   105  		{"packet destination channel ID ≠ channel counterparty channel ID", func() {
   106  			expError = types.ErrInvalidPacket
   107  			suite.coordinator.Setup(path)
   108  			// use wrong channel for dest
   109  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp)
   110  		}, false},
   111  		{"connection not found", func() {
   112  			expError = connectiontypes.ErrConnectionNotFound
   113  			// pass channel check
   114  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetChannel(
   115  				suite.chainA.GetContext(),
   116  				path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID,
   117  				types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID), []string{connIDA}, path.EndpointA.ChannelConfig.Version),
   118  			)
   119  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   120  		}, false},
   121  		{"timeout", func() {
   122  			expError = types.ErrPacketTimeout
   123  			suite.coordinator.Setup(path)
   124  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   125  			path.EndpointA.SendPacket(packet)
   126  			path.EndpointA.UpdateClient()
   127  		}, false},
   128  		{"packet already received ", func() {
   129  			expError = types.ErrPacketReceived
   130  			ordered = true
   131  			path.SetChannelOrdered()
   132  
   133  			nextSeqRecv = 2
   134  
   135  			suite.coordinator.Setup(path)
   136  			tmpCtx := suite.chainB.GetContext()
   137  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, uint64(tmpCtx.BlockTime().UnixNano()))
   138  			path.EndpointA.SendPacket(packet)
   139  			path.EndpointA.UpdateClient()
   140  		}, false},
   141  		{"packet hasn't been sent", func() {
   142  			expError = types.ErrNoOpMsg
   143  			ordered = true
   144  			path.SetChannelOrdered()
   145  
   146  			suite.coordinator.Setup(path)
   147  			tmpCtx := suite.chainB.GetContext()
   148  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, uint64(tmpCtx.BlockTime().UnixNano()))
   149  			path.EndpointA.UpdateClient()
   150  		}, false},
   151  		{"next seq receive verification failed", func() {
   152  			// skip error check, error occurs in light-clients
   153  
   154  			// set ordered to false resulting in wrong proof provided
   155  			ordered = false
   156  
   157  			path.SetChannelOrdered()
   158  
   159  			suite.coordinator.Setup(path)
   160  			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)
   161  			path.EndpointA.SendPacket(packet)
   162  			path.EndpointA.UpdateClient()
   163  		}, false},
   164  		{"packet ack verification failed", func() {
   165  			// skip error check, error occurs in light-clients
   166  
   167  			// set ordered to true resulting in wrong proof provided
   168  			ordered = true
   169  
   170  			suite.coordinator.Setup(path)
   171  			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)
   172  			path.EndpointA.SendPacket(packet)
   173  			path.EndpointA.UpdateClient()
   174  		}, false},
   175  	}
   176  
   177  	for i, tc := range testCases {
   178  		tc := tc
   179  		suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
   180  			var (
   181  				proof       []byte
   182  				proofHeight exported.Height
   183  			)
   184  
   185  			suite.SetupTest() // reset
   186  			expError = nil    // must be expliticly changed by failed cases
   187  			nextSeqRecv = 1   // must be explicitly changed
   188  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   189  
   190  			tc.malleate()
   191  
   192  			orderedPacketKey := host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   193  			unorderedPacketKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   194  
   195  			if path.EndpointB.ConnectionID != "" {
   196  				if ordered {
   197  					proof, proofHeight = path.EndpointB.QueryProof(orderedPacketKey)
   198  				} else {
   199  					proof, proofHeight = path.EndpointB.QueryProof(unorderedPacketKey)
   200  				}
   201  			}
   202  
   203  			err := suite.chainA.App().GetIBCKeeper().ChannelKeeper.TimeoutPacket(suite.chainA.GetContext(), packet, proof, proofHeight, nextSeqRecv)
   204  
   205  			if tc.expPass {
   206  				suite.Require().NoError(err)
   207  			} else {
   208  				suite.Require().Error(err)
   209  				// only check if expError is set, since not all error codes can be known
   210  				if expError != nil {
   211  					suite.Require().True(errors.Is(err, expError))
   212  				}
   213  
   214  			}
   215  		})
   216  	}
   217  }
   218  
   219  // TestTimeoutExectued verifies that packet commitments are deleted on chainA after the
   220  // channel capabilities are verified.
   221  func (suite *KeeperTestSuite) TestTimeoutExecuted() {
   222  	var (
   223  		path    *ibctesting.Path
   224  		packet  types.Packet
   225  		chanCap *capabilitytypes.Capability
   226  	)
   227  	testCases := []testCase{
   228  		{"success ORDERED", func() {
   229  			path.SetChannelOrdered()
   230  			suite.coordinator.Setup(path)
   231  
   232  			tmpCtx := suite.chainB.GetContext()
   233  			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()), uint64(tmpCtx.BlockTime().UnixNano()))
   234  			path.EndpointA.SendPacket(packet)
   235  
   236  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   237  		}, true},
   238  		{"channel not found", func() {
   239  			// use wrong channel naming
   240  			suite.coordinator.Setup(path)
   241  			packet = types.NewPacket(ibctesting.MockPacketData, 1, ibctesting.InvalidID, ibctesting.InvalidID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   242  		}, false},
   243  		{"incorrect capability ORDERED", func() {
   244  			path.SetChannelOrdered()
   245  			suite.coordinator.Setup(path)
   246  			tmpCtx := suite.chainB.GetContext()
   247  			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()), uint64(tmpCtx.BlockTime().UnixNano()))
   248  			path.EndpointA.SendPacket(packet)
   249  
   250  			chanCap = capabilitytypes.NewCapability(100)
   251  		}, false},
   252  	}
   253  
   254  	for i, tc := range testCases {
   255  		tc := tc
   256  		suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
   257  			suite.SetupTest() // reset
   258  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   259  
   260  			tc.malleate()
   261  
   262  			err := suite.chainA.App().GetIBCKeeper().ChannelKeeper.TimeoutExecuted(suite.chainA.GetContext(), chanCap, packet)
   263  			pc := suite.chainA.App().GetIBCKeeper().ChannelKeeper.GetPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
   264  
   265  			if tc.expPass {
   266  				suite.NoError(err)
   267  				suite.Nil(pc)
   268  			} else {
   269  				suite.Error(err)
   270  			}
   271  		})
   272  	}
   273  }
   274  
   275  // TestTimeoutOnClose tests the call TimeoutOnClose on chainA by closing the corresponding
   276  // channel on chainB after the packet commitment has been created.
   277  func (suite *KeeperTestSuite) TestTimeoutOnClose() {
   278  	var (
   279  		path        *ibctesting.Path
   280  		packet      types.Packet
   281  		chanCap     *capabilitytypes.Capability
   282  		nextSeqRecv uint64
   283  		ordered     bool
   284  	)
   285  
   286  	testCases := []testCase{
   287  		{"success: ORDERED", func() {
   288  			ordered = true
   289  			path.SetChannelOrdered()
   290  			suite.coordinator.Setup(path)
   291  
   292  			tmpCtx := suite.chainB.GetContext()
   293  			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()), uint64(tmpCtx.BlockTime().UnixNano()))
   294  			path.EndpointA.SendPacket(packet)
   295  			path.EndpointB.SetChannelClosed()
   296  			// need to update chainA's client representing chainB to prove missing ack
   297  			path.EndpointA.UpdateClient()
   298  
   299  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   300  		}, true},
   301  		{"success: UNORDERED", func() {
   302  			ordered = false
   303  			suite.coordinator.Setup(path)
   304  			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)
   305  			path.EndpointA.SendPacket(packet)
   306  			path.EndpointB.SetChannelClosed()
   307  			// need to update chainA's client representing chainB to prove missing ack
   308  			path.EndpointA.UpdateClient()
   309  
   310  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   311  		}, true},
   312  		{"channel not found", func() {
   313  			// use wrong channel naming
   314  			suite.coordinator.Setup(path)
   315  			packet = types.NewPacket(ibctesting.MockPacketData, 1, ibctesting.InvalidID, ibctesting.InvalidID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   316  		}, false},
   317  		{"packet dest port ≠ channel counterparty port", func() {
   318  			suite.coordinator.Setup(path)
   319  			// use wrong port for dest
   320  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.InvalidID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   321  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   322  		}, false},
   323  		{"packet dest channel ID ≠ channel counterparty channel ID", func() {
   324  			suite.coordinator.Setup(path)
   325  			// use wrong channel for dest
   326  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, ibctesting.InvalidID, timeoutHeight, disabledTimeoutTimestamp)
   327  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   328  		}, false},
   329  		{"connection not found", func() {
   330  			// pass channel check
   331  			suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetChannel(
   332  				suite.chainA.GetContext(),
   333  				path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID,
   334  				types.NewChannel(types.OPEN, types.ORDERED, types.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID), []string{connIDA}, path.EndpointA.ChannelConfig.Version),
   335  			)
   336  			packet = types.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, disabledTimeoutTimestamp)
   337  
   338  			// create chancap
   339  			suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   340  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   341  		}, false},
   342  		{"packet hasn't been sent ORDERED", func() {
   343  			path.SetChannelOrdered()
   344  			suite.coordinator.Setup(path)
   345  
   346  			tmpCtx := suite.chainB.GetContext()
   347  			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()), uint64(tmpCtx.BlockTime().UnixNano()))
   348  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   349  		}, false},
   350  		{"packet already received ORDERED", func() {
   351  			path.SetChannelOrdered()
   352  			nextSeqRecv = 2
   353  			ordered = true
   354  			suite.coordinator.Setup(path)
   355  
   356  			tmpCtx := suite.chainB.GetContext()
   357  			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()), uint64(tmpCtx.BlockTime().UnixNano()))
   358  			path.EndpointA.SendPacket(packet)
   359  			path.EndpointB.SetChannelClosed()
   360  			// need to update chainA's client representing chainB to prove missing ack
   361  			path.EndpointA.UpdateClient()
   362  
   363  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   364  		}, false},
   365  		{"channel verification failed ORDERED", func() {
   366  			ordered = true
   367  			path.SetChannelOrdered()
   368  			suite.coordinator.Setup(path)
   369  			tmpCtx := suite.chainB.GetContext()
   370  			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()), uint64(tmpCtx.BlockTime().UnixNano()))
   371  			path.EndpointA.SendPacket(packet)
   372  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   373  		}, false},
   374  		{"next seq receive verification failed ORDERED", func() {
   375  			// set ordered to false providing the wrong proof for ORDERED case
   376  			ordered = false
   377  
   378  			path.SetChannelOrdered()
   379  			suite.coordinator.Setup(path)
   380  			tmpCtx := suite.chainB.GetContext()
   381  			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()), uint64(tmpCtx.BlockTime().UnixNano()))
   382  			path.EndpointA.SendPacket(packet)
   383  			path.EndpointB.SetChannelClosed()
   384  			path.EndpointA.UpdateClient()
   385  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   386  		}, false},
   387  		{"packet ack verification failed", func() {
   388  			// set ordered to true providing the wrong proof for UNORDERED case
   389  			ordered = true
   390  			suite.coordinator.Setup(path)
   391  			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)
   392  			path.EndpointA.SendPacket(packet)
   393  			path.EndpointB.SetChannelClosed()
   394  			path.EndpointA.UpdateClient()
   395  			chanCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)
   396  		}, false},
   397  		{"channel capability not found ORDERED", func() {
   398  			ordered = true
   399  			path.SetChannelOrdered()
   400  			suite.coordinator.Setup(path)
   401  
   402  			tmpCtx := suite.chainB.GetContext()
   403  			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()), uint64(tmpCtx.BlockTime().UnixNano()))
   404  			path.EndpointA.SendPacket(packet)
   405  			path.EndpointB.SetChannelClosed()
   406  			// need to update chainA's client representing chainB to prove missing ack
   407  			path.EndpointA.UpdateClient()
   408  
   409  			chanCap = capabilitytypes.NewCapability(100)
   410  		}, false},
   411  	}
   412  
   413  	for i, tc := range testCases {
   414  		tc := tc
   415  		suite.Run(fmt.Sprintf("Case %s, %d/%d tests", tc.msg, i, len(testCases)), func() {
   416  			var proof []byte
   417  
   418  			suite.SetupTest() // reset
   419  			nextSeqRecv = 1   // must be explicitly changed
   420  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   421  
   422  			tc.malleate()
   423  
   424  			channelKey := host.ChannelKey(packet.GetDestPort(), packet.GetDestChannel())
   425  			unorderedPacketKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   426  			orderedPacketKey := host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   427  
   428  			proofClosed, proofHeight := suite.chainB.QueryProof(channelKey)
   429  
   430  			if ordered {
   431  				proof, _ = suite.chainB.QueryProof(orderedPacketKey)
   432  			} else {
   433  				proof, _ = suite.chainB.QueryProof(unorderedPacketKey)
   434  			}
   435  
   436  			err := suite.chainA.App().GetIBCKeeper().ChannelKeeper.TimeoutOnClose(suite.chainA.GetContext(), chanCap, packet, proof, proofClosed, proofHeight, nextSeqRecv)
   437  
   438  			if tc.expPass {
   439  				suite.Require().NoError(err)
   440  			} else {
   441  				suite.Require().Error(err)
   442  			}
   443  		})
   444  	}
   445  
   446  }