github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go (about) 1 package controller_test 2 3 import ( 4 "fmt" 5 "testing" 6 7 types2 "github.com/fibonacci-chain/fbc/libs/tendermint/types" 8 9 clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 10 channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types" 11 12 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 13 capabilitytypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/capability/types" 14 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/27-interchain-accounts/controller/types" 15 icatypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/27-interchain-accounts/types" 16 fee "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/29-fee" 17 host "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/24-host" 18 ibctesting "github.com/fibonacci-chain/fbc/libs/ibc-go/testing" 19 "github.com/fibonacci-chain/fbc/libs/tendermint/crypto" 20 "github.com/stretchr/testify/suite" 21 ) 22 23 var ( 24 // TODO: Cosmos-SDK ADR-28: Update crypto.AddressHash() when sdk uses address.Module() 25 // https://github.com/cosmos/cosmos-sdk/issues/10225 26 // 27 // TestAccAddress defines a resuable bech32 address for testing purposes 28 TestAccAddress = icatypes.GenerateAddress(sdk.AccAddress(crypto.AddressHash([]byte(icatypes.ModuleName))), ibctesting.FirstConnectionID, TestPortID) 29 30 // TestOwnerAddress defines a reusable bech32 address for testing purposes 31 TestOwnerAddress = "cosmos17dtl0mjt3t77kpuhg2edqzjpszulwhgzuj9ljs" 32 33 // TestPortID defines a resuable port identifier for testing purposes 34 TestPortID, _ = icatypes.NewControllerPortID(TestOwnerAddress) 35 36 // TestVersion defines a resuable interchainaccounts version string for testing purposes 37 TestVersion = string(icatypes.ModuleCdc.MustMarshalJSON(&icatypes.Metadata{ 38 Version: icatypes.Version, 39 ControllerConnectionId: ibctesting.FirstConnectionID, 40 HostConnectionId: ibctesting.FirstConnectionID, 41 Encoding: icatypes.EncodingProtobuf, 42 TxType: icatypes.TxTypeSDKMultiMsg, 43 })) 44 ) 45 46 type InterchainAccountsTestSuite struct { 47 suite.Suite 48 49 coordinator *ibctesting.Coordinator 50 51 // testing chains used for convenience and readability 52 chainA ibctesting.TestChainI 53 chainB ibctesting.TestChainI 54 chainC ibctesting.TestChainI 55 } 56 57 func TestICATestSuite(t *testing.T) { 58 suite.Run(t, new(InterchainAccountsTestSuite)) 59 } 60 61 func (suite *InterchainAccountsTestSuite) SetupTest() { 62 types2.UnittestOnlySetMilestoneVenus1Height(-1) 63 types2.UnittestOnlySetMilestoneVenus4Height(-1) 64 suite.coordinator = ibctesting.NewCoordinator(suite.T(), 3) 65 suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) 66 suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) 67 suite.chainC = suite.coordinator.GetChain(ibctesting.GetChainID(2)) 68 } 69 70 func NewICAPath(chainA, chainB ibctesting.TestChainI) *ibctesting.Path { 71 path := ibctesting.NewPath(chainA, chainB) 72 path.EndpointA.ChannelConfig.PortID = icatypes.PortID 73 path.EndpointB.ChannelConfig.PortID = icatypes.PortID 74 path.EndpointA.ChannelConfig.Order = channeltypes.ORDERED 75 path.EndpointB.ChannelConfig.Order = channeltypes.ORDERED 76 path.EndpointA.ChannelConfig.Version = TestVersion 77 path.EndpointB.ChannelConfig.Version = TestVersion 78 79 return path 80 } 81 82 func RegisterInterchainAccount(endpoint *ibctesting.Endpoint, owner string) error { 83 portID, err := icatypes.NewControllerPortID(owner) 84 if err != nil { 85 return err 86 } 87 88 channelSequence := endpoint.Chain.GetSimApp().GetIBCKeeper().ChannelKeeper.GetNextChannelSequence(endpoint.Chain.GetContext()) 89 90 if err := endpoint.Chain.GetSimApp().ICAControllerKeeper.RegisterInterchainAccount(endpoint.Chain.GetContext(), endpoint.ConnectionID, owner, TestVersion); err != nil { 91 return err 92 } 93 94 // commit state changes for proof verification 95 endpoint.Chain.Coordinator().CommitBlock(endpoint.Chain) 96 97 // update port/channel ids 98 endpoint.ChannelID = channeltypes.FormatChannelIdentifier(channelSequence) 99 endpoint.ChannelConfig.PortID = portID 100 endpoint.ChannelConfig.Version = TestVersion 101 102 return nil 103 } 104 105 // SetupICAPath invokes the InterchainAccounts entrypoint and subsequent channel handshake handlers 106 func SetupICAPath(path *ibctesting.Path, owner string) error { 107 if err := RegisterInterchainAccount(path.EndpointA, owner); err != nil { 108 return err 109 } 110 111 if err := path.EndpointB.ChanOpenTry(); err != nil { 112 return err 113 } 114 115 if err := path.EndpointA.ChanOpenAck(); err != nil { 116 return err 117 } 118 119 if err := path.EndpointB.ChanOpenConfirm(); err != nil { 120 return err 121 } 122 123 return nil 124 } 125 126 func (suite *InterchainAccountsTestSuite) TestOnChanOpenInit() { 127 var channel *channeltypes.Channel 128 129 testCases := []struct { 130 name string 131 malleate func() 132 expPass bool 133 }{ 134 { 135 "success", func() {}, true, 136 }, 137 { 138 "ICA auth module modification of channel version is ignored", func() { 139 // NOTE: explicitly modify the channel version via the auth module callback, 140 // ensuring the expected JSON encoded metadata is not modified upon return 141 suite.chainA.GetSimApp().ICAAuthModule.IBCApp.OnChanOpenInit = func(ctx sdk.Context, order channeltypes.Order, connectionHops []string, 142 portID, channelID string, chanCap *capabilitytypes.Capability, 143 counterparty channeltypes.Counterparty, version string, 144 ) (string, error) { 145 return "invalid-version", nil 146 } 147 }, true, 148 }, 149 { 150 "controller submodule disabled", func() { 151 suite.chainA.GetSimApp().ICAControllerKeeper.SetParams(suite.chainA.GetContext(), types.NewParams(false)) 152 }, false, 153 }, 154 { 155 "ICA OnChanOpenInit fails - UNORDERED channel", func() { 156 channel.Ordering = channeltypes.UNORDERED 157 }, false, 158 }, 159 { 160 "ICA auth module callback fails", func() { 161 suite.chainA.GetSimApp().ICAAuthModule.IBCApp.OnChanOpenInit = func(ctx sdk.Context, order channeltypes.Order, connectionHops []string, 162 portID, channelID string, chanCap *capabilitytypes.Capability, 163 counterparty channeltypes.Counterparty, version string, 164 ) (string, error) { 165 return "", fmt.Errorf("mock ica auth fails") 166 } 167 }, false, 168 }, 169 } 170 171 for _, tc := range testCases { 172 tc := tc 173 174 suite.Run(tc.name, func() { 175 suite.SetupTest() // reset 176 177 path := NewICAPath(suite.chainA, suite.chainB) 178 suite.coordinator.SetupConnections(path) 179 180 // mock init interchain account 181 portID, err := icatypes.NewControllerPortID(TestOwnerAddress) 182 suite.Require().NoError(err) 183 184 portCap := suite.chainA.GetSimApp().IBCKeeper.V2Keeper.PortKeeper.BindPort(suite.chainA.GetContext(), portID) 185 suite.chainA.GetSimApp().ICAControllerKeeper.ClaimCapability(suite.chainA.GetContext(), portCap, host.PortPath(portID)) 186 187 path.EndpointA.ChannelConfig.PortID = portID 188 path.EndpointA.ChannelID = ibctesting.FirstChannelID 189 190 // default values 191 counterparty := channeltypes.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 192 channel = &channeltypes.Channel{ 193 State: channeltypes.INIT, 194 Ordering: channeltypes.ORDERED, 195 Counterparty: counterparty, 196 ConnectionHops: []string{path.EndpointA.ConnectionID}, 197 Version: path.EndpointA.ChannelConfig.Version, 198 } 199 200 tc.malleate() // malleate mutates test data 201 202 // ensure channel on chainA is set in state 203 suite.chainA.GetSimApp().IBCKeeper.V2Keeper.ChannelKeeper.SetChannel(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, *channel) 204 205 module, _, err := suite.chainA.GetSimApp().GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID) 206 suite.Require().NoError(err) 207 208 chanCap, err := suite.chainA.GetSimApp().GetScopedIBCKeeper().NewCapability(suite.chainA.GetContext(), host.ChannelCapabilityPath(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)) 209 suite.Require().NoError(err) 210 211 cbs, ok := suite.chainA.GetSimApp().GetIBCKeeper().Router.GetRoute(module) 212 suite.Require().True(ok) 213 214 version, err := cbs.OnChanOpenInit(suite.chainA.GetContext(), channel.Ordering, channel.GetConnectionHops(), 215 path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, chanCap, channel.Counterparty, channel.GetVersion(), 216 ) 217 218 if tc.expPass { 219 suite.Require().Equal(icatypes.NewDefaultMetadataString(path.EndpointA.ConnectionID, path.EndpointB.ConnectionID), version) 220 suite.Require().NoError(err) 221 } else { 222 suite.Require().Error(err) 223 } 224 }) 225 } 226 } 227 228 // Test initiating a ChanOpenTry using the controller chain instead of the host chain 229 // ChainA is the controller chain. ChainB creates a controller port as well, 230 // attempting to trick chainA. 231 // Sending a MsgChanOpenTry will never reach the application callback due to 232 // core IBC checks not passing, so a call to the application callback is also 233 // done directly. 234 func (suite *InterchainAccountsTestSuite) TestChanOpenTry() { 235 suite.SetupTest() // reset 236 path := NewICAPath(suite.chainA, suite.chainB) 237 suite.coordinator.SetupConnections(path) 238 239 err := RegisterInterchainAccount(path.EndpointA, TestOwnerAddress) 240 suite.Require().NoError(err) 241 242 // chainB also creates a controller port 243 err = RegisterInterchainAccount(path.EndpointB, TestOwnerAddress) 244 suite.Require().NoError(err) 245 246 path.EndpointA.UpdateClient() 247 channelKey := host.ChannelKey(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 248 proofInit, proofHeight := path.EndpointB.Chain.QueryProof(channelKey) 249 250 // use chainA (controller) for ChanOpenTry 251 msg := channeltypes.NewMsgChannelOpenTry(path.EndpointA.ChannelConfig.PortID, "", 252 TestVersion, channeltypes.ORDERED, 253 []string{path.EndpointA.ConnectionID}, 254 path.EndpointB.ChannelConfig.PortID, 255 path.EndpointB.ChannelID, TestVersion, 256 proofInit, proofHeight, icatypes.ModuleName) 257 handler := suite.chainA.GetSimApp().MsgServiceRouter().HandlerWithMsg(msg) 258 _, err = handler(suite.chainA.GetContext(), msg) 259 260 suite.Require().Error(err) 261 262 // call application callback directly 263 module, _, err := suite.chainA.GetSimApp().GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), path.EndpointB.ChannelConfig.PortID) 264 suite.Require().NoError(err) 265 266 cbs, ok := suite.chainA.GetSimApp().GetIBCKeeper().Router.GetRoute(module) 267 suite.Require().True(ok) 268 269 counterparty := channeltypes.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 270 chanCap, found := suite.chainA.GetSimApp().GetScopedIBCKeeper().GetCapability(suite.chainA.GetContext(), host.ChannelCapabilityPath(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)) 271 suite.Require().True(found) 272 273 version, err := cbs.OnChanOpenTry( 274 suite.chainA.GetContext(), path.EndpointA.ChannelConfig.Order, []string{path.EndpointA.ConnectionID}, 275 path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, chanCap, 276 counterparty, path.EndpointA.ChannelConfig.Version, path.EndpointB.ChannelConfig.Version, 277 ) 278 suite.Require().Error(err) 279 suite.Require().Equal("", version) 280 } 281 282 func (suite *InterchainAccountsTestSuite) TestOnChanOpenAck() { 283 var path *ibctesting.Path 284 285 testCases := []struct { 286 name string 287 malleate func() 288 expPass bool 289 }{ 290 { 291 "success", func() {}, true, 292 }, 293 { 294 "controller submodule disabled", func() { 295 suite.chainA.GetSimApp().ICAControllerKeeper.SetParams(suite.chainA.GetContext(), types.NewParams(false)) 296 }, false, 297 }, 298 { 299 "ICA OnChanOpenACK fails - invalid version", func() { 300 path.EndpointB.ChannelConfig.Version = "invalid|version" 301 }, false, 302 }, 303 { 304 "ICA auth module callback fails", func() { 305 suite.chainA.GetSimApp().ICAAuthModule.IBCApp.OnChanOpenAck = func( 306 ctx sdk.Context, portID, channelID string, counterpartyChannelID string, counterpartyVersion string, 307 ) error { 308 return fmt.Errorf("mock ica auth fails") 309 } 310 }, false, 311 }, 312 } 313 314 for _, tc := range testCases { 315 tc := tc 316 317 suite.Run(tc.name, func() { 318 suite.SetupTest() // reset 319 320 path = NewICAPath(suite.chainA, suite.chainB) 321 suite.coordinator.SetupConnections(path) 322 323 err := RegisterInterchainAccount(path.EndpointA, TestOwnerAddress) 324 suite.Require().NoError(err) 325 326 err = path.EndpointB.ChanOpenTry() 327 suite.Require().NoError(err) 328 329 tc.malleate() // malleate mutates test data 330 331 module, _, err := suite.chainA.GetSimApp().GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID) 332 suite.Require().NoError(err) 333 334 cbs, ok := suite.chainA.GetSimApp().GetIBCKeeper().Router.GetRoute(module) 335 suite.Require().True(ok) 336 337 err = cbs.OnChanOpenAck(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelID, path.EndpointB.ChannelConfig.Version) 338 339 if tc.expPass { 340 suite.Require().NoError(err) 341 } else { 342 suite.Require().Error(err) 343 } 344 }) 345 } 346 } 347 348 // Test initiating a ChanOpenConfirm using the controller chain instead of the host chain 349 // ChainA is the controller chain. ChainB is the host chain 350 // Sending a MsgChanOpenConfirm will never reach the application callback due to 351 // core IBC checks not passing, so a call to the application callback is also 352 // done directly. 353 func (suite *InterchainAccountsTestSuite) TestChanOpenConfirm() { 354 suite.SetupTest() // reset 355 path := NewICAPath(suite.chainA, suite.chainB) 356 suite.coordinator.SetupConnections(path) 357 358 err := RegisterInterchainAccount(path.EndpointA, TestOwnerAddress) 359 suite.Require().NoError(err) 360 361 err = path.EndpointB.ChanOpenTry() 362 suite.Require().NoError(err) 363 364 // chainB maliciously sets channel to OPEN 365 channel := channeltypes.NewChannel(channeltypes.OPEN, channeltypes.ORDERED, channeltypes.NewCounterparty(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID), []string{path.EndpointB.ConnectionID}, TestVersion) 366 suite.chainB.GetSimApp().GetIBCKeeper().ChannelKeeper.SetChannel(suite.chainB.GetContext(), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, channel) 367 368 // commit state changes so proof can be created 369 suite.chainB.Coordinator().CommitBlock(suite.chainB) 370 371 path.EndpointA.UpdateClient() 372 373 // query proof from ChainB 374 channelKey := host.ChannelKey(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID) 375 proofAck, proofHeight := path.EndpointB.Chain.QueryProof(channelKey) 376 377 // use chainA (controller) for ChanOpenConfirm 378 msg := channeltypes.NewMsgChannelOpenConfirm(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, proofAck, proofHeight, icatypes.ModuleName) 379 handler := suite.chainA.GetSimApp().MsgServiceRouter().HandlerWithMsg(msg) 380 _, err = handler(suite.chainA.GetContext(), msg) 381 382 suite.Require().Error(err) 383 384 // call application callback directly 385 module, _, err := suite.chainA.GetSimApp().GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID) 386 suite.Require().NoError(err) 387 388 cbs, ok := suite.chainA.GetSimApp().GetIBCKeeper().Router.GetRoute(module) 389 suite.Require().True(ok) 390 391 err = cbs.OnChanOpenConfirm( 392 suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, 393 ) 394 suite.Require().Error(err) 395 } 396 397 // OnChanCloseInit on controller (chainA) 398 func (suite *InterchainAccountsTestSuite) TestOnChanCloseInit() { 399 path := NewICAPath(suite.chainA, suite.chainB) 400 suite.coordinator.SetupConnections(path) 401 402 err := SetupICAPath(path, TestOwnerAddress) 403 suite.Require().NoError(err) 404 405 module, _, err := suite.chainA.GetSimApp().GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID) 406 suite.Require().NoError(err) 407 408 cbs, ok := suite.chainA.GetSimApp().GetIBCKeeper().Router.GetRoute(module) 409 suite.Require().True(ok) 410 411 err = cbs.OnChanCloseInit( 412 suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, 413 ) 414 415 suite.Require().Error(err) 416 } 417 418 func (suite *InterchainAccountsTestSuite) TestOnChanCloseConfirm() { 419 var path *ibctesting.Path 420 421 testCases := []struct { 422 name string 423 malleate func() 424 expPass bool 425 }{ 426 { 427 "success", func() {}, true, 428 }, 429 } 430 431 for _, tc := range testCases { 432 suite.Run(tc.name, func() { 433 suite.SetupTest() // reset 434 435 path = NewICAPath(suite.chainA, suite.chainB) 436 suite.coordinator.SetupConnections(path) 437 438 err := SetupICAPath(path, TestOwnerAddress) 439 suite.Require().NoError(err) 440 441 tc.malleate() // malleate mutates test data 442 module, _, err := suite.chainA.GetSimApp().GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID) 443 suite.Require().NoError(err) 444 445 cbs, ok := suite.chainA.GetSimApp().GetIBCKeeper().Router.GetRoute(module) 446 suite.Require().True(ok) 447 448 err = cbs.OnChanCloseConfirm( 449 suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 450 451 if tc.expPass { 452 suite.Require().NoError(err) 453 } else { 454 suite.Require().Error(err) 455 } 456 }) 457 } 458 } 459 460 func (suite *InterchainAccountsTestSuite) TestOnRecvPacket() { 461 testCases := []struct { 462 name string 463 malleate func() 464 expPass bool 465 }{ 466 { 467 "ICA OnRecvPacket fails with ErrInvalidChannelFlow", func() {}, false, 468 }, 469 } 470 471 for _, tc := range testCases { 472 tc := tc 473 474 suite.Run(tc.name, func() { 475 suite.SetupTest() // reset 476 477 path := NewICAPath(suite.chainA, suite.chainB) 478 suite.coordinator.SetupConnections(path) 479 480 err := SetupICAPath(path, TestOwnerAddress) 481 suite.Require().NoError(err) 482 483 tc.malleate() // malleate mutates test data 484 485 module, _, err := suite.chainA.GetSimApp().GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID) 486 suite.Require().NoError(err) 487 488 cbs, ok := suite.chainA.GetSimApp().GetIBCKeeper().Router.GetRoute(module) 489 suite.Require().True(ok) 490 491 packet := channeltypes.NewPacket( 492 []byte("empty packet data"), 493 suite.chainB.SenderAccount().GetSequence(), 494 path.EndpointB.ChannelConfig.PortID, 495 path.EndpointB.ChannelID, 496 path.EndpointA.ChannelConfig.PortID, 497 path.EndpointA.ChannelID, 498 clienttypes.NewHeight(0, 100), 499 0, 500 ) 501 502 ack := cbs.OnRecvPacket(suite.chainA.GetContext(), packet, TestAccAddress) 503 suite.Require().Equal(tc.expPass, ack.Success()) 504 }) 505 } 506 } 507 508 func (suite *InterchainAccountsTestSuite) TestOnAcknowledgementPacket() { 509 var path *ibctesting.Path 510 511 testCases := []struct { 512 msg string 513 malleate func() 514 expPass bool 515 }{ 516 { 517 "success", 518 func() {}, 519 true, 520 }, 521 { 522 "controller submodule disabled", func() { 523 suite.chainA.GetSimApp().ICAControllerKeeper.SetParams(suite.chainA.GetContext(), types.NewParams(false)) 524 }, false, 525 }, 526 { 527 "ICA auth module callback fails", func() { 528 suite.chainA.GetSimApp().ICAAuthModule.IBCApp.OnAcknowledgementPacket = func( 529 ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress, 530 ) error { 531 return fmt.Errorf("mock ica auth fails") 532 } 533 }, false, 534 }, 535 } 536 537 for _, tc := range testCases { 538 suite.Run(tc.msg, func() { 539 suite.SetupTest() // reset 540 541 path = NewICAPath(suite.chainA, suite.chainB) 542 suite.coordinator.SetupConnections(path) 543 544 err := SetupICAPath(path, TestOwnerAddress) 545 suite.Require().NoError(err) 546 547 packet := channeltypes.NewPacket( 548 []byte("empty packet data"), 549 suite.chainA.SenderAccount().GetSequence(), 550 path.EndpointA.ChannelConfig.PortID, 551 path.EndpointA.ChannelID, 552 path.EndpointB.ChannelConfig.PortID, 553 path.EndpointB.ChannelID, 554 clienttypes.NewHeight(0, 100), 555 0, 556 ) 557 558 tc.malleate() // malleate mutates test data 559 560 module, _, err := suite.chainA.GetSimApp().GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID) 561 suite.Require().NoError(err) 562 563 cbs, ok := suite.chainA.GetSimApp().GetIBCKeeper().Router.GetRoute(module) 564 suite.Require().True(ok) 565 566 err = cbs.OnAcknowledgementPacket(suite.chainA.GetContext(), packet, []byte("ack"), nil) 567 568 if tc.expPass { 569 suite.Require().NoError(err) 570 } else { 571 suite.Require().Error(err) 572 } 573 }) 574 } 575 } 576 577 func (suite *InterchainAccountsTestSuite) TestOnTimeoutPacket() { 578 var path *ibctesting.Path 579 580 testCases := []struct { 581 msg string 582 malleate func() 583 expPass bool 584 }{ 585 { 586 "success", 587 func() {}, 588 true, 589 }, 590 { 591 "controller submodule disabled", func() { 592 suite.chainA.GetSimApp().ICAControllerKeeper.SetParams(suite.chainA.GetContext(), types.NewParams(false)) 593 }, false, 594 }, 595 { 596 "ICA auth module callback fails", func() { 597 suite.chainA.GetSimApp().ICAAuthModule.IBCApp.OnTimeoutPacket = func( 598 ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, 599 ) error { 600 return fmt.Errorf("mock ica auth fails") 601 } 602 }, false, 603 }, 604 } 605 606 for _, tc := range testCases { 607 suite.Run(tc.msg, func() { 608 suite.SetupTest() // reset 609 610 path = NewICAPath(suite.chainA, suite.chainB) 611 suite.coordinator.SetupConnections(path) 612 613 err := SetupICAPath(path, TestOwnerAddress) 614 suite.Require().NoError(err) 615 616 packet := channeltypes.NewPacket( 617 []byte("empty packet data"), 618 suite.chainA.SenderAccount().GetSequence(), 619 path.EndpointA.ChannelConfig.PortID, 620 path.EndpointA.ChannelID, 621 path.EndpointB.ChannelConfig.PortID, 622 path.EndpointB.ChannelID, 623 clienttypes.NewHeight(0, 100), 624 0, 625 ) 626 627 tc.malleate() // malleate mutates test data 628 629 module, _, err := suite.chainA.GetSimApp().GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID) 630 suite.Require().NoError(err) 631 632 cbs, ok := suite.chainA.GetSimApp().GetIBCKeeper().Router.GetRoute(module) 633 suite.Require().True(ok) 634 635 err = cbs.OnTimeoutPacket(suite.chainA.GetContext(), packet, nil) 636 637 if tc.expPass { 638 suite.Require().NoError(err) 639 } else { 640 suite.Require().Error(err) 641 } 642 }) 643 } 644 } 645 646 func (suite *InterchainAccountsTestSuite) TestSingleHostMultipleControllers() { 647 var ( 648 pathAToB *ibctesting.Path 649 pathCToB *ibctesting.Path 650 ) 651 652 testCases := []struct { 653 msg string 654 malleate func() 655 expPass bool 656 }{ 657 { 658 "success", 659 func() {}, 660 true, 661 }, 662 } 663 664 for _, tc := range testCases { 665 suite.Run(tc.msg, func() { 666 suite.SetupTest() // reset 667 668 // Setup a new path from A(controller) -> B(host) 669 pathAToB = NewICAPath(suite.chainA, suite.chainB) 670 suite.coordinator.SetupConnections(pathAToB) 671 672 err := SetupICAPath(pathAToB, TestOwnerAddress) 673 suite.Require().NoError(err) 674 675 // Setup a new path from C(controller) -> B(host) 676 pathCToB = NewICAPath(suite.chainC, suite.chainB) 677 suite.coordinator.SetupConnections(pathCToB) 678 679 // NOTE: Here the version metadata is overridden to include to the next host connection sequence (i.e. chainB's connection to chainC) 680 // SetupICAPath() will set endpoint.ChannelConfig.Version to TestVersion 681 TestVersion = string(icatypes.ModuleCdc.MustMarshalJSON(&icatypes.Metadata{ 682 Version: icatypes.Version, 683 ControllerConnectionId: pathCToB.EndpointA.ConnectionID, 684 HostConnectionId: pathCToB.EndpointB.ConnectionID, 685 Encoding: icatypes.EncodingProtobuf, 686 TxType: icatypes.TxTypeSDKMultiMsg, 687 })) 688 689 err = SetupICAPath(pathCToB, TestOwnerAddress) 690 suite.Require().NoError(err) 691 692 tc.malleate() // malleate mutates test data 693 694 accAddressChainA, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), pathAToB.EndpointB.ConnectionID, pathAToB.EndpointA.ChannelConfig.PortID) 695 suite.Require().True(found) 696 697 accAddressChainC, found := suite.chainB.GetSimApp().ICAHostKeeper.GetInterchainAccountAddress(suite.chainB.GetContext(), pathCToB.EndpointB.ConnectionID, pathCToB.EndpointA.ChannelConfig.PortID) 698 suite.Require().True(found) 699 700 suite.Require().NotEqual(accAddressChainA, accAddressChainC) 701 702 chainAChannelID, found := suite.chainB.GetSimApp().ICAHostKeeper.GetActiveChannelID(suite.chainB.GetContext(), pathAToB.EndpointB.ConnectionID, pathAToB.EndpointA.ChannelConfig.PortID) 703 suite.Require().True(found) 704 705 chainCChannelID, found := suite.chainB.GetSimApp().ICAHostKeeper.GetActiveChannelID(suite.chainB.GetContext(), pathCToB.EndpointB.ConnectionID, pathCToB.EndpointA.ChannelConfig.PortID) 706 suite.Require().True(found) 707 708 suite.Require().NotEqual(chainAChannelID, chainCChannelID) 709 }) 710 } 711 } 712 713 func (suite *InterchainAccountsTestSuite) TestGetAppVersion() { 714 path := NewICAPath(suite.chainA, suite.chainB) 715 suite.coordinator.SetupConnections(path) 716 717 err := SetupICAPath(path, TestOwnerAddress) 718 suite.Require().NoError(err) 719 720 module, _, err := suite.chainA.GetSimApp().GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID) 721 suite.Require().NoError(err) 722 723 cbs, ok := suite.chainA.GetSimApp().GetIBCKeeper().Router.GetRoute(module) 724 suite.Require().True(ok) 725 726 controllerStack := cbs.(fee.IBCMiddleware) 727 appVersion, found := controllerStack.GetAppVersion(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) 728 suite.Require().True(found) 729 suite.Require().Equal(path.EndpointA.ChannelConfig.Version, appVersion) 730 }