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