github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/04-channel/keeper/handshake_test.go (about) 1 package keeper_test 2 3 import ( 4 "fmt" 5 6 capabilitytypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/types" 7 8 clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 9 connectiontypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/03-connection/types" 10 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types" 11 host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host" 12 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported" 13 14 // capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" 15 ibctesting "github.com/fibonacci-chain/fbc/libs/ibc-go/testing" 16 ) 17 18 type testCase = struct { 19 msg string 20 malleate func() 21 expPass bool 22 } 23 24 // TestChanOpenInit tests the OpenInit handshake call for channels. It uses message passing 25 // to enter into the appropriate state and then calls ChanOpenInit directly. The channel is 26 // being created on chainA. The port capability must be created on chainA before ChanOpenInit 27 // can succeed. 28 func (suite *KeeperTestSuite) TestChanOpenInit() { 29 var ( 30 path *ibctesting.Path 31 features []string 32 portCap *capabilitytypes.Capability 33 ) 34 35 testCases := []testCase{ 36 {"success", func() { 37 suite.coordinator.SetupConnections(path) 38 features = []string{"ORDER_ORDERED", "ORDER_UNORDERED"} 39 suite.chainA.CreatePortCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, ibctesting.MockPort) 40 portCap = suite.chainA.GetPortCapability(ibctesting.MockPort) 41 }, true}, 42 {"channel already exists", func() { 43 suite.coordinator.Setup(path) 44 }, false}, 45 {"connection doesn't exist", func() { 46 // any non-empty values 47 path.EndpointA.ConnectionID = "connection-0" 48 path.EndpointB.ConnectionID = "connection-0" 49 }, false}, 50 {"capability is incorrect", func() { 51 suite.coordinator.SetupConnections(path) 52 features = []string{"ORDER_ORDERED", "ORDER_UNORDERED"} 53 portCap = capabilitytypes.NewCapability(3) 54 }, false}, 55 {"connection version not negotiated", func() { 56 suite.coordinator.SetupConnections(path) 57 58 // modify connA versions 59 conn := path.EndpointA.GetConnection() 60 61 version := connectiontypes.NewVersion("2", []string{"ORDER_ORDERED", "ORDER_UNORDERED"}) 62 conn.Versions = append(conn.Versions, version) 63 64 suite.chainA.App().GetIBCKeeper().ConnectionKeeper.SetConnection( 65 suite.chainA.GetContext(), 66 path.EndpointA.ConnectionID, conn, 67 ) 68 features = []string{"ORDER_ORDERED", "ORDER_UNORDERED"} 69 suite.chainA.CreatePortCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, ibctesting.MockPort) 70 portCap = suite.chainA.GetPortCapability(ibctesting.MockPort) 71 }, false}, 72 {"connection does not support ORDERED channels", func() { 73 suite.coordinator.SetupConnections(path) 74 75 // modify connA versions to only support UNORDERED channels 76 conn := path.EndpointA.GetConnection() 77 78 version := connectiontypes.NewVersion("1", []string{"ORDER_UNORDERED"}) 79 conn.Versions = []*connectiontypes.Version{version} 80 81 suite.chainA.App().GetIBCKeeper().ConnectionKeeper.SetConnection( 82 suite.chainA.GetContext(), 83 path.EndpointA.ConnectionID, conn, 84 ) 85 // NOTE: Opening UNORDERED channels is still expected to pass but ORDERED channels should fail 86 features = []string{"ORDER_UNORDERED"} 87 suite.chainA.CreatePortCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, ibctesting.MockPort) 88 portCap = suite.chainA.GetPortCapability(ibctesting.MockPort) 89 }, true}, 90 } 91 92 for _, tc := range testCases { 93 tc := tc 94 suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { 95 // run test for all types of ordering 96 for _, order := range []types.Order{types.UNORDERED, types.ORDERED} { 97 suite.SetupTest() // reset 98 path = ibctesting.NewPath(suite.chainA, suite.chainB) 99 path.EndpointA.ChannelConfig.Order = order 100 path.EndpointB.ChannelConfig.Order = order 101 102 tc.malleate() 103 104 counterparty := types.NewCounterparty(ibctesting.MockPort, ibctesting.FirstChannelID) 105 106 channelID, cap, err := suite.chainA.App().GetIBCKeeper().ChannelKeeper.ChanOpenInit( 107 suite.chainA.GetContext(), path.EndpointA.ChannelConfig.Order, []string{path.EndpointA.ConnectionID}, 108 path.EndpointA.ChannelConfig.PortID, portCap, counterparty, path.EndpointA.ChannelConfig.Version, 109 ) 110 111 // check if order is supported by channel to determine expected behaviour 112 orderSupported := false 113 for _, f := range features { 114 if f == order.String() { 115 orderSupported = true 116 } 117 } 118 119 // Testcase must have expectedPass = true AND channel order supported before 120 // asserting the channel handshake initiation succeeded 121 if tc.expPass && orderSupported { 122 suite.Require().NoError(err) 123 suite.Require().NotNil(cap) 124 suite.Require().Equal(types.FormatChannelIdentifier(0), channelID) 125 126 chanCap, ok := suite.chainA.App().GetScopedIBCKeeper().GetCapability( 127 suite.chainA.GetContext(), 128 host.ChannelCapabilityPath(path.EndpointA.ChannelConfig.PortID, channelID), 129 ) 130 suite.Require().True(ok, "could not retrieve channel capability after successful ChanOpenInit") 131 suite.Require().Equal(chanCap.String(), cap.String(), "channel capability is not correct") 132 } else { 133 suite.Require().Error(err) 134 suite.Require().Nil(cap) 135 suite.Require().Equal("", channelID) 136 } 137 } 138 }) 139 } 140 } 141 142 // TestChanOpenTry tests the OpenTry handshake call for channels. It uses message passing 143 // to enter into the appropriate state and then calls ChanOpenTry directly. The channel 144 // is being created on chainB. The port capability must be created on chainB before 145 // ChanOpenTry can succeed. 146 func (suite *KeeperTestSuite) TestChanOpenTry() { 147 var ( 148 path *ibctesting.Path 149 portCap *capabilitytypes.Capability 150 heightDiff uint64 151 ) 152 153 testCases := []testCase{ 154 {"success", func() { 155 suite.coordinator.SetupConnections(path) 156 path.SetChannelOrdered() 157 path.EndpointA.ChanOpenInit() 158 159 suite.chainB.CreatePortCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, ibctesting.MockPort) 160 portCap = suite.chainB.GetPortCapability(ibctesting.MockPort) 161 }, true}, 162 {"connection doesn't exist", func() { 163 path.EndpointA.ConnectionID = ibctesting.FirstConnectionID 164 path.EndpointB.ConnectionID = ibctesting.FirstConnectionID 165 166 // pass capability check 167 suite.chainB.CreatePortCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, ibctesting.MockPort) 168 portCap = suite.chainB.GetPortCapability(ibctesting.MockPort) 169 }, false}, 170 {"connection is not OPEN", func() { 171 suite.coordinator.SetupClients(path) 172 // pass capability check 173 suite.chainB.CreatePortCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, ibctesting.MockPort) 174 portCap = suite.chainB.GetPortCapability(ibctesting.MockPort) 175 176 err := path.EndpointB.ConnOpenInit() 177 suite.Require().NoError(err) 178 }, false}, 179 {"consensus state not found", func() { 180 suite.coordinator.SetupConnections(path) 181 path.SetChannelOrdered() 182 path.EndpointA.ChanOpenInit() 183 184 suite.chainB.CreatePortCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, ibctesting.MockPort) 185 portCap = suite.chainB.GetPortCapability(ibctesting.MockPort) 186 187 heightDiff = 3 // consensus state doesn't exist at this height 188 }, false}, 189 {"channel verification failed", func() { 190 // not creating a channel on chainA will result in an invalid proof of existence 191 suite.coordinator.SetupConnections(path) 192 portCap = suite.chainB.GetPortCapability(ibctesting.MockPort) 193 }, false}, 194 {"port capability not found", func() { 195 suite.coordinator.SetupConnections(path) 196 path.SetChannelOrdered() 197 path.EndpointA.ChanOpenInit() 198 199 portCap = capabilitytypes.NewCapability(3) 200 }, false}, 201 {"connection version not negotiated", func() { 202 suite.coordinator.SetupConnections(path) 203 path.SetChannelOrdered() 204 path.EndpointA.ChanOpenInit() 205 206 // modify connB versions 207 conn := path.EndpointB.GetConnection() 208 209 version := connectiontypes.NewVersion("2", []string{"ORDER_ORDERED", "ORDER_UNORDERED"}) 210 conn.Versions = append(conn.Versions, version) 211 212 suite.chainB.GetSimApp().GetIBCKeeper().ConnectionKeeper.SetConnection( 213 suite.chainB.GetContext(), 214 path.EndpointB.ConnectionID, conn, 215 ) 216 suite.chainB.CreatePortCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, ibctesting.MockPort) 217 portCap = suite.chainB.GetPortCapability(ibctesting.MockPort) 218 }, false}, 219 {"connection does not support ORDERED channels", func() { 220 suite.coordinator.SetupConnections(path) 221 path.SetChannelOrdered() 222 path.EndpointA.ChanOpenInit() 223 224 // modify connA versions to only support UNORDERED channels 225 conn := path.EndpointA.GetConnection() 226 227 version := connectiontypes.NewVersion("1", []string{"ORDER_UNORDERED"}) 228 conn.Versions = []*connectiontypes.Version{version} 229 230 suite.chainA.GetSimApp().GetIBCKeeper().ConnectionKeeper.SetConnection( 231 suite.chainA.GetContext(), 232 path.EndpointA.ConnectionID, conn, 233 ) 234 suite.chainA.CreatePortCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, ibctesting.MockPort) 235 portCap = suite.chainA.GetPortCapability(ibctesting.MockPort) 236 }, false}, 237 } 238 239 for _, tc := range testCases { 240 tc := tc 241 suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { 242 suite.SetupTest() // reset 243 heightDiff = 0 // must be explicitly changed in malleate 244 path = ibctesting.NewPath(suite.chainA, suite.chainB) 245 246 tc.malleate() 247 248 if path.EndpointB.ClientID != "" { 249 // ensure client is up to date 250 err := path.EndpointB.UpdateClient() 251 suite.Require().NoError(err) 252 } 253 254 counterparty := types.NewCounterparty(path.EndpointB.ChannelConfig.PortID, ibctesting.FirstChannelID) 255 256 channelKey := host.ChannelKey(counterparty.PortId, counterparty.ChannelId) 257 proof, proofHeight := suite.chainA.QueryProof(channelKey) 258 259 channelID, cap, err := suite.chainB.GetSimApp().GetIBCKeeper().ChannelKeeper.ChanOpenTryV4( 260 suite.chainB.GetContext(), types.ORDERED, []string{path.EndpointB.ConnectionID}, 261 path.EndpointB.ChannelConfig.PortID, portCap, counterparty, path.EndpointA.ChannelConfig.Version, 262 proof, malleateHeight(proofHeight, heightDiff), 263 ) 264 265 if tc.expPass { 266 suite.Require().NoError(err) 267 suite.Require().NotNil(cap) 268 269 chanCap, ok := suite.chainB.GetSimApp().GetScopedIBCKeeper().GetCapability( 270 suite.chainB.GetContext(), 271 host.ChannelCapabilityPath(path.EndpointB.ChannelConfig.PortID, channelID), 272 ) 273 suite.Require().True(ok, "could not retrieve channel capapbility after successful ChanOpenTry") 274 suite.Require().Equal(chanCap.String(), cap.String(), "channel capability is not correct") 275 } else { 276 suite.Require().Error(err) 277 } 278 }) 279 } 280 } 281 282 // TestChanOpenAck tests the OpenAck handshake call for channels. It uses message passing 283 // to enter into the appropriate state and then calls ChanOpenAck directly. The handshake 284 // call is occurring on chainA. 285 func (suite *KeeperTestSuite) TestChanOpenAck() { 286 var ( 287 path *ibctesting.Path 288 counterpartyChannelID string 289 channelCap *capabilitytypes.Capability 290 heightDiff uint64 291 ) 292 293 testCases := []testCase{ 294 {"success", func() { 295 suite.coordinator.SetupConnections(path) 296 path.SetChannelOrdered() 297 err := path.EndpointA.ChanOpenInit() 298 suite.Require().NoError(err) 299 300 err = path.EndpointB.ChanOpenTry() 301 suite.Require().NoError(err) 302 303 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 304 }, true}, 305 {"success with empty stored counterparty channel ID", func() { 306 suite.coordinator.SetupConnections(path) 307 path.SetChannelOrdered() 308 309 err := path.EndpointA.ChanOpenInit() 310 suite.Require().NoError(err) 311 312 err = path.EndpointB.ChanOpenTry() 313 suite.Require().NoError(err) 314 315 // set the channel's counterparty channel identifier to empty string 316 channel := path.EndpointA.GetChannel() 317 channel.Counterparty.ChannelId = "" 318 319 // use a different channel identifier 320 counterpartyChannelID = path.EndpointB.ChannelID 321 322 suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, channel) 323 324 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 325 }, true}, 326 {"channel doesn't exist", func() {}, false}, 327 {"channel state is not INIT or TRYOPEN", func() { 328 // create fully open channels on both chains 329 suite.coordinator.Setup(path) 330 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 331 }, false}, 332 {"connection not found", func() { 333 suite.coordinator.SetupConnections(path) 334 path.SetChannelOrdered() 335 err := path.EndpointA.ChanOpenInit() 336 suite.Require().NoError(err) 337 338 err = path.EndpointB.ChanOpenTry() 339 suite.Require().NoError(err) 340 341 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 342 343 // set the channel's connection hops to wrong connection ID 344 channel := path.EndpointA.GetChannel() 345 channel.ConnectionHops[0] = "doesnotexist" 346 suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, channel) 347 suite.coordinator.CommitBlock(suite.chainA) 348 suite.coordinator.CommitBlock(suite.chainB) 349 }, false}, 350 {"connection is not OPEN", func() { 351 suite.coordinator.SetupClients(path) 352 353 err := path.EndpointA.ConnOpenInit() 354 suite.Require().NoError(err) 355 356 // create channel in init 357 path.SetChannelOrdered() 358 359 err = path.EndpointA.ChanOpenInit() 360 suite.Require().NoError(err) 361 362 suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 363 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 364 }, false}, 365 {"consensus state not found", func() { 366 suite.coordinator.SetupConnections(path) 367 path.SetChannelOrdered() 368 369 err := path.EndpointA.ChanOpenInit() 370 suite.Require().NoError(err) 371 372 err = path.EndpointB.ChanOpenTry() 373 suite.Require().NoError(err) 374 375 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 376 377 heightDiff = 3 // consensus state doesn't exist at this height 378 }, false}, 379 {"invalid counterparty channel identifier", func() { 380 suite.coordinator.SetupConnections(path) 381 path.SetChannelOrdered() 382 383 err := path.EndpointA.ChanOpenInit() 384 suite.Require().NoError(err) 385 386 err = path.EndpointB.ChanOpenTry() 387 suite.Require().NoError(err) 388 389 counterpartyChannelID = "otheridentifier" 390 391 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 392 }, false}, 393 {"channel verification failed", func() { 394 // chainB is INIT, chainA in TRYOPEN 395 suite.coordinator.SetupConnections(path) 396 path.SetChannelOrdered() 397 398 err := path.EndpointB.ChanOpenInit() 399 suite.Require().NoError(err) 400 401 err = path.EndpointA.ChanOpenTry() 402 suite.Require().NoError(err) 403 404 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 405 }, false}, 406 {"channel capability not found", func() { 407 suite.coordinator.SetupConnections(path) 408 path.SetChannelOrdered() 409 err := path.EndpointA.ChanOpenInit() 410 suite.Require().NoError(err) 411 412 path.EndpointB.ChanOpenTry() 413 414 channelCap = capabilitytypes.NewCapability(6) 415 }, false}, 416 } 417 418 for _, tc := range testCases { 419 tc := tc 420 suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { 421 suite.SetupTest() // reset 422 counterpartyChannelID = "" // must be explicitly changed in malleate 423 heightDiff = 0 // must be explicitly changed 424 path = ibctesting.NewPath(suite.chainA, suite.chainB) 425 426 tc.malleate() 427 428 if counterpartyChannelID == "" { 429 counterpartyChannelID = ibctesting.FirstChannelID 430 } 431 432 if path.EndpointA.ClientID != "" { 433 // ensure client is up to date 434 err := path.EndpointA.UpdateClient() 435 suite.Require().NoError(err) 436 } 437 438 channelKey := host.ChannelKey(path.EndpointB.ChannelConfig.PortID, ibctesting.FirstChannelID) 439 proof, proofHeight := suite.chainB.QueryProof(channelKey) 440 441 err := suite.chainA.App().GetIBCKeeper().ChannelKeeper.ChanOpenAck( 442 suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, channelCap, path.EndpointB.ChannelConfig.Version, counterpartyChannelID, 443 proof, malleateHeight(proofHeight, heightDiff), 444 ) 445 446 if tc.expPass { 447 suite.Require().NoError(err) 448 } else { 449 suite.Require().Error(err) 450 } 451 }) 452 } 453 } 454 455 // TestChanOpenConfirm tests the OpenAck handshake call for channels. It uses message passing 456 // to enter into the appropriate state and then calls ChanOpenConfirm directly. The handshake 457 // call is occurring on chainB. 458 func (suite *KeeperTestSuite) TestChanOpenConfirm() { 459 var ( 460 path *ibctesting.Path 461 channelCap *capabilitytypes.Capability 462 heightDiff uint64 463 ) 464 testCases := []testCase{ 465 {"success", func() { 466 suite.coordinator.SetupConnections(path) 467 path.SetChannelOrdered() 468 469 err := path.EndpointA.ChanOpenInit() 470 suite.Require().NoError(err) 471 472 err = path.EndpointB.ChanOpenTry() 473 suite.Require().NoError(err) 474 475 err = path.EndpointA.ChanOpenAck() 476 suite.Require().NoError(err) 477 478 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 479 }, true}, 480 {"channel doesn't exist", func() {}, false}, 481 {"channel state is not TRYOPEN", func() { 482 // create fully open channels on both cahins 483 suite.coordinator.Setup(path) 484 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 485 }, false}, 486 {"connection not found", func() { 487 suite.coordinator.SetupConnections(path) 488 path.SetChannelOrdered() 489 490 err := path.EndpointA.ChanOpenInit() 491 suite.Require().NoError(err) 492 493 err = path.EndpointB.ChanOpenTry() 494 suite.Require().NoError(err) 495 496 err = path.EndpointA.ChanOpenAck() 497 suite.Require().NoError(err) 498 499 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 500 501 // set the channel's connection hops to wrong connection ID 502 channel := path.EndpointB.GetChannel() 503 channel.ConnectionHops[0] = "doesnotexist" 504 suite.chainB.App().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, channel) 505 suite.coordinator.CommitBlock(suite.chainB) 506 }, false}, 507 {"connection is not OPEN", func() { 508 suite.coordinator.SetupClients(path) 509 510 err := path.EndpointB.ConnOpenInit() 511 suite.Require().NoError(err) 512 513 suite.chainB.CreateChannelCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, path.EndpointB.ChannelConfig.PortID, ibctesting.FirstChannelID) 514 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, ibctesting.FirstChannelID) 515 }, false}, 516 {"consensus state not found", func() { 517 suite.coordinator.SetupConnections(path) 518 path.SetChannelOrdered() 519 520 err := path.EndpointA.ChanOpenInit() 521 suite.Require().NoError(err) 522 523 err = path.EndpointB.ChanOpenTry() 524 suite.Require().NoError(err) 525 526 err = path.EndpointA.ChanOpenAck() 527 suite.Require().NoError(err) 528 529 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 530 531 heightDiff = 3 532 }, false}, 533 {"channel verification failed", func() { 534 // chainA is INIT, chainB in TRYOPEN 535 suite.coordinator.SetupConnections(path) 536 path.SetChannelOrdered() 537 538 err := path.EndpointA.ChanOpenInit() 539 suite.Require().NoError(err) 540 541 err = path.EndpointB.ChanOpenTry() 542 suite.Require().NoError(err) 543 544 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 545 }, false}, 546 {"channel capability not found", func() { 547 suite.coordinator.SetupConnections(path) 548 path.SetChannelOrdered() 549 550 err := path.EndpointA.ChanOpenInit() 551 suite.Require().NoError(err) 552 553 err = path.EndpointB.ChanOpenTry() 554 suite.Require().NoError(err) 555 556 err = path.EndpointA.ChanOpenAck() 557 suite.Require().NoError(err) 558 559 channelCap = capabilitytypes.NewCapability(6) 560 }, false}, 561 } 562 563 for _, tc := range testCases { 564 tc := tc 565 suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { 566 suite.SetupTest() // reset 567 heightDiff = 0 // must be explicitly changed 568 path = ibctesting.NewPath(suite.chainA, suite.chainB) 569 570 tc.malleate() 571 572 if path.EndpointB.ClientID != "" { 573 // ensure client is up to date 574 err := path.EndpointB.UpdateClient() 575 suite.Require().NoError(err) 576 577 } 578 579 channelKey := host.ChannelKey(path.EndpointA.ChannelConfig.PortID, ibctesting.FirstChannelID) 580 proof, proofHeight := suite.chainA.QueryProof(channelKey) 581 582 err := suite.chainB.App().GetIBCKeeper().ChannelKeeper.ChanOpenConfirm( 583 suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, ibctesting.FirstChannelID, 584 channelCap, proof, malleateHeight(proofHeight, heightDiff), 585 ) 586 587 if tc.expPass { 588 suite.Require().NoError(err) 589 } else { 590 suite.Require().Error(err) 591 } 592 }) 593 } 594 } 595 596 // TestChanCloseInit tests the initial closing of a handshake on chainA by calling 597 // ChanCloseInit. Both chains will use message passing to setup OPEN channels. 598 func (suite *KeeperTestSuite) TestChanCloseInit() { 599 var ( 600 path *ibctesting.Path 601 channelCap *capabilitytypes.Capability 602 ) 603 604 testCases := []testCase{ 605 {"success", func() { 606 suite.coordinator.Setup(path) 607 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 608 }, true}, 609 {"channel doesn't exist", func() { 610 // any non-nil values work for connections 611 path.EndpointA.ConnectionID = ibctesting.FirstConnectionID 612 path.EndpointB.ConnectionID = ibctesting.FirstConnectionID 613 614 path.EndpointA.ChannelID = ibctesting.FirstChannelID 615 path.EndpointB.ChannelID = ibctesting.FirstChannelID 616 617 // ensure channel capability check passes 618 suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 619 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 620 }, false}, 621 {"channel state is CLOSED", func() { 622 suite.coordinator.Setup(path) 623 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 624 625 // close channel 626 err := path.EndpointA.SetChannelClosed() 627 suite.Require().NoError(err) 628 }, false}, 629 {"connection not found", func() { 630 suite.coordinator.Setup(path) 631 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 632 633 // set the channel's connection hops to wrong connection ID 634 channel := path.EndpointA.GetChannel() 635 channel.ConnectionHops[0] = "doesnotexist" 636 suite.chainA.App().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, channel) 637 }, false}, 638 {"connection is not OPEN", func() { 639 suite.coordinator.SetupClients(path) 640 641 err := path.EndpointA.ConnOpenInit() 642 suite.Require().NoError(err) 643 644 // create channel in init 645 path.SetChannelOrdered() 646 err = path.EndpointA.ChanOpenInit() 647 648 // ensure channel capability check passes 649 suite.chainA.CreateChannelCapability(suite.chainA.GetSimApp().ScopedIBCMockKeeper, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 650 channelCap = suite.chainA.GetChannelCapability(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 651 }, false}, 652 {"channel capability not found", func() { 653 suite.coordinator.Setup(path) 654 channelCap = capabilitytypes.NewCapability(3) 655 }, false}, 656 } 657 658 for _, tc := range testCases { 659 tc := tc 660 suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { 661 suite.SetupTest() // reset 662 path = ibctesting.NewPath(suite.chainA, suite.chainB) 663 664 tc.malleate() 665 666 err := suite.chainA.App().GetIBCKeeper().ChannelKeeper.ChanCloseInit( 667 suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, ibctesting.FirstChannelID, channelCap, 668 ) 669 670 if tc.expPass { 671 suite.Require().NoError(err) 672 } else { 673 suite.Require().Error(err) 674 } 675 }) 676 } 677 } 678 679 // TestChanCloseConfirm tests the confirming closing channel ends by calling ChanCloseConfirm 680 // on chainB. Both chains will use message passing to setup OPEN channels. ChanCloseInit is 681 // bypassed on chainA by setting the channel state in the ChannelKeeper. 682 func (suite *KeeperTestSuite) TestChanCloseConfirm() { 683 var ( 684 path *ibctesting.Path 685 channelCap *capabilitytypes.Capability 686 heightDiff uint64 687 ) 688 689 testCases := []testCase{ 690 {"success", func() { 691 suite.coordinator.Setup(path) 692 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 693 694 err := path.EndpointA.SetChannelClosed() 695 suite.Require().NoError(err) 696 }, true}, 697 {"channel doesn't exist", func() { 698 // any non-nil values work for connections 699 path.EndpointA.ChannelID = ibctesting.FirstChannelID 700 path.EndpointB.ChannelID = ibctesting.FirstChannelID 701 702 // ensure channel capability check passes 703 suite.chainB.CreateChannelCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, path.EndpointB.ChannelConfig.PortID, ibctesting.FirstChannelID) 704 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, ibctesting.FirstChannelID) 705 }, false}, 706 {"channel state is CLOSED", func() { 707 suite.coordinator.Setup(path) 708 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 709 710 err := path.EndpointB.SetChannelClosed() 711 suite.Require().NoError(err) 712 }, false}, 713 {"connection not found", func() { 714 suite.coordinator.Setup(path) 715 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 716 717 // set the channel's connection hops to wrong connection ID 718 channel := path.EndpointB.GetChannel() 719 channel.ConnectionHops[0] = "doesnotexist" 720 suite.chainB.App().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, channel) 721 }, false}, 722 {"connection is not OPEN", func() { 723 suite.coordinator.SetupClients(path) 724 725 err := path.EndpointB.ConnOpenInit() 726 suite.Require().NoError(err) 727 728 // create channel in init 729 path.SetChannelOrdered() 730 err = path.EndpointB.ChanOpenInit() 731 suite.Require().NoError(err) 732 733 // ensure channel capability check passes 734 suite.chainB.CreateChannelCapability(suite.chainB.GetSimApp().ScopedIBCMockKeeper, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 735 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 736 }, false}, 737 {"consensus state not found", func() { 738 suite.coordinator.Setup(path) 739 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 740 741 err := path.EndpointA.SetChannelClosed() 742 suite.Require().NoError(err) 743 744 heightDiff = 3 745 }, false}, 746 {"channel verification failed", func() { 747 // channel not closed 748 suite.coordinator.Setup(path) 749 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 750 }, false}, 751 {"channel capability not found", func() { 752 suite.coordinator.Setup(path) 753 channelCap = suite.chainB.GetChannelCapability(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 754 755 err := path.EndpointA.SetChannelClosed() 756 suite.Require().NoError(err) 757 758 channelCap = capabilitytypes.NewCapability(3) 759 }, false}, 760 } 761 762 for _, tc := range testCases { 763 tc := tc 764 suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { 765 suite.SetupTest() // reset 766 heightDiff = 0 // must explicitly be changed 767 path = ibctesting.NewPath(suite.chainA, suite.chainB) 768 769 tc.malleate() 770 771 channelKey := host.ChannelKey(path.EndpointA.ChannelConfig.PortID, ibctesting.FirstChannelID) 772 proof, proofHeight := suite.chainA.QueryProof(channelKey) 773 774 err := suite.chainB.App().GetIBCKeeper().ChannelKeeper.ChanCloseConfirm( 775 suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, ibctesting.FirstChannelID, channelCap, 776 proof, malleateHeight(proofHeight, heightDiff), 777 ) 778 779 if tc.expPass { 780 suite.Require().NoError(err) 781 } else { 782 suite.Require().Error(err) 783 } 784 }) 785 } 786 } 787 788 func malleateHeight(height exported.Height, diff uint64) exported.Height { 789 return clienttypes.NewHeight(height.GetRevisionNumber(), height.GetRevisionHeight()+diff) 790 }