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

     1  package keeper_test
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
     8  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types"
     9  	channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types"
    10  	host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host"
    11  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported"
    12  	ibctmtypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/07-tendermint/types"
    13  	ibctesting "github.com/fibonacci-chain/fbc/libs/ibc-go/testing"
    14  	ibcmock "github.com/fibonacci-chain/fbc/libs/ibc-go/testing/mock"
    15  )
    16  
    17  var defaultTimeoutHeight = clienttypes.NewHeight(0, 100000)
    18  
    19  // TestVerifyClientState verifies a client state of chainA
    20  // stored on path.EndpointB (which is on chainB)
    21  func (suite *KeeperTestSuite) TestVerifyClientState() {
    22  	var (
    23  		path       *ibctesting.Path
    24  		heightDiff uint64
    25  	)
    26  	cases := []struct {
    27  		name     string
    28  		malleate func()
    29  		expPass  bool
    30  	}{
    31  		{"verification success", func() {}, true},
    32  		{"client state not found", func() {
    33  			connection := path.EndpointA.GetConnection()
    34  			connection.ClientId = ibctesting.InvalidID
    35  			path.EndpointA.SetConnection(connection)
    36  		}, false},
    37  		{"consensus state for proof height not found", func() {
    38  			heightDiff = 5
    39  		}, false},
    40  		{"verification failed", func() {
    41  			counterpartyClient := path.EndpointB.GetClientState().(*ibctmtypes.ClientState)
    42  			counterpartyClient.ChainId = "wrongChainID"
    43  			path.EndpointB.SetClientState(counterpartyClient)
    44  		}, false},
    45  		{"client status is not active - client is expired", func() {
    46  			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
    47  			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
    48  			path.EndpointA.SetClientState(clientState)
    49  		}, false},
    50  	}
    51  
    52  	for _, tc := range cases {
    53  		tc := tc
    54  
    55  		suite.Run(tc.name, func() {
    56  			suite.SetupTest() // reset
    57  			heightDiff = 0    // must be explicitly changed
    58  
    59  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
    60  			suite.coordinator.SetupConnections(path)
    61  
    62  			tc.malleate()
    63  
    64  			tmpCtx := suite.chainB.GetContext()
    65  			counterpartyClient, clientProof := path.EndpointB.QueryClientStateProof()
    66  			proofHeight := clienttypes.NewHeight(0, uint64(tmpCtx.BlockHeight()-1))
    67  
    68  			connection := path.EndpointA.GetConnection()
    69  
    70  			err := suite.chainA.App().GetIBCKeeper().ConnectionKeeper.VerifyClientState(
    71  				suite.chainA.GetContext(), connection,
    72  				malleateHeight(proofHeight, heightDiff), clientProof, counterpartyClient,
    73  			)
    74  
    75  			if tc.expPass {
    76  				suite.Require().NoError(err)
    77  			} else {
    78  				suite.Require().Error(err)
    79  			}
    80  		})
    81  	}
    82  }
    83  
    84  // TestVerifyClientConsensusState verifies that the consensus state of
    85  // chainA stored on path.EndpointB.ClientID (which is on chainB) matches the consensus
    86  // state for chainA at that height.
    87  func (suite *KeeperTestSuite) TestVerifyClientConsensusState() {
    88  	var (
    89  		path       *ibctesting.Path
    90  		heightDiff uint64
    91  	)
    92  	cases := []struct {
    93  		name     string
    94  		malleate func()
    95  		expPass  bool
    96  	}{
    97  		{"verification success", func() {}, true},
    98  		{"client state not found", func() {
    99  			connection := path.EndpointA.GetConnection()
   100  			connection.ClientId = ibctesting.InvalidID
   101  			path.EndpointA.SetConnection(connection)
   102  		}, false},
   103  		{"consensus state not found", func() {
   104  			heightDiff = 5
   105  		}, false},
   106  		{"verification failed", func() {
   107  			clientState := suite.chainB.GetClientState(path.EndpointB.ClientID)
   108  
   109  			// give chainB wrong consensus state for chainA
   110  			consState, found := suite.chainB.App().GetIBCKeeper().ClientKeeper.GetLatestClientConsensusState(suite.chainB.GetContext(), path.EndpointB.ClientID)
   111  			suite.Require().True(found)
   112  
   113  			tmConsState, ok := consState.(*ibctmtypes.ConsensusState)
   114  			suite.Require().True(ok)
   115  
   116  			tmConsState.Timestamp = time.Now()
   117  			suite.chainB.App().GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainB.GetContext(), path.EndpointB.ClientID, clientState.GetLatestHeight(), tmConsState)
   118  
   119  			suite.coordinator.CommitBlock(suite.chainB)
   120  		}, false},
   121  		{"client status is not active - client is expired", func() {
   122  			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
   123  			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
   124  			path.EndpointA.SetClientState(clientState)
   125  		}, false},
   126  	}
   127  
   128  	for _, tc := range cases {
   129  		tc := tc
   130  
   131  		suite.Run(tc.name, func() {
   132  			suite.SetupTest() // reset
   133  			heightDiff = 0    // must be explicitly changed in malleate
   134  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   135  			suite.coordinator.SetupConnections(path)
   136  
   137  			tc.malleate()
   138  
   139  			connection := path.EndpointA.GetConnection()
   140  
   141  			proof, consensusHeight := suite.chainB.QueryConsensusStateProof(path.EndpointB.ClientID)
   142  			tmpCtx := suite.chainB.GetContext()
   143  			proofHeight := clienttypes.NewHeight(0, uint64(tmpCtx.BlockHeight()-1))
   144  			consensusState, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetSelfConsensusState(suite.chainA.GetContext(), consensusHeight)
   145  			suite.Require().True(found)
   146  
   147  			err := suite.chainA.App().GetIBCKeeper().ConnectionKeeper.VerifyClientConsensusState(
   148  				suite.chainA.GetContext(), connection,
   149  				malleateHeight(proofHeight, heightDiff), consensusHeight, proof, consensusState,
   150  			)
   151  
   152  			if tc.expPass {
   153  				suite.Require().NoError(err)
   154  			} else {
   155  				suite.Require().Error(err)
   156  			}
   157  		})
   158  	}
   159  }
   160  
   161  // TestVerifyConnectionState verifies the connection state of the connection
   162  // on chainB. The connections on chainA and chainB are fully opened.
   163  func (suite *KeeperTestSuite) TestVerifyConnectionState() {
   164  	var (
   165  		path       *ibctesting.Path
   166  		heightDiff uint64
   167  	)
   168  	cases := []struct {
   169  		name     string
   170  		malleate func()
   171  		expPass  bool
   172  	}{
   173  		{"verification success", func() {}, true},
   174  		{"client state not found - changed client ID", func() {
   175  			connection := path.EndpointA.GetConnection()
   176  			connection.ClientId = ibctesting.InvalidID
   177  			path.EndpointA.SetConnection(connection)
   178  		}, false},
   179  		{"consensus state not found - increased proof height", func() {
   180  			heightDiff = 5
   181  		}, false},
   182  		{"verification failed - connection state is different than proof", func() {
   183  			connection := path.EndpointA.GetConnection()
   184  			connection.State = types.TRYOPEN
   185  			path.EndpointA.SetConnection(connection)
   186  		}, false},
   187  		{"client status is not active - client is expired", func() {
   188  			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
   189  			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
   190  			path.EndpointA.SetClientState(clientState)
   191  		}, false},
   192  	}
   193  
   194  	for _, tc := range cases {
   195  		tc := tc
   196  
   197  		suite.Run(tc.name, func() {
   198  			suite.SetupTest() // reset
   199  
   200  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   201  			suite.coordinator.SetupConnections(path)
   202  
   203  			connectionKey := host.ConnectionKey(path.EndpointB.ConnectionID)
   204  			proof, proofHeight := suite.chainB.QueryProof(connectionKey)
   205  
   206  			tc.malleate()
   207  
   208  			connection := path.EndpointA.GetConnection()
   209  
   210  			expectedConnection := path.EndpointB.GetConnection()
   211  
   212  			err := suite.chainA.App().GetIBCKeeper().ConnectionKeeper.VerifyConnectionState(
   213  				suite.chainA.GetContext(), connection,
   214  				malleateHeight(proofHeight, heightDiff), proof, path.EndpointB.ConnectionID, expectedConnection,
   215  			)
   216  
   217  			if tc.expPass {
   218  				suite.Require().NoError(err)
   219  			} else {
   220  				suite.Require().Error(err)
   221  			}
   222  		})
   223  	}
   224  }
   225  
   226  // TestVerifyChannelState verifies the channel state of the channel on
   227  // chainB. The channels on chainA and chainB are fully opened.
   228  func (suite *KeeperTestSuite) TestVerifyChannelState() {
   229  	var (
   230  		path       *ibctesting.Path
   231  		heightDiff uint64
   232  	)
   233  	cases := []struct {
   234  		name     string
   235  		malleate func()
   236  		expPass  bool
   237  	}{
   238  		{"verification success", func() {}, true},
   239  		{"client state not found- changed client ID", func() {
   240  			connection := path.EndpointA.GetConnection()
   241  			connection.ClientId = ibctesting.InvalidID
   242  			path.EndpointA.SetConnection(connection)
   243  		}, false},
   244  		{"consensus state not found - increased proof height", func() {
   245  			heightDiff = 5
   246  		}, false},
   247  		{"verification failed - changed channel state", func() {
   248  			channel := path.EndpointA.GetChannel()
   249  			channel.State = channeltypes.TRYOPEN
   250  			path.EndpointA.SetChannel(channel)
   251  		}, false},
   252  		{"client status is not active - client is expired", func() {
   253  			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
   254  			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
   255  			path.EndpointA.SetClientState(clientState)
   256  		}, false},
   257  	}
   258  
   259  	for _, tc := range cases {
   260  		tc := tc
   261  
   262  		suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
   263  			suite.SetupTest() // reset
   264  
   265  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   266  			suite.coordinator.Setup(path)
   267  
   268  			channelKey := host.ChannelKey(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
   269  			proof, proofHeight := suite.chainB.QueryProof(channelKey)
   270  
   271  			tc.malleate()
   272  			connection := path.EndpointA.GetConnection()
   273  
   274  			channel := path.EndpointB.GetChannel()
   275  
   276  			err := suite.chainA.App().GetIBCKeeper().ConnectionKeeper.VerifyChannelState(
   277  				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, heightDiff), proof,
   278  				path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, channel,
   279  			)
   280  
   281  			if tc.expPass {
   282  				suite.Require().NoError(err)
   283  			} else {
   284  				suite.Require().Error(err)
   285  			}
   286  		})
   287  	}
   288  }
   289  
   290  // TestVerifyPacketCommitmentState has chainB verify the packet commitment
   291  // on channelA. The channels on chainA and chainB are fully opened and a
   292  // packet is sent from chainA to chainB, but has not been received.
   293  func (suite *KeeperTestSuite) TestVerifyPacketCommitment() {
   294  	var (
   295  		path            *ibctesting.Path
   296  		packet          channeltypes.Packet
   297  		heightDiff      uint64
   298  		delayTimePeriod uint64
   299  		timePerBlock    uint64
   300  	)
   301  	cases := []struct {
   302  		name     string
   303  		malleate func()
   304  		expPass  bool
   305  	}{
   306  		{"verification success", func() {}, true},
   307  		{"verification success: delay period passed", func() {
   308  			delayTimePeriod = uint64(1 * time.Second.Nanoseconds())
   309  		}, true},
   310  		{"delay time period has not passed", func() {
   311  			delayTimePeriod = uint64(1 * time.Hour.Nanoseconds())
   312  		}, false},
   313  		{"delay block period has not passed", func() {
   314  			// make timePerBlock 1 nanosecond so that block delay is not passed.
   315  			// must also set a non-zero time delay to ensure block delay is enforced.
   316  			delayTimePeriod = uint64(1 * time.Second.Nanoseconds())
   317  			timePerBlock = 1
   318  		}, false},
   319  		{"client state not found- changed client ID", func() {
   320  			connection := path.EndpointB.GetConnection()
   321  			connection.ClientId = ibctesting.InvalidID
   322  			path.EndpointB.SetConnection(connection)
   323  		}, false},
   324  		{"consensus state not found - increased proof height", func() {
   325  			heightDiff = 5
   326  		}, false},
   327  		{"verification failed - changed packet commitment state", func() {
   328  			packet.Data = []byte(ibctesting.InvalidID)
   329  		}, false},
   330  		{"client status is not active - client is expired", func() {
   331  			clientState := path.EndpointB.GetClientState().(*ibctmtypes.ClientState)
   332  			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
   333  			path.EndpointB.SetClientState(clientState)
   334  		}, false},
   335  	}
   336  
   337  	for _, tc := range cases {
   338  		tc := tc
   339  
   340  		suite.Run(tc.name, func() {
   341  			suite.SetupTest() // reset
   342  
   343  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   344  			suite.coordinator.Setup(path)
   345  
   346  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, 0)
   347  			err := path.EndpointA.SendPacket(packet)
   348  			suite.Require().NoError(err)
   349  
   350  			// reset variables
   351  			heightDiff = 0
   352  			delayTimePeriod = 0
   353  			timePerBlock = 0
   354  			tc.malleate()
   355  
   356  			connection := path.EndpointB.GetConnection()
   357  			connection.DelayPeriod = delayTimePeriod
   358  			commitmentKey := host.PacketCommitmentKey(packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())
   359  			proof, proofHeight := suite.chainA.QueryProof(commitmentKey)
   360  
   361  			// set time per block param
   362  			if timePerBlock != 0 {
   363  				suite.chainB.App().GetIBCKeeper().ConnectionKeeper.SetParams(suite.chainB.GetContext(), types.NewParams(timePerBlock))
   364  			}
   365  
   366  			commitment := channeltypes.CommitPacket(suite.chainB.App().GetIBCKeeper().Codec(), packet)
   367  			err = suite.chainB.App().GetIBCKeeper().ConnectionKeeper.VerifyPacketCommitment(
   368  				suite.chainB.GetContext(), connection, malleateHeight(proofHeight, heightDiff), proof,
   369  				packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence(), commitment,
   370  			)
   371  
   372  			if tc.expPass {
   373  				suite.Require().NoError(err)
   374  			} else {
   375  				suite.Require().Error(err)
   376  			}
   377  		})
   378  	}
   379  }
   380  
   381  // TestVerifyPacketAcknowledgement has chainA verify the acknowledgement on
   382  // channelB. The channels on chainA and chainB are fully opened and a packet
   383  // is sent from chainA to chainB and received.
   384  func (suite *KeeperTestSuite) TestVerifyPacketAcknowledgement() {
   385  	var (
   386  		path            *ibctesting.Path
   387  		ack             exported.Acknowledgement
   388  		heightDiff      uint64
   389  		delayTimePeriod uint64
   390  		timePerBlock    uint64
   391  	)
   392  
   393  	cases := []struct {
   394  		name     string
   395  		malleate func()
   396  		expPass  bool
   397  	}{
   398  		{"verification success", func() {}, true},
   399  		{"verification success: delay period passed", func() {
   400  			delayTimePeriod = uint64(1 * time.Second.Nanoseconds())
   401  		}, true},
   402  		{"delay time period has not passed", func() {
   403  			delayTimePeriod = uint64(1 * time.Hour.Nanoseconds())
   404  		}, false},
   405  		{"delay block period has not passed", func() {
   406  			// make timePerBlock 1 nanosecond so that block delay is not passed.
   407  			// must also set a non-zero time delay to ensure block delay is enforced.
   408  			delayTimePeriod = uint64(1 * time.Second.Nanoseconds())
   409  			timePerBlock = 1
   410  		}, false},
   411  		{"client state not found- changed client ID", func() {
   412  			connection := path.EndpointA.GetConnection()
   413  			connection.ClientId = ibctesting.InvalidID
   414  			path.EndpointA.SetConnection(connection)
   415  		}, false},
   416  		{"consensus state not found - increased proof height", func() {
   417  			heightDiff = 5
   418  		}, false},
   419  		{"verification failed - changed acknowledgement", func() {
   420  			ack = ibcmock.MockFailAcknowledgement
   421  		}, false},
   422  		{"client status is not active - client is expired", func() {
   423  			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
   424  			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
   425  			path.EndpointA.SetClientState(clientState)
   426  		}, false},
   427  	}
   428  
   429  	for _, tc := range cases {
   430  		tc := tc
   431  
   432  		suite.Run(tc.name, func() {
   433  			suite.SetupTest()                 // reset
   434  			ack = ibcmock.MockAcknowledgement // must be explicitly changed
   435  
   436  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   437  			suite.coordinator.Setup(path)
   438  
   439  			// send and receive packet
   440  			packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, 0)
   441  			err := path.EndpointA.SendPacket(packet)
   442  			suite.Require().NoError(err)
   443  
   444  			// increment receiving chain's (chainB) time by 2 hour to always pass receive
   445  			suite.coordinator.IncrementTimeBy(time.Hour * 2)
   446  			suite.coordinator.CommitBlock(suite.chainB)
   447  
   448  			err = path.EndpointB.RecvPacket(packet)
   449  			suite.Require().NoError(err)
   450  
   451  			packetAckKey := host.PacketAcknowledgementKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   452  			proof, proofHeight := suite.chainB.QueryProof(packetAckKey)
   453  
   454  			// reset variables
   455  			heightDiff = 0
   456  			delayTimePeriod = 0
   457  			timePerBlock = 0
   458  			tc.malleate()
   459  
   460  			connection := path.EndpointA.GetConnection()
   461  			connection.DelayPeriod = delayTimePeriod
   462  
   463  			// set time per block param
   464  			if timePerBlock != 0 {
   465  				suite.chainA.App().GetIBCKeeper().ConnectionKeeper.SetParams(suite.chainA.GetContext(), types.NewParams(timePerBlock))
   466  			}
   467  
   468  			err = suite.chainA.App().GetIBCKeeper().ConnectionKeeper.VerifyPacketAcknowledgement(
   469  				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, heightDiff), proof,
   470  				packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(), ack.Acknowledgement(),
   471  			)
   472  
   473  			if tc.expPass {
   474  				suite.Require().NoError(err)
   475  			} else {
   476  				suite.Require().Error(err)
   477  			}
   478  		})
   479  	}
   480  }
   481  
   482  // TestVerifyPacketReceiptAbsence has chainA verify the receipt
   483  // absence on channelB. The channels on chainA and chainB are fully opened and
   484  // a packet is sent from chainA to chainB and not received.
   485  func (suite *KeeperTestSuite) TestVerifyPacketReceiptAbsence() {
   486  	var (
   487  		path            *ibctesting.Path
   488  		packet          channeltypes.Packet
   489  		heightDiff      uint64
   490  		delayTimePeriod uint64
   491  		timePerBlock    uint64
   492  	)
   493  
   494  	cases := []struct {
   495  		name     string
   496  		malleate func()
   497  		expPass  bool
   498  	}{
   499  		{"verification success", func() {}, true},
   500  		{"verification success: delay period passed", func() {
   501  			delayTimePeriod = uint64(1 * time.Second.Nanoseconds())
   502  		}, true},
   503  		{"delay time period has not passed", func() {
   504  			delayTimePeriod = uint64(1 * time.Hour.Nanoseconds())
   505  		}, false},
   506  		{"delay block period has not passed", func() {
   507  			// make timePerBlock 1 nanosecond so that block delay is not passed.
   508  			// must also set a non-zero time delay to ensure block delay is enforced.
   509  			delayTimePeriod = uint64(1 * time.Second.Nanoseconds())
   510  			timePerBlock = 1
   511  		}, false},
   512  		{"client state not found - changed client ID", func() {
   513  			connection := path.EndpointA.GetConnection()
   514  			connection.ClientId = ibctesting.InvalidID
   515  			path.EndpointA.SetConnection(connection)
   516  		}, false},
   517  		{"consensus state not found - increased proof height", func() {
   518  			heightDiff = 5
   519  		}, false},
   520  		{"verification failed - acknowledgement was received", func() {
   521  			// increment receiving chain's (chainB) time by 2 hour to always pass receive
   522  			suite.coordinator.IncrementTimeBy(time.Hour * 2)
   523  			suite.coordinator.CommitBlock(suite.chainB)
   524  
   525  			err := path.EndpointB.RecvPacket(packet)
   526  			suite.Require().NoError(err)
   527  		}, false},
   528  		{"client status is not active - client is expired", func() {
   529  			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
   530  			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
   531  			path.EndpointA.SetClientState(clientState)
   532  		}, false},
   533  	}
   534  
   535  	for _, tc := range cases {
   536  		tc := tc
   537  
   538  		suite.Run(tc.name, func() {
   539  			suite.SetupTest() // reset
   540  
   541  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   542  			suite.coordinator.Setup(path)
   543  
   544  			// send, only receive in malleate if applicable
   545  			packet = channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, 0)
   546  			err := path.EndpointA.SendPacket(packet)
   547  			suite.Require().NoError(err)
   548  
   549  			// reset variables
   550  			heightDiff = 0
   551  			delayTimePeriod = 0
   552  			timePerBlock = 0
   553  			tc.malleate()
   554  
   555  			connection := path.EndpointA.GetConnection()
   556  			connection.DelayPeriod = delayTimePeriod
   557  
   558  			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
   559  			if clientState.FrozenHeight.IsZero() {
   560  				// need to update height to prove absence or receipt
   561  				suite.coordinator.CommitBlock(suite.chainA, suite.chainB)
   562  				path.EndpointA.UpdateClient()
   563  			}
   564  
   565  			packetReceiptKey := host.PacketReceiptKey(packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
   566  			proof, proofHeight := suite.chainB.QueryProof(packetReceiptKey)
   567  
   568  			// set time per block param
   569  			if timePerBlock != 0 {
   570  				suite.chainA.App().GetIBCKeeper().ConnectionKeeper.SetParams(suite.chainA.GetContext(), types.NewParams(timePerBlock))
   571  			}
   572  
   573  			err = suite.chainA.App().GetIBCKeeper().ConnectionKeeper.VerifyPacketReceiptAbsence(
   574  				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, heightDiff), proof,
   575  				packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence(),
   576  			)
   577  
   578  			if tc.expPass {
   579  				suite.Require().NoError(err)
   580  			} else {
   581  				suite.Require().Error(err)
   582  			}
   583  		})
   584  	}
   585  }
   586  
   587  // TestVerifyNextSequenceRecv has chainA verify the next sequence receive on
   588  // channelB. The channels on chainA and chainB are fully opened and a packet
   589  // is sent from chainA to chainB and received.
   590  func (suite *KeeperTestSuite) TestVerifyNextSequenceRecv() {
   591  	var (
   592  		path            *ibctesting.Path
   593  		heightDiff      uint64
   594  		delayTimePeriod uint64
   595  		timePerBlock    uint64
   596  		offsetSeq       uint64
   597  	)
   598  
   599  	cases := []struct {
   600  		name     string
   601  		malleate func()
   602  		expPass  bool
   603  	}{
   604  		{"verification success", func() {}, true},
   605  		{"verification success: delay period passed", func() {
   606  			delayTimePeriod = uint64(1 * time.Second.Nanoseconds())
   607  		}, true},
   608  		{"delay time period has not passed", func() {
   609  			delayTimePeriod = uint64(1 * time.Hour.Nanoseconds())
   610  		}, false},
   611  		{"delay block period has not passed", func() {
   612  			// make timePerBlock 1 nanosecond so that block delay is not passed.
   613  			// must also set a non-zero time delay to ensure block delay is enforced.
   614  			delayTimePeriod = uint64(1 * time.Second.Nanoseconds())
   615  			timePerBlock = 1
   616  		}, false},
   617  		{"client state not found- changed client ID", func() {
   618  			connection := path.EndpointA.GetConnection()
   619  			connection.ClientId = ibctesting.InvalidID
   620  			path.EndpointA.SetConnection(connection)
   621  		}, false},
   622  		{"consensus state not found - increased proof height", func() {
   623  			heightDiff = 5
   624  		}, false},
   625  		{"verification failed - wrong expected next seq recv", func() {
   626  			offsetSeq = 1
   627  		}, false},
   628  		{"client status is not active - client is expired", func() {
   629  			clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState)
   630  			clientState.FrozenHeight = clienttypes.NewHeight(0, 1)
   631  			path.EndpointA.SetClientState(clientState)
   632  		}, false},
   633  	}
   634  
   635  	for _, tc := range cases {
   636  		tc := tc
   637  
   638  		suite.Run(tc.name, func() {
   639  			suite.SetupTest() // reset
   640  
   641  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   642  			suite.coordinator.Setup(path)
   643  
   644  			// send and receive packet
   645  			packet := channeltypes.NewPacket(ibctesting.MockPacketData, 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, defaultTimeoutHeight, 0)
   646  			err := path.EndpointA.SendPacket(packet)
   647  			suite.Require().NoError(err)
   648  
   649  			// increment receiving chain's (chainB) time by 2 hour to always pass receive
   650  			suite.coordinator.IncrementTimeBy(time.Hour * 2)
   651  			suite.coordinator.CommitBlock(suite.chainB)
   652  
   653  			err = path.EndpointB.RecvPacket(packet)
   654  			suite.Require().NoError(err)
   655  
   656  			nextSeqRecvKey := host.NextSequenceRecvKey(packet.GetDestPort(), packet.GetDestChannel())
   657  			proof, proofHeight := suite.chainB.QueryProof(nextSeqRecvKey)
   658  
   659  			// reset variables
   660  			heightDiff = 0
   661  			delayTimePeriod = 0
   662  			timePerBlock = 0
   663  			tc.malleate()
   664  
   665  			// set time per block param
   666  			if timePerBlock != 0 {
   667  				suite.chainA.App().GetIBCKeeper().ConnectionKeeper.SetParams(suite.chainA.GetContext(), types.NewParams(timePerBlock))
   668  			}
   669  
   670  			connection := path.EndpointA.GetConnection()
   671  			connection.DelayPeriod = delayTimePeriod
   672  			err = suite.chainA.App().GetIBCKeeper().ConnectionKeeper.VerifyNextSequenceRecv(
   673  				suite.chainA.GetContext(), connection, malleateHeight(proofHeight, heightDiff), proof,
   674  				packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence()+offsetSeq,
   675  			)
   676  
   677  			if tc.expPass {
   678  				suite.Require().NoError(err)
   679  			} else {
   680  				suite.Require().Error(err)
   681  			}
   682  		})
   683  	}
   684  }
   685  
   686  func malleateHeight(height exported.Height, diff uint64) exported.Height {
   687  	return clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+diff)
   688  }