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

     1  package keeper_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/fibonacci-chain/fbc/libs/tendermint/types"
     7  
     8  	"github.com/stretchr/testify/suite"
     9  
    10  	// sdk "github.com/cosmos/cosmos-sdk/types"
    11  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    12  
    13  	clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
    14  	channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types"
    15  	commitmenttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/23-commitment/types"
    16  	host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host"
    17  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported"
    18  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/keeper"
    19  	ibctmtypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/07-tendermint/types"
    20  	ibctesting "github.com/fibonacci-chain/fbc/libs/ibc-go/testing"
    21  	ibcmock "github.com/fibonacci-chain/fbc/libs/ibc-go/testing/mock"
    22  	types2 "github.com/fibonacci-chain/fbc/libs/ibc-go/testing/simapp/types"
    23  )
    24  
    25  const height = 10
    26  
    27  var (
    28  	timeoutHeight = clienttypes.NewHeight(0, 10000)
    29  	maxSequence   = uint64(10)
    30  )
    31  
    32  type KeeperTestSuite struct {
    33  	suite.Suite
    34  
    35  	coordinator *ibctesting.Coordinator
    36  
    37  	chainA ibctesting.TestChainI
    38  	chainB ibctesting.TestChainI
    39  }
    40  
    41  // SetupTest creates a coordinator with 2 test chains.
    42  func (suite *KeeperTestSuite) SetupTest() {
    43  	types.UnittestOnlySetMilestoneVenus1Height(-1)
    44  	suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2)
    45  
    46  	suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0))
    47  	suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1))
    48  
    49  	// TODO: remove
    50  	// commit some blocks so that QueryProof returns valid proof (cannot return valid query if height <= 1)
    51  	suite.coordinator.CommitNBlocks(suite.chainA, 2)
    52  	suite.coordinator.CommitNBlocks(suite.chainB, 2)
    53  
    54  }
    55  
    56  func TestIBCTestSuite(t *testing.T) {
    57  	suite.Run(t, new(KeeperTestSuite))
    58  }
    59  
    60  // tests the IBC handler receiving a packet on ordered and unordered channels.
    61  // It verifies that the storing of an acknowledgement on success occurs. It
    62  // tests high level properties like ordering and basic sanity checks. More
    63  // rigorous testing of 'RecvPacket' can be found in the
    64  // 04-channel/keeper/packet_test.go.
    65  func (suite *KeeperTestSuite) TestHandleRecvPacket() {
    66  	var (
    67  		packet channeltypes.Packet
    68  		path   *ibctesting.Path
    69  		async  bool // indicate no ack written
    70  	)
    71  
    72  	testCases := []struct {
    73  		name      string
    74  		malleate  func()
    75  		expPass   bool
    76  		expRevert bool
    77  	}{
    78  		{"success: ORDERED", func() {
    79  			path.SetChannelOrdered()
    80  			suite.coordinator.Setup(path)
    81  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
    82  
    83  			err := path.EndpointA.SendPacket(packet)
    84  			suite.Require().NoError(err)
    85  		}, true, false},
    86  		{"success: UNORDERED", func() {
    87  			suite.coordinator.Setup(path)
    88  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
    89  
    90  			err := path.EndpointA.SendPacket(packet)
    91  			suite.Require().NoError(err)
    92  		}, true, false},
    93  		{"success: UNORDERED out of order packet", func() {
    94  			// setup uses an UNORDERED channel
    95  			suite.coordinator.Setup(path)
    96  
    97  			// attempts to receive packet with sequence 10 without receiving packet with sequence 1
    98  			for i := uint64(1); i < 10; i++ {
    99  				packet = channeltypes.NewPacket(ibctesting.MockPacketData, i, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   100  
   101  				err := path.EndpointA.SendPacket(packet)
   102  				suite.Require().NoError(err)
   103  			}
   104  		}, true, false},
   105  		{"success: OnRecvPacket callback returns revert=true", func() {
   106  			suite.coordinator.Setup(path)
   107  			packet = channeltypes.NewPacket(ibctesting.MockFailPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   108  
   109  			err := path.EndpointA.SendPacket(packet)
   110  			suite.Require().NoError(err)
   111  		}, true, true},
   112  		{"success: ORDERED - async acknowledgement", func() {
   113  			path.SetChannelOrdered()
   114  			suite.coordinator.Setup(path)
   115  			async = true
   116  			packet = channeltypes.NewPacket(ibcmock.MockAsyncPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   117  
   118  			err := path.EndpointA.SendPacket(packet)
   119  			suite.Require().NoError(err)
   120  		}, true, false},
   121  		{"success: UNORDERED - async acknowledgement", func() {
   122  			suite.coordinator.Setup(path)
   123  			async = true
   124  			packet = channeltypes.NewPacket(ibcmock.MockAsyncPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   125  
   126  			err := path.EndpointA.SendPacket(packet)
   127  			suite.Require().NoError(err)
   128  		}, true, false},
   129  		{"failure: ORDERED out of order packet", func() {
   130  			path.SetChannelOrdered()
   131  			suite.coordinator.Setup(path)
   132  
   133  			// attempts to receive packet with sequence 10 without receiving packet with sequence 1
   134  			for i := uint64(1); i < 10; i++ {
   135  				packet = channeltypes.NewPacket(ibctesting.MockPacketData, i, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   136  
   137  				err := path.EndpointA.SendPacket(packet)
   138  				suite.Require().NoError(err)
   139  			}
   140  		}, false, false},
   141  		{"channel does not exist", func() {
   142  			// any non-nil value of packet is valid
   143  			suite.Require().NotNil(packet)
   144  		}, false, false},
   145  		{"packet not sent", func() {
   146  			suite.coordinator.Setup(path)
   147  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   148  		}, false, false},
   149  		{"successful no-op: ORDERED - packet already received (replay)", func() {
   150  			// mock will panic if application callback is called twice on the same packet
   151  			path.SetChannelOrdered()
   152  			suite.coordinator.Setup(path)
   153  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   154  
   155  			err := path.EndpointA.SendPacket(packet)
   156  			suite.Require().NoError(err)
   157  
   158  			err = path.EndpointB.RecvPacket(packet)
   159  			suite.Require().NoError(err)
   160  		}, true, false},
   161  		{"successful no-op: UNORDERED - packet already received (replay)", func() {
   162  			// mock will panic if application callback is called twice on the same packet
   163  			suite.coordinator.Setup(path)
   164  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   165  
   166  			err := path.EndpointA.SendPacket(packet)
   167  			suite.Require().NoError(err)
   168  
   169  			err = path.EndpointB.RecvPacket(packet)
   170  			suite.Require().NoError(err)
   171  		}, true, false},
   172  	}
   173  
   174  	for _, tc := range testCases {
   175  		tc := tc
   176  
   177  		suite.Run(tc.name, func() {
   178  			suite.SetupTest() // reset
   179  			async = false     // reset
   180  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   181  
   182  			tc.malleate()
   183  
   184  			var (
   185  				proof       []byte
   186  				proofHeight clienttypes.Height
   187  			)
   188  
   189  			// get proof of packet commitment from chainA
   190  			packetKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
   191  			if path.EndpointA.ChannelID != "" {
   192  				proof, proofHeight = path.EndpointA.QueryProof(packetKey)
   193  			}
   194  
   195  			msg := channeltypes.NewMsgRecvPacket(packet, proof, proofHeight, suite.chainB.SenderAccount().GetAddress().String())
   196  
   197  			_, err := keeper.Keeper.RecvPacket(*suite.chainB.GetSimApp().GetIBCKeeper(), sdk.WrapSDKContext(suite.chainB.GetContext()), msg)
   198  
   199  			if tc.expPass {
   200  				suite.Require().NoError(err)
   201  
   202  				// replay should not fail since it will be treated as a no-op
   203  				_, err := keeper.Keeper.RecvPacket(*suite.chainB.GetSimApp().GetIBCKeeper(), sdk.WrapSDKContext(suite.chainB.GetContext()), msg)
   204  				suite.Require().NoError(err)
   205  
   206  				// check that callback state was handled correctly
   207  				_, exists := suite.chainB.GetSimApp().ScopedIBCMockKeeper.GetCapability(suite.chainB.GetContext(), ibcmock.GetMockRecvCanaryCapabilityName(packet))
   208  				if tc.expRevert {
   209  					suite.Require().False(exists, "capability exists in store even after callback reverted")
   210  				} else {
   211  					suite.Require().True(exists, "callback state not persisted when revert is false")
   212  				}
   213  
   214  				// verify if ack was written
   215  				ack, found := suite.chainB.GetSimApp().GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(suite.chainB.GetContext(), packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   216  
   217  				if async {
   218  					suite.Require().Nil(ack)
   219  					suite.Require().False(found)
   220  
   221  				} else {
   222  					suite.Require().NotNil(ack)
   223  					suite.Require().True(found)
   224  				}
   225  			} else {
   226  				suite.Require().Error(err)
   227  			}
   228  		})
   229  	}
   230  }
   231  
   232  // tests the IBC handler acknowledgement of a packet on ordered and unordered
   233  // channels. It verifies that the deletion of packet commitments from state
   234  // occurs. It test high level properties like ordering and basic sanity
   235  // checks. More rigorous testing of 'AcknowledgePacket'
   236  // can be found in the 04-channel/keeper/packet_test.go.
   237  func (suite *KeeperTestSuite) TestHandleAcknowledgePacket() {
   238  	var (
   239  		packet channeltypes.Packet
   240  		path   *ibctesting.Path
   241  	)
   242  
   243  	testCases := []struct {
   244  		name     string
   245  		malleate func()
   246  		expPass  bool
   247  	}{
   248  		{"success: ORDERED", func() {
   249  			path.SetChannelOrdered()
   250  			suite.coordinator.Setup(path)
   251  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   252  
   253  			err := path.EndpointA.SendPacket(packet)
   254  			suite.Require().NoError(err)
   255  
   256  			err = path.EndpointB.RecvPacket(packet)
   257  			suite.Require().NoError(err)
   258  		}, true},
   259  		{"success: UNORDERED", func() {
   260  			suite.coordinator.Setup(path)
   261  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   262  
   263  			err := path.EndpointA.SendPacket(packet)
   264  			suite.Require().NoError(err)
   265  
   266  			err = path.EndpointB.RecvPacket(packet)
   267  			suite.Require().NoError(err)
   268  		}, true},
   269  		{"success: UNORDERED acknowledge out of order packet", func() {
   270  			// setup uses an UNORDERED channel
   271  			suite.coordinator.Setup(path)
   272  
   273  			// attempts to acknowledge ack with sequence 10 without acknowledging ack with sequence 1 (removing packet commitment)
   274  			for i := uint64(1); i < 10; i++ {
   275  				packet = channeltypes.NewPacket(ibctesting.MockPacketData, i, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   276  
   277  				err := path.EndpointA.SendPacket(packet)
   278  				suite.Require().NoError(err)
   279  
   280  				err = path.EndpointB.RecvPacket(packet)
   281  				suite.Require().NoError(err)
   282  			}
   283  		}, true},
   284  		{"failure: ORDERED acknowledge out of order packet", func() {
   285  			path.SetChannelOrdered()
   286  			suite.coordinator.Setup(path)
   287  
   288  			// attempts to acknowledge ack with sequence 10 without acknowledging ack with sequence 1 (removing packet commitment
   289  			for i := uint64(1); i < 10; i++ {
   290  				packet = channeltypes.NewPacket(ibctesting.MockPacketData, i, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   291  
   292  				err := path.EndpointA.SendPacket(packet)
   293  				suite.Require().NoError(err)
   294  
   295  				err = path.EndpointB.RecvPacket(packet)
   296  				suite.Require().NoError(err)
   297  			}
   298  		}, false},
   299  		{"channel does not exist", func() {
   300  			// any non-nil value of packet is valid
   301  			suite.Require().NotNil(packet)
   302  		}, false},
   303  		{"packet not received", func() {
   304  			suite.coordinator.Setup(path)
   305  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   306  
   307  			err := path.EndpointA.SendPacket(packet)
   308  			suite.Require().NoError(err)
   309  		}, false},
   310  		{"successful no-op: ORDERED - packet already acknowledged (replay)", func() {
   311  			suite.coordinator.Setup(path)
   312  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   313  
   314  			err := path.EndpointA.SendPacket(packet)
   315  			suite.Require().NoError(err)
   316  
   317  			err = path.EndpointB.RecvPacket(packet)
   318  			suite.Require().NoError(err)
   319  
   320  			err = path.EndpointA.AcknowledgePacket(packet, ibctesting.MockAcknowledgement)
   321  			suite.Require().NoError(err)
   322  		}, true},
   323  		{"successful no-op: UNORDERED - packet already acknowledged (replay)", func() {
   324  			suite.coordinator.Setup(path)
   325  
   326  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   327  
   328  			err := path.EndpointA.SendPacket(packet)
   329  			suite.Require().NoError(err)
   330  
   331  			err = path.EndpointB.RecvPacket(packet)
   332  			suite.Require().NoError(err)
   333  
   334  			err = path.EndpointA.AcknowledgePacket(packet, ibctesting.MockAcknowledgement)
   335  			suite.Require().NoError(err)
   336  		}, true},
   337  	}
   338  
   339  	for _, tc := range testCases {
   340  		tc := tc
   341  
   342  		suite.Run(tc.name, func() {
   343  			suite.SetupTest() // reset
   344  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   345  
   346  			tc.malleate()
   347  
   348  			var (
   349  				proof       []byte
   350  				proofHeight clienttypes.Height
   351  			)
   352  			packetKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   353  			if path.EndpointB.ChannelID != "" {
   354  				proof, proofHeight = path.EndpointB.QueryProof(packetKey)
   355  			}
   356  
   357  			msg := channeltypes.NewMsgAcknowledgement(packet, ibcmock.MockAcknowledgement.Acknowledgement(), proof, proofHeight, suite.chainA.SenderAccount().GetAddress().String())
   358  
   359  			_, err := keeper.Keeper.Acknowledgement(*suite.chainA.App().GetIBCKeeper(), sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
   360  
   361  			if tc.expPass {
   362  				suite.Require().NoError(err)
   363  
   364  				// verify packet commitment was deleted on source chain
   365  				has := suite.chainA.App().GetIBCKeeper().ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
   366  				suite.Require().False(has)
   367  
   368  				// replay should not error as it is treated as a no-op
   369  				_, err := keeper.Keeper.Acknowledgement(*suite.chainA.App().GetIBCKeeper(), sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
   370  				suite.Require().NoError(err)
   371  			} else {
   372  				suite.Require().Error(err)
   373  			}
   374  		})
   375  	}
   376  }
   377  
   378  // tests the IBC handler timing out a packet on ordered and unordered channels.
   379  // It verifies that the deletion of a packet commitment occurs. It tests
   380  // high level properties like ordering and basic sanity checks. More
   381  // rigorous testing of 'TimeoutPacket' and 'TimeoutExecuted' can be found in
   382  // the 04-channel/keeper/timeout_test.go.
   383  func (suite *KeeperTestSuite) TestHandleTimeoutPacket() {
   384  	var (
   385  		packet    channeltypes.Packet
   386  		packetKey []byte
   387  		path      *ibctesting.Path
   388  	)
   389  	//tmpCtx := suite.chainB.GetContext()
   390  
   391  	testCases := []struct {
   392  		name     string
   393  		malleate func()
   394  		expPass  bool
   395  	}{
   396  		{"success: ORDERED", func() {
   397  			path.SetChannelOrdered()
   398  			suite.coordinator.Setup(path)
   399  			tmpCtx := suite.chainB.GetContext()
   400  			packet = channeltypes.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()))
   401  
   402  			// create packet commitment
   403  			err := path.EndpointA.SendPacket(packet)
   404  			suite.Require().NoError(err)
   405  
   406  			// need to update chainA client to prove missing ack
   407  			path.EndpointA.UpdateClient()
   408  
   409  			packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   410  		}, true},
   411  		{"success: UNORDERED", func() {
   412  			suite.coordinator.Setup(path)
   413  			tmpCtx := suite.chainB.GetContext()
   414  			packet = channeltypes.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()))
   415  
   416  			// create packet commitment
   417  			err := path.EndpointA.SendPacket(packet)
   418  			suite.Require().NoError(err)
   419  
   420  			// need to update chainA client to prove missing ack
   421  			path.EndpointA.UpdateClient()
   422  
   423  			packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   424  		}, true},
   425  		{"success: UNORDERED timeout out of order packet", func() {
   426  			// setup uses an UNORDERED channel
   427  			suite.coordinator.Setup(path)
   428  
   429  			// attempts to timeout the last packet sent without timing out the first packet
   430  			// packet sequences begin at 1
   431  			for i := uint64(1); i < maxSequence; i++ {
   432  				packet = channeltypes.NewPacket(ibctesting.MockPacketData, i, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), 0)
   433  
   434  				// create packet commitment
   435  				err := path.EndpointA.SendPacket(packet)
   436  				suite.Require().NoError(err)
   437  			}
   438  
   439  			path.EndpointA.UpdateClient()
   440  			packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   441  		}, true},
   442  		{"success: ORDERED timeout out of order packet", func() {
   443  			path.SetChannelOrdered()
   444  			suite.coordinator.Setup(path)
   445  
   446  			// attempts to timeout the last packet sent without timing out the first packet
   447  			// packet sequences begin at 1
   448  			for i := uint64(1); i < maxSequence; i++ {
   449  				packet = channeltypes.NewPacket(ibctesting.MockPacketData, i, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.GetSelfHeight(suite.chainB.GetContext()), 0)
   450  
   451  				// create packet commitment
   452  				err := path.EndpointA.SendPacket(packet)
   453  				suite.Require().NoError(err)
   454  			}
   455  
   456  			path.EndpointA.UpdateClient()
   457  			packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   458  
   459  		}, true},
   460  		{"channel does not exist", func() {
   461  			// any non-nil value of packet is valid
   462  			suite.Require().NotNil(packet)
   463  
   464  			packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   465  		}, false},
   466  		{"successful no-op: UNORDERED - packet not sent", func() {
   467  			suite.coordinator.Setup(path)
   468  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 1), 0)
   469  			packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   470  		}, true},
   471  	}
   472  
   473  	for _, tc := range testCases {
   474  		tc := tc
   475  
   476  		suite.Run(tc.name, func() {
   477  			suite.SetupTest() // reset
   478  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   479  
   480  			tc.malleate()
   481  
   482  			var (
   483  				proof       []byte
   484  				proofHeight clienttypes.Height
   485  			)
   486  			if path.EndpointB.ChannelID != "" {
   487  				proof, proofHeight = path.EndpointB.QueryProof(packetKey)
   488  			}
   489  
   490  			msg := channeltypes.NewMsgTimeout(packet, 1, proof, proofHeight, suite.chainA.SenderAccount().GetAddress().String())
   491  
   492  			_, err := keeper.Keeper.Timeout(*suite.chainA.App().GetIBCKeeper(), sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
   493  
   494  			if tc.expPass {
   495  				suite.Require().NoError(err)
   496  
   497  				// replay should not return an error as it is treated as a no-op
   498  				_, err := keeper.Keeper.Timeout(*suite.chainA.App().GetIBCKeeper(), sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
   499  				suite.Require().NoError(err)
   500  
   501  				// verify packet commitment was deleted on source chain
   502  				has := suite.chainA.App().GetIBCKeeper().ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
   503  				suite.Require().False(has)
   504  
   505  			} else {
   506  				suite.Require().Error(err)
   507  			}
   508  		})
   509  	}
   510  }
   511  
   512  // tests the IBC handler timing out a packet via channel closure on ordered
   513  // and unordered channels. It verifies that the deletion of a packet
   514  // commitment occurs. It tests high level properties like ordering and basic
   515  // sanity checks. More rigorous testing of 'TimeoutOnClose' and
   516  // 'TimeoutExecuted' can be found in the 04-channel/keeper/timeout_test.go.
   517  func (suite *KeeperTestSuite) TestHandleTimeoutOnClosePacket() {
   518  	var (
   519  		packet    channeltypes.Packet
   520  		packetKey []byte
   521  		path      *ibctesting.Path
   522  	)
   523  
   524  	testCases := []struct {
   525  		name     string
   526  		malleate func()
   527  		expPass  bool
   528  	}{
   529  		{"success: ORDERED", func() {
   530  			path.SetChannelOrdered()
   531  			suite.coordinator.Setup(path)
   532  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   533  
   534  			// create packet commitment
   535  			err := path.EndpointA.SendPacket(packet)
   536  			suite.Require().NoError(err)
   537  
   538  			// need to update chainA client to prove missing ack
   539  			path.EndpointA.UpdateClient()
   540  
   541  			packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   542  
   543  			// close counterparty channel
   544  			path.EndpointB.SetChannelClosed()
   545  		}, true},
   546  		{"success: UNORDERED", func() {
   547  			suite.coordinator.Setup(path)
   548  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   549  
   550  			// create packet commitment
   551  			err := path.EndpointA.SendPacket(packet)
   552  			suite.Require().NoError(err)
   553  
   554  			// need to update chainA client to prove missing ack
   555  			path.EndpointA.UpdateClient()
   556  
   557  			packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   558  
   559  			// close counterparty channel
   560  			path.EndpointB.SetChannelClosed()
   561  		}, true},
   562  		{"success: UNORDERED timeout out of order packet", func() {
   563  			// setup uses an UNORDERED channel
   564  			suite.coordinator.Setup(path)
   565  
   566  			// attempts to timeout the last packet sent without timing out the first packet
   567  			// packet sequences begin at 1
   568  			for i := uint64(1); i < maxSequence; i++ {
   569  				packet = channeltypes.NewPacket(ibctesting.MockPacketData, i, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   570  
   571  				// create packet commitment
   572  				err := path.EndpointA.SendPacket(packet)
   573  				suite.Require().NoError(err)
   574  			}
   575  
   576  			path.EndpointA.UpdateClient()
   577  			packetKey = host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   578  
   579  			// close counterparty channel
   580  			path.EndpointB.SetChannelClosed()
   581  		}, true},
   582  		{"success: ORDERED timeout out of order packet", func() {
   583  			path.SetChannelOrdered()
   584  			suite.coordinator.Setup(path)
   585  
   586  			// attempts to timeout the last packet sent without timing out the first packet
   587  			// packet sequences begin at 1
   588  			for i := uint64(1); i < maxSequence; i++ {
   589  				packet = channeltypes.NewPacket(ibctesting.MockPacketData, i, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   590  
   591  				// create packet commitment
   592  				err := path.EndpointA.SendPacket(packet)
   593  				suite.Require().NoError(err)
   594  			}
   595  
   596  			path.EndpointA.UpdateClient()
   597  			packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   598  
   599  			// close counterparty channel
   600  			path.EndpointB.SetChannelClosed()
   601  		}, true},
   602  		{"channel does not exist", func() {
   603  			// any non-nil value of packet is valid
   604  			suite.Require().NotNil(packet)
   605  
   606  			packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   607  		}, false},
   608  		{"successful no-op: UNORDERED - packet not sent", func() {
   609  			suite.coordinator.Setup(path)
   610  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(0, 1), 0)
   611  			packetKey = host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   612  
   613  			// close counterparty channel
   614  			path.EndpointB.SetChannelClosed()
   615  		}, true},
   616  		{"ORDERED: channel not closed", func() {
   617  			path.SetChannelOrdered()
   618  			suite.coordinator.Setup(path)
   619  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, timeoutHeight, 0)
   620  
   621  			// create packet commitment
   622  			err := path.EndpointA.SendPacket(packet)
   623  			suite.Require().NoError(err)
   624  
   625  			// need to update chainA client to prove missing ack
   626  			path.EndpointA.UpdateClient()
   627  
   628  			packetKey = host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   629  		}, false},
   630  	}
   631  
   632  	for _, tc := range testCases {
   633  		tc := tc
   634  
   635  		suite.Run(tc.name, func() {
   636  			suite.SetupTest() // reset
   637  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   638  
   639  			tc.malleate()
   640  
   641  			proof, proofHeight := suite.chainB.QueryProof(packetKey)
   642  
   643  			channelKey := host.ChannelKey(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   644  			proofClosed, _ := suite.chainB.QueryProof(channelKey)
   645  
   646  			msg := channeltypes.NewMsgTimeoutOnClose(packet, 1, proof, proofClosed, proofHeight, suite.chainA.SenderAccount().GetAddress().String())
   647  
   648  			_, err := keeper.Keeper.TimeoutOnClose(*suite.chainA.App().GetIBCKeeper(), sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
   649  
   650  			if tc.expPass {
   651  				suite.Require().NoError(err)
   652  
   653  				// replay should not return an error as it will be treated as a no-op
   654  				_, err := keeper.Keeper.TimeoutOnClose(*suite.chainA.App().GetIBCKeeper(), sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
   655  				suite.Require().NoError(err)
   656  
   657  				// verify packet commitment was deleted on source chain
   658  				has := suite.chainA.App().GetIBCKeeper().ChannelKeeper.HasPacketCommitment(suite.chainA.GetContext(), packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
   659  				suite.Require().False(has)
   660  
   661  			} else {
   662  				suite.Require().Error(err)
   663  			}
   664  		})
   665  	}
   666  }
   667  
   668  func (suite *KeeperTestSuite) TestUpgradeClient() {
   669  	var (
   670  		path              *ibctesting.Path
   671  		upgradedClient    exported.ClientState
   672  		upgradedConsState exported.ConsensusState
   673  		lastHeight        exported.Height
   674  		msg               *clienttypes.MsgUpgradeClient
   675  	)
   676  
   677  	newClientHeight := clienttypes.NewHeight(1, 1)
   678  	newChainId := "newChainId-1"
   679  
   680  	cases := []struct {
   681  		name    string
   682  		setup   func()
   683  		expPass bool
   684  	}{
   685  		{
   686  			name: "successful upgrade",
   687  			setup: func() {
   688  
   689  				upgradedClient = ibctmtypes.NewClientState(newChainId, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
   690  				// Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient
   691  				upgradedClient = upgradedClient.ZeroCustomFields()
   692  
   693  				upgradedConsState = &ibctmtypes.ConsensusState{
   694  					NextValidatorsHash: []byte("nextValsHash"),
   695  				}
   696  
   697  				// last Height is at next block
   698  				tmpCtx := suite.chainB.GetContext()
   699  				lastHeight = clienttypes.NewHeight(0, uint64(tmpCtx.BlockHeight()+1))
   700  
   701  				upgradedClientBz, err := clienttypes.MarshalClientState(suite.chainA.App().AppCodec(), upgradedClient)
   702  				suite.Require().NoError(err)
   703  				upgradedConsStateBz, err := clienttypes.MarshalConsensusState(suite.chainA.App().AppCodec(), upgradedConsState)
   704  				suite.Require().NoError(err)
   705  
   706  				// zero custom fields and store in upgrade store
   707  				suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz)
   708  				suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz)
   709  
   710  				// commit upgrade store changes and update clients
   711  				suite.coordinator.CommitBlock(suite.chainB)
   712  				err = path.EndpointA.UpdateClient()
   713  				suite.Require().NoError(err)
   714  
   715  				cs, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID)
   716  				suite.Require().True(found)
   717  
   718  				proofUpgradeClient, _ := suite.chainB.QueryUpgradeProof(types2.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight())
   719  				proofUpgradedConsState, _ := suite.chainB.QueryUpgradeProof(types2.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight())
   720  
   721  				msg, err = clienttypes.NewMsgUpgradeClient(path.EndpointA.ClientID, upgradedClient, upgradedConsState,
   722  					proofUpgradeClient, proofUpgradedConsState, suite.chainA.SenderAccount().GetAddress())
   723  				suite.Require().NoError(err)
   724  			},
   725  			expPass: true,
   726  		},
   727  		{
   728  			name: "VerifyUpgrade fails",
   729  			setup: func() {
   730  
   731  				upgradedClient = ibctmtypes.NewClientState(newChainId, ibctmtypes.DefaultTrustLevel, ibctesting.TrustingPeriod, ibctesting.UnbondingPeriod+ibctesting.TrustingPeriod, ibctesting.MaxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false)
   732  				// Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient
   733  				upgradedClient = upgradedClient.ZeroCustomFields()
   734  
   735  				upgradedConsState = &ibctmtypes.ConsensusState{
   736  					NextValidatorsHash: []byte("nextValsHash"),
   737  				}
   738  
   739  				// last Height is at next block
   740  				lastHeight = clienttypes.NewHeight(0, uint64(suite.chainB.GetContextPointer().BlockHeight()+1))
   741  
   742  				upgradedClientBz, err := clienttypes.MarshalClientState(suite.chainA.App().AppCodec(), upgradedClient)
   743  				suite.Require().NoError(err)
   744  				upgradedConsStateBz, err := clienttypes.MarshalConsensusState(suite.chainA.App().AppCodec(), upgradedConsState)
   745  				suite.Require().NoError(err)
   746  
   747  				// zero custom fields and store in upgrade store
   748  				suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz)
   749  				suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz)
   750  
   751  				// commit upgrade store changes and update clients
   752  				suite.coordinator.CommitBlock(suite.chainB)
   753  				err = path.EndpointA.UpdateClient()
   754  				suite.Require().NoError(err)
   755  
   756  				msg, err = clienttypes.NewMsgUpgradeClient(path.EndpointA.ClientID, upgradedClient, upgradedConsState, nil, nil, suite.chainA.SenderAccount().GetAddress())
   757  				suite.Require().NoError(err)
   758  			},
   759  			expPass: false,
   760  		},
   761  	}
   762  
   763  	for _, tc := range cases {
   764  		tc := tc
   765  		path = ibctesting.NewPath(suite.chainA, suite.chainB)
   766  		suite.coordinator.SetupClients(path)
   767  
   768  		tc.setup()
   769  
   770  		_, err := keeper.Keeper.UpgradeClient(*suite.chainA.App().GetIBCKeeper(), sdk.WrapSDKContext(suite.chainA.GetContext()), msg)
   771  
   772  		if tc.expPass {
   773  			suite.Require().NoError(err, "upgrade handler failed on valid case: %s", tc.name)
   774  			newClient, ok := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID)
   775  			suite.Require().True(ok)
   776  			newChainSpecifiedClient := newClient.ZeroCustomFields()
   777  			suite.Require().Equal(upgradedClient, newChainSpecifiedClient)
   778  		} else {
   779  			suite.Require().Error(err, "upgrade handler passed on invalid case: %s", tc.name)
   780  		}
   781  	}
   782  }