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

     1  package keeper_test
     2  
     3  import (
     4  	"time"
     5  
     6  	clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
     7  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types"
     8  	host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host"
     9  	"github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported"
    10  	ibctmtypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/07-tendermint/types"
    11  	ibctesting "github.com/fibonacci-chain/fbc/libs/ibc-go/testing"
    12  )
    13  
    14  // TestConnOpenInit - chainA initializes (INIT state) a connection with
    15  // chainB which is yet UNINITIALIZED
    16  func (suite *KeeperTestSuite) TestConnOpenInit() {
    17  	var (
    18  		path         *ibctesting.Path
    19  		version      *types.Version
    20  		delayPeriod  uint64
    21  		emptyConnBID bool
    22  	)
    23  
    24  	testCases := []struct {
    25  		msg      string
    26  		malleate func()
    27  		expPass  bool
    28  	}{
    29  		{"success", func() {
    30  		}, true},
    31  		{"success with empty counterparty identifier", func() {
    32  			emptyConnBID = true
    33  		}, true},
    34  		{"success with non empty version", func() {
    35  			version = types.ExportedVersionsToProto(types.GetCompatibleVersions())[0]
    36  		}, true},
    37  		{"success with non zero delayPeriod", func() {
    38  			delayPeriod = uint64(time.Hour.Nanoseconds())
    39  		}, true},
    40  
    41  		{"invalid version", func() {
    42  			version = &types.Version{}
    43  		}, false},
    44  		{"couldn't add connection to client", func() {
    45  			// set path.EndpointA.ClientID to invalid client identifier
    46  			path.EndpointA.ClientID = "clientidentifier"
    47  		}, false},
    48  	}
    49  
    50  	for _, tc := range testCases {
    51  		tc := tc
    52  		suite.Run(tc.msg, func() {
    53  			suite.SetupTest()    // reset
    54  			emptyConnBID = false // must be explicitly changed
    55  			version = nil        // must be explicitly changed
    56  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
    57  			suite.coordinator.SetupClients(path)
    58  
    59  			tc.malleate()
    60  
    61  			if emptyConnBID {
    62  				path.EndpointB.ConnectionID = ""
    63  			}
    64  			counterparty := types.NewCounterparty(path.EndpointB.ClientID, path.EndpointB.ConnectionID, suite.chainB.GetPrefix())
    65  
    66  			connectionID, err := suite.chainA.App().GetIBCKeeper().ConnectionKeeper.ConnOpenInit(suite.chainA.GetContext(), path.EndpointA.ClientID, counterparty, version, delayPeriod)
    67  
    68  			if tc.expPass {
    69  				suite.Require().NoError(err)
    70  				suite.Require().Equal(types.FormatConnectionIdentifier(0), connectionID)
    71  			} else {
    72  				suite.Require().Error(err)
    73  				suite.Require().Equal("", connectionID)
    74  			}
    75  		})
    76  	}
    77  }
    78  
    79  // TestConnOpenTry - chainB calls ConnOpenTry to verify the state of
    80  // connection on chainA is INIT
    81  func (suite *KeeperTestSuite) TestConnOpenTry() {
    82  	var (
    83  		path                 *ibctesting.Path
    84  		delayPeriod          uint64
    85  		previousConnectionID string
    86  		versions             []exported.Version
    87  		consensusHeight      exported.Height
    88  		counterpartyClient   exported.ClientState
    89  	)
    90  
    91  	testCases := []struct {
    92  		msg      string
    93  		malleate func()
    94  		expPass  bool
    95  	}{
    96  		{"success", func() {
    97  			err := path.EndpointA.ConnOpenInit()
    98  			suite.Require().NoError(err)
    99  
   100  			// retrieve client state of chainA to pass as counterpartyClient
   101  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   102  		}, true},
   103  		{"success with crossing hellos", func() {
   104  			err := suite.coordinator.ConnOpenInitOnBothChains(path)
   105  			suite.Require().NoError(err)
   106  
   107  			// retrieve client state of chainA to pass as counterpartyClient
   108  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   109  
   110  			previousConnectionID = path.EndpointB.ConnectionID
   111  		}, true},
   112  		{"success with delay period", func() {
   113  			err := path.EndpointA.ConnOpenInit()
   114  			suite.Require().NoError(err)
   115  
   116  			delayPeriod = uint64(time.Hour.Nanoseconds())
   117  
   118  			// set delay period on counterparty to non-zero value
   119  			conn := path.EndpointA.GetConnection()
   120  			conn.DelayPeriod = delayPeriod
   121  			suite.chainA.App().GetIBCKeeper().ConnectionKeeper.SetConnection(suite.chainA.GetContext(), path.EndpointA.ConnectionID, conn)
   122  
   123  			// commit in order for proof to return correct value
   124  			suite.coordinator.CommitBlock(suite.chainA)
   125  			path.EndpointB.UpdateClient()
   126  
   127  			// retrieve client state of chainA to pass as counterpartyClient
   128  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   129  		}, true},
   130  		{"invalid counterparty client", func() {
   131  			err := path.EndpointA.ConnOpenInit()
   132  			suite.Require().NoError(err)
   133  
   134  			// retrieve client state of chainB to pass as counterpartyClient
   135  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   136  
   137  			// Set an invalid client of chainA on chainB
   138  			tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
   139  			suite.Require().True(ok)
   140  			tmClient.ChainId = "wrongchainid"
   141  
   142  			suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, tmClient)
   143  		}, false},
   144  		{"consensus height >= latest height", func() {
   145  			err := path.EndpointA.ConnOpenInit()
   146  			suite.Require().NoError(err)
   147  
   148  			// retrieve client state of chainA to pass as counterpartyClient
   149  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   150  
   151  			consensusHeight = clienttypes.GetSelfHeight(suite.chainB.GetContext())
   152  		}, false},
   153  		{"self consensus state not found", func() {
   154  			err := path.EndpointA.ConnOpenInit()
   155  			suite.Require().NoError(err)
   156  
   157  			// retrieve client state of chainA to pass as counterpartyClient
   158  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   159  
   160  			consensusHeight = clienttypes.NewHeight(0, 1)
   161  		}, false},
   162  		{"counterparty versions is empty", func() {
   163  			err := path.EndpointA.ConnOpenInit()
   164  			suite.Require().NoError(err)
   165  
   166  			// retrieve client state of chainA to pass as counterpartyClient
   167  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   168  
   169  			versions = nil
   170  		}, false},
   171  		{"counterparty versions don't have a match", func() {
   172  			err := path.EndpointA.ConnOpenInit()
   173  			suite.Require().NoError(err)
   174  
   175  			// retrieve client state of chainA to pass as counterpartyClient
   176  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   177  
   178  			version := types.NewVersion("0.0", nil)
   179  			versions = []exported.Version{version}
   180  		}, false},
   181  		{"connection state verification failed", func() {
   182  			// chainA connection not created
   183  
   184  			// retrieve client state of chainA to pass as counterpartyClient
   185  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   186  		}, false},
   187  		{"client state verification failed", func() {
   188  			err := path.EndpointA.ConnOpenInit()
   189  			suite.Require().NoError(err)
   190  
   191  			// retrieve client state of chainA to pass as counterpartyClient
   192  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   193  
   194  			// modify counterparty client without setting in store so it still passes validate but fails proof verification
   195  			tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
   196  			suite.Require().True(ok)
   197  			tmClient.LatestHeight = tmClient.LatestHeight.Increment().(clienttypes.Height)
   198  		}, false},
   199  		{"consensus state verification failed", func() {
   200  			// retrieve client state of chainA to pass as counterpartyClient
   201  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   202  
   203  			// give chainA wrong consensus state for chainB
   204  			consState, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetLatestClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID)
   205  			suite.Require().True(found)
   206  
   207  			tmConsState, ok := consState.(*ibctmtypes.ConsensusState)
   208  			suite.Require().True(ok)
   209  
   210  			tmConsState.Timestamp = time.Now()
   211  			suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID, counterpartyClient.GetLatestHeight(), tmConsState)
   212  
   213  			err := path.EndpointA.ConnOpenInit()
   214  			suite.Require().NoError(err)
   215  		}, false},
   216  		{"invalid previous connection is in TRYOPEN", func() {
   217  			// open init chainA
   218  			err := path.EndpointA.ConnOpenInit()
   219  			suite.Require().NoError(err)
   220  
   221  			// open try chainB
   222  			err = path.EndpointB.ConnOpenTry()
   223  			suite.Require().NoError(err)
   224  
   225  			err = path.EndpointB.UpdateClient()
   226  			suite.Require().NoError(err)
   227  
   228  			// retrieve client state of chainA to pass as counterpartyClient
   229  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   230  
   231  			previousConnectionID = path.EndpointB.ConnectionID
   232  		}, false},
   233  		{"invalid previous connection has invalid versions", func() {
   234  			// open init chainA
   235  			err := path.EndpointA.ConnOpenInit()
   236  			suite.Require().NoError(err)
   237  
   238  			// open try chainB
   239  			err = path.EndpointB.ConnOpenTry()
   240  			suite.Require().NoError(err)
   241  
   242  			// modify connB to be in INIT with incorrect versions
   243  			connection, found := suite.chainB.App().GetIBCKeeper().ConnectionKeeper.GetConnection(suite.chainB.GetContext(), path.EndpointB.ConnectionID)
   244  			suite.Require().True(found)
   245  
   246  			connection.State = types.INIT
   247  			connection.Versions = []*types.Version{{}}
   248  
   249  			suite.chainB.App().GetIBCKeeper().ConnectionKeeper.SetConnection(suite.chainB.GetContext(), path.EndpointB.ConnectionID, connection)
   250  
   251  			err = path.EndpointB.UpdateClient()
   252  			suite.Require().NoError(err)
   253  
   254  			// retrieve client state of chainA to pass as counterpartyClient
   255  			counterpartyClient = suite.chainA.GetClientState(path.EndpointA.ClientID)
   256  
   257  			previousConnectionID = path.EndpointB.ConnectionID
   258  		}, false},
   259  	}
   260  
   261  	for _, tc := range testCases {
   262  		tc := tc
   263  
   264  		suite.Run(tc.msg, func() {
   265  			suite.SetupTest()                          // reset
   266  			consensusHeight = clienttypes.ZeroHeight() // must be explicitly changed in malleate
   267  			versions = types.GetCompatibleVersions()   // must be explicitly changed in malleate
   268  			previousConnectionID = ""
   269  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   270  			suite.coordinator.SetupClients(path)
   271  
   272  			tc.malleate()
   273  
   274  			counterparty := types.NewCounterparty(path.EndpointA.ClientID, path.EndpointA.ConnectionID, suite.chainA.GetPrefix())
   275  
   276  			// ensure client is up to date to receive proof
   277  			err := path.EndpointB.UpdateClient()
   278  			suite.Require().NoError(err)
   279  
   280  			connectionKey := host.ConnectionKey(path.EndpointA.ConnectionID)
   281  			proofInit, proofHeight := suite.chainA.QueryProof(connectionKey)
   282  
   283  			if consensusHeight.IsZero() {
   284  				// retrieve consensus state height to provide proof for
   285  				consensusHeight = counterpartyClient.GetLatestHeight()
   286  			}
   287  			consensusKey := host.FullConsensusStateKey(path.EndpointA.ClientID, consensusHeight)
   288  			proofConsensus, _ := suite.chainA.QueryProof(consensusKey)
   289  
   290  			// retrieve proof of counterparty clientstate on chainA
   291  			clientKey := host.FullClientStateKey(path.EndpointA.ClientID)
   292  			proofClient, _ := suite.chainA.QueryProof(clientKey)
   293  
   294  			connectionID, err := suite.chainB.App().GetIBCKeeper().ConnectionKeeper.ConnOpenTry(
   295  				suite.chainB.GetContext(), previousConnectionID, counterparty, delayPeriod, path.EndpointB.ClientID, counterpartyClient,
   296  				versions, proofInit, proofClient, proofConsensus,
   297  				proofHeight, consensusHeight,
   298  			)
   299  
   300  			if tc.expPass {
   301  				suite.Require().NoError(err)
   302  				suite.Require().Equal(types.FormatConnectionIdentifier(0), connectionID)
   303  			} else {
   304  				suite.Require().Error(err)
   305  				suite.Require().Equal("", connectionID)
   306  			}
   307  		})
   308  	}
   309  }
   310  
   311  // TestConnOpenAck - Chain A (ID #1) calls TestConnOpenAck to acknowledge (ACK state)
   312  // the initialization (TRYINIT) of the connection on  Chain B (ID #2).
   313  func (suite *KeeperTestSuite) TestConnOpenAck() {
   314  	var (
   315  		path               *ibctesting.Path
   316  		consensusHeight    exported.Height
   317  		version            *types.Version
   318  		counterpartyClient exported.ClientState
   319  	)
   320  
   321  	testCases := []struct {
   322  		msg      string
   323  		malleate func()
   324  		expPass  bool
   325  	}{
   326  		{"success", func() {
   327  			err := path.EndpointA.ConnOpenInit()
   328  			suite.Require().NoError(err)
   329  
   330  			err = path.EndpointB.ConnOpenTry()
   331  			suite.Require().NoError(err)
   332  
   333  			// retrieve client state of chainB to pass as counterpartyClient
   334  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   335  		}, true},
   336  		{"success from tryopen", func() {
   337  			// chainA is in TRYOPEN, chainB is in TRYOPEN
   338  			err := path.EndpointB.ConnOpenInit()
   339  			suite.Require().NoError(err)
   340  
   341  			err = path.EndpointA.ConnOpenTry()
   342  			suite.Require().NoError(err)
   343  
   344  			// set chainB to TRYOPEN
   345  			connection := path.EndpointB.GetConnection()
   346  			connection.State = types.TRYOPEN
   347  			connection.Counterparty.ConnectionId = path.EndpointA.ConnectionID
   348  			suite.chainB.App().GetIBCKeeper().ConnectionKeeper.SetConnection(suite.chainB.GetContext(), path.EndpointB.ConnectionID, connection)
   349  			// update path.EndpointB.ClientID so state change is committed
   350  			suite.coordinator.CommitBlock(suite.chainB)
   351  
   352  			path.EndpointB.UpdateClient()
   353  			path.EndpointA.UpdateClient()
   354  
   355  			// retrieve client state of chainB to pass as counterpartyClient
   356  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   357  		}, true},
   358  		{"invalid counterparty client", func() {
   359  			err := path.EndpointA.ConnOpenInit()
   360  			suite.Require().NoError(err)
   361  
   362  			err = path.EndpointB.ConnOpenTry()
   363  			suite.Require().NoError(err)
   364  
   365  			// retrieve client state of chainB to pass as counterpartyClient
   366  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   367  
   368  			// Set an invalid client of chainA on chainB
   369  			tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
   370  			suite.Require().True(ok)
   371  			tmClient.ChainId = "wrongchainid"
   372  
   373  			suite.chainB.App().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainB.GetContext(), path.EndpointB.ClientID, tmClient)
   374  
   375  		}, false},
   376  		{"consensus height >= latest height", func() {
   377  			err := path.EndpointA.ConnOpenInit()
   378  			suite.Require().NoError(err)
   379  
   380  			// retrieve client state of chainB to pass as counterpartyClient
   381  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   382  
   383  			err = path.EndpointB.ConnOpenTry()
   384  			suite.Require().NoError(err)
   385  
   386  			consensusHeight = clienttypes.GetSelfHeight(suite.chainA.GetContext())
   387  		}, false},
   388  		{"connection not found", func() {
   389  			// connections are never created
   390  
   391  			// retrieve client state of chainB to pass as counterpartyClient
   392  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   393  		}, false},
   394  		{"invalid counterparty connection ID", func() {
   395  			err := path.EndpointA.ConnOpenInit()
   396  			suite.Require().NoError(err)
   397  
   398  			// retrieve client state of chainB to pass as counterpartyClient
   399  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   400  
   401  			err = path.EndpointB.ConnOpenTry()
   402  			suite.Require().NoError(err)
   403  
   404  			// modify connB to set counterparty connection identifier to wrong identifier
   405  			connection, found := suite.chainA.App().GetIBCKeeper().ConnectionKeeper.GetConnection(suite.chainA.GetContext(), path.EndpointA.ConnectionID)
   406  			suite.Require().True(found)
   407  
   408  			connection.Counterparty.ConnectionId = "badconnectionid"
   409  
   410  			suite.chainA.App().GetIBCKeeper().ConnectionKeeper.SetConnection(suite.chainA.GetContext(), path.EndpointA.ConnectionID, connection)
   411  
   412  			err = path.EndpointA.UpdateClient()
   413  			suite.Require().NoError(err)
   414  
   415  			err = path.EndpointB.UpdateClient()
   416  			suite.Require().NoError(err)
   417  		}, false},
   418  		{"connection state is not INIT", func() {
   419  			// connection state is already OPEN on chainA
   420  			err := path.EndpointA.ConnOpenInit()
   421  			suite.Require().NoError(err)
   422  
   423  			// retrieve client state of chainB to pass as counterpartyClient
   424  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   425  
   426  			err = path.EndpointB.ConnOpenTry()
   427  			suite.Require().NoError(err)
   428  
   429  			err = path.EndpointA.ConnOpenAck()
   430  			suite.Require().NoError(err)
   431  		}, false},
   432  		{"connection is in INIT but the proposed version is invalid", func() {
   433  			// chainA is in INIT, chainB is in TRYOPEN
   434  			err := path.EndpointA.ConnOpenInit()
   435  			suite.Require().NoError(err)
   436  
   437  			// retrieve client state of chainB to pass as counterpartyClient
   438  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   439  
   440  			err = path.EndpointB.ConnOpenTry()
   441  			suite.Require().NoError(err)
   442  
   443  			version = types.NewVersion("2.0", nil)
   444  		}, false},
   445  		{"connection is in TRYOPEN but the set version in the connection is invalid", func() {
   446  			// chainA is in TRYOPEN, chainB is in TRYOPEN
   447  			err := path.EndpointB.ConnOpenInit()
   448  			suite.Require().NoError(err)
   449  
   450  			err = path.EndpointA.ConnOpenTry()
   451  			suite.Require().NoError(err)
   452  
   453  			// set chainB to TRYOPEN
   454  			connection := path.EndpointB.GetConnection()
   455  			connection.State = types.TRYOPEN
   456  			suite.chainB.App().GetIBCKeeper().ConnectionKeeper.SetConnection(suite.chainB.GetContext(), path.EndpointB.ConnectionID, connection)
   457  
   458  			// update path.EndpointB.ClientID so state change is committed
   459  			path.EndpointB.UpdateClient()
   460  			path.EndpointA.UpdateClient()
   461  
   462  			// retrieve client state of chainB to pass as counterpartyClient
   463  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   464  
   465  			version = types.NewVersion("2.0", nil)
   466  		}, false},
   467  		{"incompatible IBC versions", func() {
   468  			err := path.EndpointA.ConnOpenInit()
   469  			suite.Require().NoError(err)
   470  
   471  			// retrieve client state of chainB to pass as counterpartyClient
   472  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   473  
   474  			err = path.EndpointB.ConnOpenTry()
   475  			suite.Require().NoError(err)
   476  
   477  			// set version to a non-compatible version
   478  			version = types.NewVersion("2.0", nil)
   479  		}, false},
   480  		{"empty version", func() {
   481  			err := path.EndpointA.ConnOpenInit()
   482  			suite.Require().NoError(err)
   483  
   484  			// retrieve client state of chainB to pass as counterpartyClient
   485  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   486  
   487  			err = path.EndpointB.ConnOpenTry()
   488  			suite.Require().NoError(err)
   489  
   490  			version = &types.Version{}
   491  		}, false},
   492  		{"feature set verification failed - unsupported feature", func() {
   493  			err := path.EndpointA.ConnOpenInit()
   494  			suite.Require().NoError(err)
   495  
   496  			// retrieve client state of chainB to pass as counterpartyClient
   497  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   498  
   499  			err = path.EndpointB.ConnOpenTry()
   500  			suite.Require().NoError(err)
   501  
   502  			version = types.NewVersion(types.DefaultIBCVersionIdentifier, []string{"ORDER_ORDERED", "ORDER_UNORDERED", "ORDER_DAG"})
   503  		}, false},
   504  		{"self consensus state not found", func() {
   505  			err := path.EndpointA.ConnOpenInit()
   506  			suite.Require().NoError(err)
   507  
   508  			// retrieve client state of chainB to pass as counterpartyClient
   509  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   510  
   511  			err = path.EndpointB.ConnOpenTry()
   512  			suite.Require().NoError(err)
   513  
   514  			consensusHeight = clienttypes.NewHeight(0, 1)
   515  		}, false},
   516  		{"connection state verification failed", func() {
   517  			// chainB connection is not in INIT
   518  			err := path.EndpointA.ConnOpenInit()
   519  			suite.Require().NoError(err)
   520  
   521  			// retrieve client state of chainB to pass as counterpartyClient
   522  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   523  		}, false},
   524  		{"client state verification failed", func() {
   525  			err := path.EndpointA.ConnOpenInit()
   526  			suite.Require().NoError(err)
   527  
   528  			// retrieve client state of chainB to pass as counterpartyClient
   529  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   530  
   531  			// modify counterparty client without setting in store so it still passes validate but fails proof verification
   532  			tmClient, ok := counterpartyClient.(*ibctmtypes.ClientState)
   533  			suite.Require().True(ok)
   534  			tmClient.LatestHeight = tmClient.LatestHeight.Increment().(clienttypes.Height)
   535  
   536  			err = path.EndpointB.ConnOpenTry()
   537  			suite.Require().NoError(err)
   538  		}, false},
   539  		{"consensus state verification failed", func() {
   540  			err := path.EndpointA.ConnOpenInit()
   541  			suite.Require().NoError(err)
   542  
   543  			// retrieve client state of chainB to pass as counterpartyClient
   544  			counterpartyClient = suite.chainB.GetClientState(path.EndpointB.ClientID)
   545  
   546  			// give chainB wrong consensus state for chainA
   547  			consState, found := suite.chainB.App().GetIBCKeeper().ClientKeeper.GetLatestClientConsensusState(suite.chainB.GetContext(), path.EndpointB.ClientID)
   548  			suite.Require().True(found)
   549  
   550  			tmConsState, ok := consState.(*ibctmtypes.ConsensusState)
   551  			suite.Require().True(ok)
   552  
   553  			tmConsState.Timestamp = tmConsState.Timestamp.Add(time.Second)
   554  			suite.chainB.App().GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainB.GetContext(), path.EndpointB.ClientID, counterpartyClient.GetLatestHeight(), tmConsState)
   555  
   556  			err = path.EndpointB.ConnOpenTry()
   557  			suite.Require().NoError(err)
   558  
   559  		}, false},
   560  	}
   561  
   562  	for _, tc := range testCases {
   563  		tc := tc
   564  		suite.Run(tc.msg, func() {
   565  			suite.SetupTest()                                                         // reset
   566  			version = types.ExportedVersionsToProto(types.GetCompatibleVersions())[0] // must be explicitly changed in malleate
   567  			consensusHeight = clienttypes.ZeroHeight()                                // must be explicitly changed in malleate
   568  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   569  			suite.coordinator.SetupClients(path)
   570  
   571  			tc.malleate()
   572  
   573  			// ensure client is up to date to receive proof
   574  			err := path.EndpointA.UpdateClient()
   575  			suite.Require().NoError(err)
   576  
   577  			connectionKey := host.ConnectionKey(path.EndpointB.ConnectionID)
   578  			proofTry, proofHeight := suite.chainB.QueryProof(connectionKey)
   579  
   580  			if consensusHeight.IsZero() {
   581  				// retrieve consensus state height to provide proof for
   582  				clientState := suite.chainB.GetClientState(path.EndpointB.ClientID)
   583  				consensusHeight = clientState.GetLatestHeight()
   584  			}
   585  			consensusKey := host.FullConsensusStateKey(path.EndpointB.ClientID, consensusHeight)
   586  			proofConsensus, _ := suite.chainB.QueryProof(consensusKey)
   587  
   588  			// retrieve proof of counterparty clientstate on chainA
   589  			clientKey := host.FullClientStateKey(path.EndpointB.ClientID)
   590  			proofClient, _ := suite.chainB.QueryProof(clientKey)
   591  
   592  			err = suite.chainA.App().GetIBCKeeper().ConnectionKeeper.ConnOpenAck(
   593  				suite.chainA.GetContext(), path.EndpointA.ConnectionID, counterpartyClient, version, path.EndpointB.ConnectionID,
   594  				proofTry, proofClient, proofConsensus, proofHeight, consensusHeight,
   595  			)
   596  
   597  			if tc.expPass {
   598  				suite.Require().NoError(err)
   599  			} else {
   600  				suite.Require().Error(err)
   601  			}
   602  		})
   603  	}
   604  }
   605  
   606  // TestConnOpenConfirm - chainB calls ConnOpenConfirm to confirm that
   607  // chainA state is now OPEN.
   608  func (suite *KeeperTestSuite) TestConnOpenConfirm() {
   609  	var path *ibctesting.Path
   610  	testCases := []struct {
   611  		msg      string
   612  		malleate func()
   613  		expPass  bool
   614  	}{
   615  		{"success", func() {
   616  			err := path.EndpointA.ConnOpenInit()
   617  			suite.Require().NoError(err)
   618  
   619  			err = path.EndpointB.ConnOpenTry()
   620  			suite.Require().NoError(err)
   621  
   622  			err = path.EndpointA.ConnOpenAck()
   623  			suite.Require().NoError(err)
   624  		}, true},
   625  		{"connection not found", func() {
   626  			// connections are never created
   627  		}, false},
   628  		{"chain B's connection state is not TRYOPEN", func() {
   629  			// connections are OPEN
   630  			suite.coordinator.CreateConnections(path)
   631  		}, false},
   632  		{"connection state verification failed", func() {
   633  			// chainA is in INIT
   634  			err := path.EndpointA.ConnOpenInit()
   635  			suite.Require().NoError(err)
   636  
   637  			err = path.EndpointB.ConnOpenTry()
   638  			suite.Require().NoError(err)
   639  		}, false},
   640  	}
   641  
   642  	for _, tc := range testCases {
   643  		tc := tc
   644  
   645  		suite.Run(tc.msg, func() {
   646  			suite.SetupTest() // reset
   647  			path = ibctesting.NewPath(suite.chainA, suite.chainB)
   648  			suite.coordinator.SetupClients(path)
   649  
   650  			tc.malleate()
   651  
   652  			// ensure client is up to date to receive proof
   653  			err := path.EndpointB.UpdateClient()
   654  			suite.Require().NoError(err)
   655  
   656  			connectionKey := host.ConnectionKey(path.EndpointA.ConnectionID)
   657  			proofAck, proofHeight := suite.chainA.QueryProof(connectionKey)
   658  
   659  			err = suite.chainB.App().GetIBCKeeper().ConnectionKeeper.ConnOpenConfirm(
   660  				suite.chainB.GetContext(), path.EndpointB.ConnectionID, proofAck, proofHeight,
   661  			)
   662  
   663  			if tc.expPass {
   664  				suite.Require().NoError(err)
   665  			} else {
   666  				suite.Require().Error(err)
   667  			}
   668  		})
   669  	}
   670  }