github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/02-client/keeper/keeper_test.go (about) 1 package keeper_test 2 3 import ( 4 "math/rand" 5 "testing" 6 "time" 7 8 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 9 tmproto "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types" 10 stakingtypes "github.com/fibonacci-chain/fbc/x/staking/types" 11 12 tmbytes "github.com/fibonacci-chain/fbc/libs/tendermint/libs/bytes" 13 // tmproto "github.com/fibonacci-chain/fbc/libs/tendermint/proto/tendermint/types" 14 tmtypes "github.com/fibonacci-chain/fbc/libs/tendermint/types" 15 "github.com/stretchr/testify/suite" 16 17 // stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" 18 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 19 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/keeper" 20 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 21 commitmenttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/23-commitment/types" 22 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/exported" 23 ibctmtypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/07-tendermint/types" 24 localhosttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/light-clients/09-localhost/types" 25 ibctesting "github.com/fibonacci-chain/fbc/libs/ibc-go/testing" 26 ibctestingmock "github.com/fibonacci-chain/fbc/libs/ibc-go/testing/mock" 27 "github.com/fibonacci-chain/fbc/libs/ibc-go/testing/simapp" 28 ) 29 30 const ( 31 testChainID = "gaiahub-0" 32 testChainIDRevision1 = "gaiahub-1" 33 34 testClientID = "tendermint-0" 35 testClientID2 = "tendermint-1" 36 testClientID3 = "tendermint-2" 37 38 height = 5 39 40 trustingPeriod time.Duration = time.Hour * 24 * 7 * 2 41 ubdPeriod time.Duration = time.Hour * 24 * 7 * 3 42 maxClockDrift time.Duration = time.Second * 10 43 ) 44 45 var ( 46 testClientHeight = types.NewHeight(0, 5) 47 testClientHeightRevision1 = types.NewHeight(1, 5) 48 newClientHeight = types.NewHeight(1, 1) 49 ) 50 51 type KeeperTestSuite struct { 52 suite.Suite 53 54 coordinator *ibctesting.Coordinator 55 56 chainA ibctesting.TestChainI 57 chainB ibctesting.TestChainI 58 59 // cdc codec.Codec 60 cdc *codec.CodecProxy 61 ctx sdk.Context 62 keeper *keeper.Keeper 63 consensusState *ibctmtypes.ConsensusState 64 header *ibctmtypes.Header 65 valSet *tmtypes.ValidatorSet 66 valSetHash tmbytes.HexBytes 67 privVal tmtypes.PrivValidator 68 now time.Time 69 past time.Time 70 71 // TODO: deprecate 72 queryClient types.QueryClient 73 } 74 75 func (suite *KeeperTestSuite) SetupTest() { 76 tmtypes.UnittestOnlySetMilestoneVenus1Height(-1) 77 suite.coordinator = ibctesting.NewCoordinator(suite.T(), 2) 78 79 suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(0)) 80 suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(1)) 81 82 isCheckTx := false 83 suite.now = time.Date(2020, 1, 2, 0, 0, 0, 0, time.UTC) 84 suite.past = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC) 85 now2 := suite.now.Add(time.Hour) 86 app := simapp.Setup(isCheckTx) 87 88 //todo codec 89 //suite.cdc = app.AppCodec() 90 suite.ctx = app.BaseApp.NewContext(isCheckTx, tmproto.Header{Height: height, ChainID: testClientID, Time: now2}) 91 suite.keeper = &app.IBCKeeper.V2Keeper.ClientKeeper 92 suite.privVal = ibctestingmock.NewPV() 93 94 pubKey, err := suite.privVal.GetPubKey() 95 suite.Require().NoError(err) 96 97 testClientHeightMinus1 := types.NewHeight(0, height-1) 98 99 validator := tmtypes.NewValidator(pubKey, 1) 100 suite.valSet = tmtypes.NewValidatorSet([]*tmtypes.Validator{validator}) 101 // suite.valSetHash = suite.valSet.Hash() 102 suite.valSetHash = suite.valSet.Hash(int64(testClientHeightMinus1.GetRevisionHeight())) 103 suite.header = suite.chainA.CreateTMClientHeader(testChainID, int64(testClientHeight.RevisionHeight), testClientHeightMinus1, now2, suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) 104 suite.consensusState = ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("hash")), suite.valSetHash) 105 106 var validators stakingtypes.Validators 107 for i := 1; i < 11; i++ { 108 privVal := ibctestingmock.NewPV() 109 tmPk, err := privVal.GetPubKey() 110 suite.Require().NoError(err) 111 // pk, err := cryptocodec.FromTmPubKeyInterface(tmPk) 112 // suite.Require().NoError(err) 113 valAddr := sdk.ValAddress(tmPk.Address().Bytes()) 114 // val, err := stakingtypes.NewValidator(sdk.ValAddress(pk), pk, stakingtypes.Description{}) 115 // suite.Require().NoError(err) 116 val := stakingtypes.NewValidator(valAddr, tmPk, stakingtypes.Description{}, stakingtypes.DefaultMinSelfDelegation) 117 118 // val.Status = stakingtypes.Bonded 119 val.Status = sdk.Bonded 120 val.Tokens = sdk.NewInt(rand.Int63()) 121 validators = append(validators, val) 122 123 // hi := stakingtypes.NewHistoricalInfo(suite.ctx.BlockHeader(), validators, sdk.DefaultPowerReduction) 124 hi := stakingtypes.NewHistoricalInfo(suite.ctx.BlockHeader(), validators) 125 app.StakingKeeper.SetHistoricalInfo(suite.ctx, int64(i), hi) 126 } 127 128 // add localhost client 129 revision := types.ParseChainID(suite.chainA.ChainID()) 130 tmpCtx := suite.chainA.GetContext() 131 localHostClient := localhosttypes.NewClientState( 132 // suite.chainA.ChainID, types.NewHeight(revision, uint64(suite.chainA.GetContext().BlockHeight())), 133 suite.chainA.ChainID(), types.NewHeight(revision, uint64(tmpCtx.BlockHeight())), 134 ) 135 suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), exported.Localhost, localHostClient) 136 137 // TODO: deprecate 138 //queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, app.InterfaceRegistry()) 139 //types.RegisterQueryServer(queryHelper, app.IBCKeeper.ClientKeeper) 140 //suite.queryClient = types.NewQueryClient(queryHelper) 141 } 142 143 func TestKeeperTestSuite(t *testing.T) { 144 suite.Run(t, new(KeeperTestSuite)) 145 } 146 147 func (suite *KeeperTestSuite) TestSetClientState() { 148 clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 149 suite.keeper.SetClientState(suite.ctx, testClientID, clientState) 150 151 retrievedState, found := suite.keeper.GetClientState(suite.ctx, testClientID) 152 suite.Require().True(found, "GetClientState failed") 153 suite.Require().Equal(clientState, retrievedState, "Client states are not equal") 154 } 155 156 func (suite *KeeperTestSuite) TestSetClientConsensusState() { 157 suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, suite.consensusState) 158 159 retrievedConsState, found := suite.keeper.GetClientConsensusState(suite.ctx, testClientID, testClientHeight) 160 suite.Require().True(found, "GetConsensusState failed") 161 162 tmConsState, ok := retrievedConsState.(*ibctmtypes.ConsensusState) 163 suite.Require().True(ok) 164 suite.Require().Equal(suite.consensusState, tmConsState, "ConsensusState not stored correctly") 165 } 166 167 func (suite *KeeperTestSuite) TestValidateSelfClient() { 168 tmpCtx := suite.chainA.GetContext() 169 testClientHeight := types.NewHeight(0, uint64(tmpCtx.BlockHeight()-1)) 170 171 testCases := []struct { 172 name string 173 clientState exported.ClientState 174 expPass bool 175 }{ 176 { 177 "success", 178 ibctmtypes.NewClientState(suite.chainA.ChainID(), ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 179 true, 180 }, 181 { 182 "success with nil UpgradePath", 183 ibctmtypes.NewClientState(suite.chainA.ChainID(), ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), nil, false, false), 184 true, 185 }, 186 { 187 "invalid client type", 188 localhosttypes.NewClientState(suite.chainA.ChainID(), testClientHeight), 189 false, 190 }, 191 { 192 "frozen client", 193 &ibctmtypes.ClientState{suite.chainA.ChainID(), ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false}, 194 false, 195 }, 196 { 197 "incorrect chainID", 198 ibctmtypes.NewClientState("gaiatestnet", ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 199 false, 200 }, 201 { 202 "invalid client height", 203 //ibctmtypes.NewClientState(suite.chainA.ChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.NewHeight(0, uint64(suite.chainA.GetContext().BlockHeight())), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 204 ibctmtypes.NewClientState(suite.chainA.ChainID(), ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.NewHeight(0, uint64(tmpCtx.BlockHeight())), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 205 false, 206 }, 207 { 208 "invalid client revision", 209 ibctmtypes.NewClientState(suite.chainA.ChainID(), ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeightRevision1, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 210 false, 211 }, 212 { 213 "invalid proof specs", 214 ibctmtypes.NewClientState(suite.chainA.ChainID(), ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, nil, ibctesting.UpgradePath, false, false), 215 false, 216 }, 217 { 218 "invalid trust level", 219 ibctmtypes.NewClientState(suite.chainA.ChainID(), ibctmtypes.Fraction{0, 1}, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 220 false, 221 }, 222 { 223 "invalid unbonding period", 224 ibctmtypes.NewClientState(suite.chainA.ChainID(), ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod+10, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 225 false, 226 }, 227 { 228 "invalid trusting period", 229 ibctmtypes.NewClientState(suite.chainA.ChainID(), ibctmtypes.DefaultTrustLevel, ubdPeriod+10, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 230 false, 231 }, 232 { 233 "invalid upgrade path", 234 ibctmtypes.NewClientState(suite.chainA.ChainID(), ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), []string{"bad", "upgrade", "path"}, false, false), 235 false, 236 }, 237 } 238 239 for _, tc := range testCases { 240 err := suite.chainA.App().GetIBCKeeper().ClientKeeper.ValidateSelfClient(suite.chainA.GetContext(), tc.clientState) 241 if tc.expPass { 242 suite.Require().NoError(err, "expected valid client for case: %s", tc.name) 243 } else { 244 suite.Require().Error(err, "expected invalid client for case: %s", tc.name) 245 } 246 } 247 } 248 249 func (suite KeeperTestSuite) TestGetAllGenesisClients() { 250 clientIDs := []string{ 251 testClientID2, testClientID3, testClientID, 252 } 253 expClients := []exported.ClientState{ 254 ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 255 ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 256 ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, types.ZeroHeight(), commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false), 257 } 258 259 expGenClients := make(types.IdentifiedClientStates, len(expClients)) 260 261 for i := range expClients { 262 suite.chainA.App().GetIBCKeeper().ClientKeeper.SetClientState(suite.chainA.GetContext(), clientIDs[i], expClients[i]) 263 expGenClients[i] = types.NewIdentifiedClientState(clientIDs[i], expClients[i]) 264 } 265 266 // add localhost client 267 localHostClient, found := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetClientState(suite.chainA.GetContext(), exported.Localhost) 268 suite.Require().True(found) 269 expGenClients = append(expGenClients, types.NewIdentifiedClientState(exported.Localhost, localHostClient)) 270 271 genClients := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetAllGenesisClients(suite.chainA.GetContext()) 272 273 suite.Require().Equal(expGenClients.Sort(), genClients) 274 } 275 276 func (suite KeeperTestSuite) TestGetAllGenesisMetadata() { 277 expectedGenMetadata := []types.IdentifiedGenesisMetadata{ 278 types.NewIdentifiedGenesisMetadata( 279 "07-tendermint-1", 280 []types.GenesisMetadata{ 281 types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(0, 1)), []byte("foo")), 282 types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(0, 2)), []byte("bar")), 283 types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(0, 3)), []byte("baz")), 284 }, 285 ), 286 types.NewIdentifiedGenesisMetadata( 287 "clientB", 288 []types.GenesisMetadata{ 289 types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(1, 100)), []byte("val1")), 290 types.NewGenesisMetadata(ibctmtypes.ProcessedTimeKey(types.NewHeight(2, 300)), []byte("val2")), 291 }, 292 ), 293 } 294 295 genClients := []types.IdentifiedClientState{ 296 types.NewIdentifiedClientState("07-tendermint-1", &ibctmtypes.ClientState{}), types.NewIdentifiedClientState("clientB", &ibctmtypes.ClientState{}), 297 types.NewIdentifiedClientState("clientC", &ibctmtypes.ClientState{}), types.NewIdentifiedClientState("clientD", &localhosttypes.ClientState{}), 298 } 299 300 suite.chainA.App().GetIBCKeeper().ClientKeeper.SetAllClientMetadata(suite.chainA.GetContext(), expectedGenMetadata) 301 302 actualGenMetadata, err := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetAllClientMetadata(suite.chainA.GetContext(), genClients) 303 suite.Require().NoError(err, "get client metadata returned error unexpectedly") 304 suite.Require().Equal(expectedGenMetadata, actualGenMetadata, "retrieved metadata is unexpected") 305 } 306 307 func (suite KeeperTestSuite) TestGetConsensusState() { 308 suite.ctx = suite.ctx.WithBlockHeight(10) 309 cases := []struct { 310 name string 311 height types.Height 312 expPass bool 313 }{ 314 {"zero height", types.ZeroHeight(), false}, 315 {"height > latest height", types.NewHeight(0, uint64(suite.ctx.BlockHeight())+1), false}, 316 {"latest height - 1", types.NewHeight(0, uint64(suite.ctx.BlockHeight())-1), true}, 317 {"latest height", types.GetSelfHeight(suite.ctx), true}, 318 } 319 320 for i, tc := range cases { 321 tc := tc 322 cs, found := suite.keeper.GetSelfConsensusState(suite.ctx, tc.height) 323 if tc.expPass { 324 suite.Require().True(found, "Case %d should have passed: %s", i, tc.name) 325 suite.Require().NotNil(cs, "Case %d should have passed: %s", i, tc.name) 326 } else { 327 suite.Require().False(found, "Case %d should have failed: %s", i, tc.name) 328 suite.Require().Nil(cs, "Case %d should have failed: %s", i, tc.name) 329 } 330 } 331 } 332 333 func (suite KeeperTestSuite) TestConsensusStateHelpers() { 334 // initial setup 335 clientState := ibctmtypes.NewClientState(testChainID, ibctmtypes.DefaultTrustLevel, trustingPeriod, ubdPeriod, maxClockDrift, testClientHeight, commitmenttypes.GetSDKSpecs(), ibctesting.UpgradePath, false, false) 336 337 suite.keeper.SetClientState(suite.ctx, testClientID, clientState) 338 suite.keeper.SetClientConsensusState(suite.ctx, testClientID, testClientHeight, suite.consensusState) 339 340 nextState := ibctmtypes.NewConsensusState(suite.now, commitmenttypes.NewMerkleRoot([]byte("next")), suite.valSetHash) 341 342 testClientHeightPlus5 := types.NewHeight(0, height+5) 343 344 header := suite.chainA.CreateTMClientHeader(testClientID, int64(testClientHeightPlus5.RevisionHeight), testClientHeight, suite.header.Header.Time.Add(time.Minute), 345 suite.valSet, suite.valSet, []tmtypes.PrivValidator{suite.privVal}) 346 347 // mock update functionality 348 clientState.LatestHeight = header.GetHeight().(types.Height) 349 suite.keeper.SetClientConsensusState(suite.ctx, testClientID, header.GetHeight(), nextState) 350 suite.keeper.SetClientState(suite.ctx, testClientID, clientState) 351 352 latest, ok := suite.keeper.GetLatestClientConsensusState(suite.ctx, testClientID) 353 suite.Require().True(ok) 354 suite.Require().Equal(nextState, latest, "Latest client not returned correctly") 355 } 356 357 // 2 clients in total are created on chainA. The first client is updated so it contains an initial consensus state 358 // and a consensus state at the update height. 359 func (suite KeeperTestSuite) TestGetAllConsensusStates() { 360 path := ibctesting.NewPath(suite.chainA, suite.chainB) 361 suite.coordinator.SetupClients(path) 362 363 clientState := path.EndpointA.GetClientState() 364 expConsensusHeight0 := clientState.GetLatestHeight() 365 consensusState0, ok := suite.chainA.GetConsensusState(path.EndpointA.ClientID, expConsensusHeight0) 366 suite.Require().True(ok) 367 368 // update client to create a second consensus state 369 err := path.EndpointA.UpdateClient() 370 suite.Require().NoError(err) 371 372 clientState = path.EndpointA.GetClientState() 373 expConsensusHeight1 := clientState.GetLatestHeight() 374 suite.Require().True(expConsensusHeight1.GT(expConsensusHeight0)) 375 consensusState1, ok := suite.chainA.GetConsensusState(path.EndpointA.ClientID, expConsensusHeight1) 376 suite.Require().True(ok) 377 378 expConsensus := []exported.ConsensusState{ 379 consensusState0, 380 consensusState1, 381 } 382 383 // create second client on chainA 384 path2 := ibctesting.NewPath(suite.chainA, suite.chainB) 385 suite.coordinator.SetupClients(path2) 386 clientState = path2.EndpointA.GetClientState() 387 388 expConsensusHeight2 := clientState.GetLatestHeight() 389 consensusState2, ok := suite.chainA.GetConsensusState(path2.EndpointA.ClientID, expConsensusHeight2) 390 suite.Require().True(ok) 391 392 expConsensus2 := []exported.ConsensusState{consensusState2} 393 394 expConsensusStates := types.ClientsConsensusStates{ 395 types.NewClientConsensusStates(path.EndpointA.ClientID, []types.ConsensusStateWithHeight{ 396 types.NewConsensusStateWithHeight(expConsensusHeight0.(types.Height), expConsensus[0]), 397 types.NewConsensusStateWithHeight(expConsensusHeight1.(types.Height), expConsensus[1]), 398 }), 399 types.NewClientConsensusStates(path2.EndpointA.ClientID, []types.ConsensusStateWithHeight{ 400 types.NewConsensusStateWithHeight(expConsensusHeight2.(types.Height), expConsensus2[0]), 401 }), 402 }.Sort() 403 404 consStates := suite.chainA.App().GetIBCKeeper().ClientKeeper.GetAllConsensusStates(suite.chainA.GetContext()) 405 suite.Require().Equal(expConsensusStates, consStates, "%s \n\n%s", expConsensusStates, consStates) 406 }