github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/02-client/keeper/client_test.go (about) 1 package keeper_test 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "math" 7 "time" 8 9 // tmtypes "github.com/tendermint/tendermint/types" 10 11 // upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" 12 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 13 clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 14 commitmenttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/23-commitment/types" 15 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported" 16 ibctmtypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/07-tendermint/types" 17 localhosttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/09-localhost/types" 18 ibctesting "github.com/fibonacci-chain/fbc/libs/ibc-go/testing" 19 ) 20 21 const ( 22 IBCHeight = math.MaxInt64 / 2 23 ) 24 25 func (suite *KeeperTestSuite) TestCreateClient() { 26 cases := []struct { 27 msg string 28 clientState exported.ClientState 29 expPass bool 30 }{ 31 {"success", ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), true}, 32 {"client type not supported", localhosttypes.NewClientState(testChainID, clienttypes.NewHeight(0, 1)), false}, 33 } 34 35 for i, tc := range cases { 36 37 clientID, err := suite.keeper.CreateClient(suite.ctx, tc.clientState, suite.consensusState) 38 if tc.expPass { 39 suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.msg) 40 suite.Require().NotNil(clientID, "valid test case %d failed: %s", i, tc.msg) 41 } else { 42 suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.msg) 43 suite.Require().Equal("", clientID, "invalid test case %d passed: %s", i, tc.msg) 44 } 45 } 46 } 47 48 func (suite *KeeperTestSuite) TestUpdateClientTendermint() { 49 var ( 50 path *ibctesting.Path 51 updateHeader *ibctmtypes.Header 52 ) 53 54 // Must create header creation functions since suite.header gets recreated on each test case 55 createFutureUpdateFn := func(trustedHeight clienttypes.Height) *ibctmtypes.Header { 56 header, err := suite.chainA.ConstructUpdateTMClientHeaderWithTrustedHeight(path.EndpointB.Chain, path.EndpointA.ClientID, trustedHeight) 57 suite.Require().NoError(err) 58 return header 59 } 60 createPastUpdateFn := func(fillHeight, trustedHeight clienttypes.Height) *ibctmtypes.Header { 61 consState, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID, trustedHeight) 62 suite.Require().True(found) 63 64 return suite.chainB.CreateTMClientHeader(suite.chainB.ChainID(), int64(fillHeight.RevisionHeight), trustedHeight, consState.(*ibctmtypes.ConsensusState).Timestamp.Add(time.Second*5), 65 suite.chainB.Vals(), suite.chainB.Vals(), suite.chainB.Signers()) 66 } 67 68 cases := []struct { 69 name string 70 malleate func() 71 expPass bool 72 expFreeze bool 73 }{ 74 {"valid update", func() { 75 clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState) 76 trustHeight := clientState.GetLatestHeight().(types.Height) 77 78 // store intermediate consensus state to check that trustedHeight does not need to be highest consensus state before header height 79 path.EndpointA.UpdateClient() 80 81 updateHeader = createFutureUpdateFn(trustHeight) 82 }, true, false}, 83 {"valid past update", func() { 84 clientState := path.EndpointA.GetClientState() 85 trustedHeight := clientState.GetLatestHeight().(types.Height) 86 87 currHeight := suite.chainB.CurrentHeader().Height 88 fillHeight := types.NewHeight(clientState.GetLatestHeight().GetRevisionNumber(), uint64(currHeight)) 89 90 // commit a couple blocks to allow client to fill in gaps 91 suite.coordinator.CommitBlock(suite.chainB) // this height is not filled in yet 92 suite.coordinator.CommitBlock(suite.chainB) // this height is filled in by the update below 93 94 path.EndpointA.UpdateClient() 95 96 // ensure fill height not set 97 _, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID, fillHeight) 98 suite.Require().False(found) 99 100 // updateHeader will fill in consensus state between prevConsState and suite.consState 101 // clientState should not be updated 102 updateHeader = createPastUpdateFn(fillHeight, trustedHeight) 103 }, true, false}, 104 {"valid duplicate update", func() { 105 clientID := path.EndpointA.ClientID 106 107 height1 := types.NewHeight(0, 1) 108 109 // store previous consensus state 110 prevConsState := &ibctmtypes.ConsensusState{ 111 Timestamp: suite.past, 112 NextValidatorsHash: suite.chainB.Vals().Hash(IBCHeight), 113 } 114 suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientID, height1, prevConsState) 115 116 height5 := types.NewHeight(0, 5) 117 // store next consensus state to check that trustedHeight does not need to be hightest consensus state before header height 118 nextConsState := &ibctmtypes.ConsensusState{ 119 Timestamp: suite.past.Add(time.Minute), 120 NextValidatorsHash: suite.chainB.Vals().Hash(IBCHeight), 121 } 122 suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientID, height5, nextConsState) 123 124 height3 := types.NewHeight(0, 3) 125 // updateHeader will fill in consensus state between prevConsState and suite.consState 126 // clientState should not be updated 127 updateHeader = createPastUpdateFn(height3, height1) 128 // set updateHeader's consensus state in store to create duplicate UpdateClient scenario 129 suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientConsensusState(suite.chainA.GetContext(), clientID, updateHeader.GetHeight(), updateHeader.ConsensusState()) 130 }, true, false}, 131 {"client state not found", func() { 132 updateHeader = createFutureUpdateFn(path.EndpointA.GetClientState().GetLatestHeight().(types.Height)) 133 134 path.EndpointA.ClientID = ibctesting.InvalidID 135 }, false, false}, 136 {"consensus state not found", func() { 137 clientState := path.EndpointA.GetClientState() 138 tmClient, ok := clientState.(*ibctmtypes.ClientState) 139 suite.Require().True(ok) 140 tmClient.LatestHeight = tmClient.LatestHeight.Increment().(types.Height) 141 142 suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, clientState) 143 updateHeader = createFutureUpdateFn(clientState.GetLatestHeight().(types.Height)) 144 }, false, false}, 145 {"client is not active", func() { 146 clientState := path.EndpointA.GetClientState().(*ibctmtypes.ClientState) 147 clientState.FrozenHeight = types.NewHeight(0, 1) 148 suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, clientState) 149 updateHeader = createFutureUpdateFn(clientState.GetLatestHeight().(types.Height)) 150 }, false, false}, 151 {"invalid header", func() { 152 updateHeader = createFutureUpdateFn(path.EndpointA.GetClientState().GetLatestHeight().(types.Height)) 153 updateHeader.TrustedHeight = updateHeader.TrustedHeight.Increment().(types.Height) 154 }, false, false}, 155 } 156 157 for _, tc := range cases { 158 tc := tc 159 suite.Run(fmt.Sprintf("Case %s", tc.name), func() { 160 suite.SetupTest() 161 path = ibctesting.NewPath(suite.chainA, suite.chainB) 162 suite.coordinator.SetupClients(path) 163 164 tc.malleate() 165 166 var clientState exported.ClientState 167 if tc.expPass { 168 clientState = path.EndpointA.GetClientState() 169 } 170 171 err := suite.chainA.App().GetIBCKeeper().ClientKeeper.UpdateClient(suite.chainA.GetContext(), path.EndpointA.ClientID, updateHeader) 172 173 if tc.expPass { 174 suite.Require().NoError(err, err) 175 176 newClientState := path.EndpointA.GetClientState() 177 178 if tc.expFreeze { 179 suite.Require().True(!newClientState.(*ibctmtypes.ClientState).FrozenHeight.IsZero(), "client did not freeze after conflicting header was submitted to UpdateClient") 180 } else { 181 expConsensusState := &ibctmtypes.ConsensusState{ 182 Timestamp: updateHeader.GetTime(), 183 Root: commitmenttypes.NewMerkleRoot(updateHeader.Header.GetAppHash()), 184 NextValidatorsHash: updateHeader.Header.NextValidatorsHash, 185 } 186 187 consensusState, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientConsensusState(suite.chainA.GetContext(), path.EndpointA.ClientID, updateHeader.GetHeight()) 188 suite.Require().True(found) 189 190 // Determine if clientState should be updated or not 191 if updateHeader.GetHeight().GT(clientState.GetLatestHeight()) { 192 // Header Height is greater than clientState latest Height, clientState should be updated with header.GetHeight() 193 suite.Require().Equal(updateHeader.GetHeight(), newClientState.GetLatestHeight(), "clientstate height did not update") 194 } else { 195 // Update will add past consensus state, clientState should not be updated at all 196 suite.Require().Equal(clientState.GetLatestHeight(), newClientState.GetLatestHeight(), "client state height updated for past header") 197 } 198 199 suite.Require().NoError(err) 200 suite.Require().Equal(expConsensusState, consensusState, "consensus state should have been updated on case %s", tc.name) 201 } 202 } else { 203 suite.Require().Error(err) 204 } 205 }) 206 } 207 } 208 209 func (suite *KeeperTestSuite) TestUpdateClientLocalhost() { 210 revision := types.ParseChainID(suite.chainA.ChainID()) 211 chainACtx := suite.chainA.GetContext() 212 var localhostClient exported.ClientState = localhosttypes.NewClientState(suite.chainA.ChainID(), types.NewHeight(revision, uint64(chainACtx.BlockHeight()))) 213 214 ctx := suite.chainA.GetContext().WithBlockHeight(chainACtx.BlockHeight() + 1) 215 err := suite.chainA.App().GetIBCKeeper().ClientKeeper.UpdateClient(ctx, exported.Localhost, nil) 216 suite.Require().NoError(err) 217 218 clientState, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientState(ctx, exported.Localhost) 219 suite.Require().True(found) 220 suite.Require().Equal(localhostClient.GetLatestHeight().(types.Height).Increment(), clientState.GetLatestHeight()) 221 } 222 223 // todo add upgrade client 224 func (suite *KeeperTestSuite) testUpgradeClient() { 225 // var ( 226 // path *ibctesting.Path 227 // upgradedClient exported.ClientState 228 // upgradedConsState exported.ConsensusState 229 // lastHeight exported.Height 230 // proofUpgradedClient, proofUpgradedConsState []byte 231 // upgradedClientBz, upgradedConsStateBz []byte 232 // err error 233 // ) 234 // 235 // testCases := []struct { 236 // name string 237 // setup func() 238 // expPass bool 239 // }{ 240 // { 241 // name: "successful upgrade", 242 // setup: func() { 243 // tmpCtx := suite.chainB.GetContext() 244 // // last Height is at next block 245 // lastHeight = clienttypes.NewHeight(0, uint64(tmpCtx.BlockHeight()+1)) 246 // 247 // // zero custom fields and store in upgrade store 248 // suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) 249 // suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) 250 // 251 // // commit upgrade store changes and update clients 252 // 253 // suite.coordinator.CommitBlock(suite.chainB) 254 // err := path.EndpointA.UpdateClient() 255 // suite.Require().NoError(err) 256 // 257 // cs, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) 258 // suite.Require().True(found) 259 // 260 // proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) 261 // proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) 262 // }, 263 // expPass: true, 264 // }, 265 // { 266 // name: "client state not found", 267 // setup: func() { 268 // // last Height is at next block 269 // tmpCtx := suite.chainB.GetContext() 270 // lastHeight = clienttypes.NewHeight(0, uint64(tmpCtx.BlockHeight()+1)) 271 // 272 // // zero custom fields and store in upgrade store 273 // suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) 274 // suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) 275 // 276 // // commit upgrade store changes and update clients 277 // 278 // suite.coordinator.CommitBlock(suite.chainB) 279 // err := path.EndpointA.UpdateClient() 280 // suite.Require().NoError(err) 281 // 282 // cs, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) 283 // suite.Require().True(found) 284 // 285 // proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) 286 // proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) 287 // 288 // path.EndpointA.ClientID = "wrongclientid" 289 // }, 290 // expPass: false, 291 // }, 292 // { 293 // name: "client state is not active", 294 // setup: func() { 295 // // client is frozen 296 // 297 // tmpCtx := suite.chainB.GetContext() 298 // // last Height is at next block 299 // lastHeight = clienttypes.NewHeight(0, uint64(tmpCtx.BlockHeight()+1)) 300 // 301 // // zero custom fields and store in upgrade store 302 // suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) 303 // suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) 304 // 305 // // commit upgrade store changes and update clients 306 // 307 // suite.coordinator.CommitBlock(suite.chainB) 308 // err := path.EndpointA.UpdateClient() 309 // suite.Require().NoError(err) 310 // 311 // cs, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) 312 // suite.Require().True(found) 313 // 314 // proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) 315 // proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) 316 // 317 // // set frozen client in store 318 // tmClient, ok := cs.(*ibctmtypes.ClientState) 319 // suite.Require().True(ok) 320 // tmClient.FrozenHeight = types.NewHeight(0, 1) 321 // suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID, tmClient) 322 // }, 323 // expPass: false, 324 // }, 325 // { 326 // name: "tendermint client VerifyUpgrade fails", 327 // setup: func() { 328 // // last Height is at next block 329 // tmpCtx := suite.chainB.GetContext() 330 // lastHeight = clienttypes.NewHeight(0, uint64(tmpCtx.BlockHeight()+1)) 331 // 332 // // zero custom fields and store in upgrade store 333 // suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedClient(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedClientBz) 334 // suite.chainB.GetSimApp().UpgradeKeeper.SetUpgradedConsensusState(suite.chainB.GetContext(), int64(lastHeight.GetRevisionHeight()), upgradedConsStateBz) 335 // 336 // // change upgradedClient client-specified parameters 337 // upgradedClient = ibctmtypes.NewClientState("wrongchainID", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, true, true) 338 // 339 // suite.coordinator.CommitBlock(suite.chainB) 340 // err := path.EndpointA.UpdateClient() 341 // suite.Require().NoError(err) 342 // 343 // cs, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), path.EndpointA.ClientID) 344 // suite.Require().True(found) 345 // 346 // proofUpgradedClient, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedClientKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) 347 // proofUpgradedConsState, _ = suite.chainB.QueryUpgradeProof(upgradetypes.UpgradedConsStateKey(int64(lastHeight.GetRevisionHeight())), cs.GetLatestHeight().GetRevisionHeight()) 348 // }, 349 // expPass: false, 350 // }, 351 // } 352 // 353 // for _, tc := range testCases { 354 // tc := tc 355 // path = ibctesting.NewPath(suite.chainA, suite.chainB) 356 // suite.coordinator.SetupClients(path) 357 // upgradedClient = ibctmtypes.NewClientState("newChainId-1", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+trustingPeriod, maxClockDrift, newClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 358 // upgradedClient = upgradedClient.ZeroCustomFields() 359 // upgradedClientBz, err = types.MarshalClientState(suite.chainA.App().AppCodec(), upgradedClient) 360 // suite.Require().NoError(err) 361 // 362 // upgradedConsState = &ibctmtypes.ConsensusState{ 363 // NextValidatorsHash: []byte("nextValsHash"), 364 // } 365 // upgradedConsStateBz, err = types.MarshalConsensusState(suite.chainA.App().AppCodec(), upgradedConsState) 366 // suite.Require().NoError(err) 367 // 368 // tc.setup() 369 // 370 // // Call ZeroCustomFields on upgraded clients to clear any client-chosen parameters in test-case upgradedClient 371 // upgradedClient = upgradedClient.ZeroCustomFields() 372 // 373 // err = suite.chainA.App().GetIBCKeeper().ClientKeeper.UpgradeClient(suite.chainA.GetContext(), path.EndpointA.ClientID, upgradedClient, upgradedConsState, proofUpgradedClient, proofUpgradedConsState) 374 // 375 // if tc.expPass { 376 // suite.Require().NoError(err, "verify upgrade failed on valid case: %s", tc.name) 377 // } else { 378 // suite.Require().Error(err, "verify upgrade passed on invalid case: %s", tc.name) 379 // } 380 // } 381 // 382 //} 383 // 384 //func (suite *KeeperTestSuite) TestCheckMisbehaviourAndUpdateState() { 385 // var ( 386 // clientID string 387 // err error 388 // ) 389 // 390 // altPrivVal := ibctestingmock.NewPV() 391 // altPubKey, err := altPrivVal.GetPubKey() 392 // suite.Require().NoError(err) 393 // altVal := tmtypes.NewValidator(altPubKey, 4) 394 // 395 // // Set valSet here with suite.valSet so it doesn't get reset on each testcase 396 // valSet := suite.valSet 397 // valsHash := valSet.Hash() 398 // 399 // // Create bothValSet with both suite validator and altVal 400 // bothValSet := tmtypes.NewValidatorSet(append(suite.valSet.Validators, altVal)) 401 // bothValsHash := bothValSet.Hash() 402 // // Create alternative validator set with only altVal 403 // altValSet := tmtypes.NewValidatorSet([]*tmtypes.Validator{altVal}) 404 // 405 // // Create signer array and ensure it is in same order as bothValSet 406 // _, suiteVal := suite.valSet.GetByIndex(0) 407 // bothSigners := ibctesting.CreateSortedSignerArray(altPrivVal, suite.privVal, altVal, suiteVal) 408 // 409 // altSigners := []tmtypes.PrivValidator{altPrivVal} 410 // 411 // // Create valid Misbehaviour by making a duplicate header that signs over different block time 412 // altTime := suite.ctx.BlockTime().Add(time.Minute) 413 // 414 // heightPlus3 := types.NewHeight(0, height+3) 415 // heightPlus5 := types.NewHeight(0, height+5) 416 // 417 // testCases := []struct { 418 // name string 419 // misbehaviour *ibctmtypes.Misbehaviour 420 // malleate func() error 421 // expPass bool 422 // }{ 423 // { 424 // "trusting period misbehavior should pass", 425 // &ibctmtypes.Misbehaviour{ 426 // Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, bothSigners), 427 // Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), 428 // ClientId: clientID, 429 // }, 430 // func() error { 431 // suite.consensusState.NextValidatorsHash = bothValsHash 432 // clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 433 // clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) 434 // 435 // return err 436 // }, 437 // true, 438 // }, 439 // { 440 // "time misbehavior should pass", 441 // &ibctmtypes.Misbehaviour{ 442 // Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+5), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), 443 // Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, bothSigners), 444 // ClientId: clientID, 445 // }, 446 // func() error { 447 // suite.consensusState.NextValidatorsHash = bothValsHash 448 // clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 449 // clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) 450 // 451 // return err 452 // }, 453 // true, 454 // }, 455 // { 456 // "misbehavior at later height should pass", 457 // &ibctmtypes.Misbehaviour{ 458 // Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), testClientHeight, altTime, bothValSet, valSet, bothSigners), 459 // Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), testClientHeight, suite.ctx.BlockTime(), bothValSet, valSet, bothSigners), 460 // ClientId: clientID, 461 // }, 462 // func() error { 463 // suite.consensusState.NextValidatorsHash = valsHash 464 // clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 465 // clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) 466 // 467 // // store intermediate consensus state to check that trustedHeight does not need to be highest consensus state before header height 468 // intermediateConsState := &ibctmtypes.ConsensusState{ 469 // Timestamp: suite.now.Add(time.Minute), 470 // NextValidatorsHash: suite.chainB.Vals().Hash(), 471 // } 472 // suite.keeper.SetClientConsensusState(suite.ctx, clientID, heightPlus3, intermediateConsState) 473 // 474 // clientState.LatestHeight = heightPlus3 475 // suite.keeper.SetClientState(suite.ctx, clientID, clientState) 476 // 477 // return err 478 // }, 479 // true, 480 // }, 481 // { 482 // "misbehavior at later height with different trusted heights should pass", 483 // &ibctmtypes.Misbehaviour{ 484 // Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), testClientHeight, altTime, bothValSet, valSet, bothSigners), 485 // Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), heightPlus3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), 486 // ClientId: clientID, 487 // }, 488 // func() error { 489 // suite.consensusState.NextValidatorsHash = valsHash 490 // clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 491 // clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) 492 // 493 // // store trusted consensus state for Header2 494 // intermediateConsState := &ibctmtypes.ConsensusState{ 495 // Timestamp: suite.now.Add(time.Minute), 496 // NextValidatorsHash: bothValsHash, 497 // } 498 // suite.keeper.SetClientConsensusState(suite.ctx, clientID, heightPlus3, intermediateConsState) 499 // 500 // clientState.LatestHeight = heightPlus3 501 // suite.keeper.SetClientState(suite.ctx, clientID, clientState) 502 // 503 // return err 504 // }, 505 // true, 506 // }, 507 // { 508 // "misbehavior ValidateBasic fails: misbehaviour height is at same height as trusted height", 509 // &ibctmtypes.Misbehaviour{ 510 // Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, altTime, bothValSet, bothValSet, bothSigners), 511 // Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), 512 // ClientId: clientID, 513 // }, 514 // func() error { 515 // suite.consensusState.NextValidatorsHash = bothValsHash 516 // clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 517 // clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) 518 // 519 // return err 520 // }, 521 // false, 522 // }, 523 // { 524 // "trusted ConsensusState1 not found", 525 // &ibctmtypes.Misbehaviour{ 526 // Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), heightPlus3, altTime, bothValSet, bothValSet, bothSigners), 527 // Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), testClientHeight, suite.ctx.BlockTime(), bothValSet, valSet, bothSigners), 528 // ClientId: clientID, 529 // }, 530 // func() error { 531 // suite.consensusState.NextValidatorsHash = valsHash 532 // clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 533 // clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) 534 // // intermediate consensus state at height + 3 is not created 535 // return err 536 // }, 537 // false, 538 // }, 539 // { 540 // "trusted ConsensusState2 not found", 541 // &ibctmtypes.Misbehaviour{ 542 // Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), testClientHeight, altTime, bothValSet, valSet, bothSigners), 543 // Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(heightPlus5.RevisionHeight+1), heightPlus3, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), 544 // ClientId: clientID, 545 // }, 546 // func() error { 547 // suite.consensusState.NextValidatorsHash = valsHash 548 // clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 549 // clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) 550 // // intermediate consensus state at height + 3 is not created 551 // return err 552 // }, 553 // false, 554 // }, 555 // { 556 // "client state not found", 557 // &ibctmtypes.Misbehaviour{}, 558 // func() error { return nil }, 559 // false, 560 // }, 561 // { 562 // "client already is not active - client is frozen", 563 // &ibctmtypes.Misbehaviour{ 564 // Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, bothSigners), 565 // Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, suite.ctx.BlockTime(), bothValSet, bothValSet, bothSigners), 566 // ClientId: clientID, 567 // }, 568 // func() error { 569 // suite.consensusState.NextValidatorsHash = bothValsHash 570 // clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 571 // clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) 572 // 573 // clientState.FrozenHeight = types.NewHeight(0, 1) 574 // suite.keeper.SetClientState(suite.ctx, clientID, clientState) 575 // 576 // return err 577 // }, 578 // false, 579 // }, 580 // { 581 // "misbehaviour check failed", 582 // &ibctmtypes.Misbehaviour{ 583 // Header1: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, altTime, bothValSet, bothValSet, bothSigners), 584 // Header2: suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight+1), testClientHeight, suite.ctx.BlockTime(), altValSet, bothValSet, altSigners), 585 // ClientId: clientID, 586 // }, 587 // func() error { 588 // clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 589 // if err != nil { 590 // return err 591 // } 592 // clientID, err = suite.keeper.CreateClient(suite.ctx, clientState, suite.consensusState) 593 // 594 // return err 595 // }, 596 // false, 597 // }, 598 // } 599 // 600 // for i, tc := range testCases { 601 // tc := tc 602 // i := i 603 // 604 // suite.Run(tc.name, func() { 605 // suite.SetupTest() // reset 606 // clientID = testClientID // must be explicitly changed 607 // 608 // err := tc.malleate() 609 // suite.Require().NoError(err) 610 // 611 // tc.misbehaviour.ClientId = clientID 612 // 613 // err = suite.keeper.CheckMisbehaviourAndUpdateState(suite.ctx, tc.misbehaviour) 614 // 615 // if tc.expPass { 616 // suite.Require().NoError(err, "valid test case %d failed: %s", i, tc.name) 617 // 618 // clientState, found := suite.keeper.GetClientState(suite.ctx, clientID) 619 // suite.Require().True(found, "valid test case %d failed: %s", i, tc.name) 620 // suite.Require().True(!clientState.(*ibctmtypes.ClientState).FrozenHeight.IsZero(), "valid test case %d failed: %s", i, tc.name) 621 // } else { 622 // suite.Require().Error(err, "invalid test case %d passed: %s", i, tc.name) 623 // } 624 // }) 625 // } 626 } 627 628 func (suite *KeeperTestSuite) TestUpdateClientEventEmission() { 629 path := ibctesting.NewPath(suite.chainA, suite.chainB) 630 suite.coordinator.SetupClients(path) 631 header, err := suite.chainA.ConstructUpdateTMClientHeader(suite.chainB, path.EndpointA.ClientID) 632 suite.Require().NoError(err) 633 634 msg, err := clienttypes.NewMsgUpdateClient( 635 path.EndpointA.ClientID, header, 636 suite.chainA.SenderAccount().GetAddress(), 637 ) 638 639 result, err := suite.chainA.SendMsgs(msg) 640 suite.Require().NoError(err) 641 // first event type is "message", followed by 3 "tx" events in ante 642 //todo why 5, 2nd is update 643 updateEvent := result.Events[1] 644 suite.Require().Equal(clienttypes.EventTypeUpdateClient, updateEvent.Type) 645 646 // use a boolean to ensure the update event contains the header 647 contains := false 648 for _, attr := range updateEvent.Attributes { 649 if string(attr.Key) == clienttypes.AttributeKeyHeader { 650 contains = true 651 652 bz, err := hex.DecodeString(string(attr.Value)) 653 suite.Require().NoError(err) 654 655 // emittedHeader, err := types.UnmarshalHeader(suite.chainA.App().AppCodec(), bz) 656 emittedHeader, err := types.UnmarshalHeader(suite.chainA.App().AppCodec().GetProtocMarshal(), bz) 657 suite.Require().NoError(err) 658 suite.Require().Equal(header, emittedHeader) 659 } 660 661 } 662 suite.Require().True(contains) 663 664 }