github.com/Finschia/finschia-sdk@v0.49.1/x/staking/keeper/validator_test.go (about) 1 package keeper_test 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 abci "github.com/tendermint/tendermint/abci/types" 11 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 12 13 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 14 "github.com/Finschia/finschia-sdk/simapp" 15 sdk "github.com/Finschia/finschia-sdk/types" 16 "github.com/Finschia/finschia-sdk/x/staking/keeper" 17 "github.com/Finschia/finschia-sdk/x/staking/teststaking" 18 "github.com/Finschia/finschia-sdk/x/staking/types" 19 ) 20 21 func newMonikerValidator(tb testing.TB, operator sdk.ValAddress, pubKey cryptotypes.PubKey, moniker string) types.Validator { 22 tb.Helper() 23 v, err := types.NewValidator(operator, pubKey, types.Description{Moniker: moniker}) 24 require.NoError(tb, err) 25 return v 26 } 27 28 func bootstrapValidatorTest(tb testing.TB, power int64, numAddrs int) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress) { 29 tb.Helper() 30 _, app, ctx := createTestInput() 31 32 addrDels, addrVals := generateAddresses(app, ctx, numAddrs) 33 34 amt := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 35 totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels))))) 36 37 notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) 38 // set bonded pool supply 39 app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) 40 41 require.NoError(tb, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), totalSupply)) 42 43 return app, ctx, addrDels, addrVals 44 } 45 46 func initValidators(tb testing.TB, power int64, numAddrs int, powers []int64) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress, []types.Validator) { 47 tb.Helper() 48 app, ctx, addrs, valAddrs := bootstrapValidatorTest(tb, power, numAddrs) 49 pks := simapp.CreateTestPubKeys(numAddrs) 50 51 vs := make([]types.Validator, len(powers)) 52 for i, power := range powers { 53 vs[i] = teststaking.NewValidator(tb, sdk.ValAddress(addrs[i]), pks[i]) 54 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 55 vs[i], _ = vs[i].AddTokensFromDel(tokens) 56 } 57 return app, ctx, addrs, valAddrs, vs 58 } 59 60 func TestSetValidator(t *testing.T) { 61 app, ctx, _, _ := bootstrapValidatorTest(t, 10, 100) 62 63 valPubKey := PKs[0] 64 valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) 65 valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10) 66 67 // test how the validator is set from a purely unbonbed pool 68 validator := teststaking.NewValidator(t, valAddr, valPubKey) 69 validator, _ = validator.AddTokensFromDel(valTokens) 70 require.Equal(t, types.Unbonded, validator.Status) 71 assert.Equal(t, valTokens, validator.Tokens) 72 assert.Equal(t, valTokens, validator.DelegatorShares.RoundInt()) 73 app.StakingKeeper.SetValidator(ctx, validator) 74 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validator) 75 76 // ensure update 77 updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1) 78 validator, found := app.StakingKeeper.GetValidator(ctx, valAddr) 79 require.True(t, found) 80 require.Equal(t, validator.ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 81 82 // after the save the validator should be bonded 83 require.Equal(t, types.Bonded, validator.Status) 84 assert.Equal(t, valTokens, validator.Tokens) 85 assert.Equal(t, valTokens, validator.DelegatorShares.RoundInt()) 86 87 // Check each store for being saved 88 resVal, found := app.StakingKeeper.GetValidator(ctx, valAddr) 89 assert.True(ValEq(t, validator, resVal)) 90 require.True(t, found) 91 92 resVals := app.StakingKeeper.GetLastValidators(ctx) 93 require.Equal(t, 1, len(resVals)) 94 assert.True(ValEq(t, validator, resVals[0])) 95 96 resVals = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 97 require.Equal(t, 1, len(resVals)) 98 require.True(ValEq(t, validator, resVals[0])) 99 100 resVals = app.StakingKeeper.GetValidators(ctx, 1) 101 require.Equal(t, 1, len(resVals)) 102 require.True(ValEq(t, validator, resVals[0])) 103 104 resVals = app.StakingKeeper.GetValidators(ctx, 10) 105 require.Equal(t, 1, len(resVals)) 106 require.True(ValEq(t, validator, resVals[0])) 107 108 allVals := app.StakingKeeper.GetAllValidators(ctx) 109 require.Equal(t, 1, len(allVals)) 110 } 111 112 func TestUpdateValidatorByPowerIndex(t *testing.T) { 113 app, ctx, _, _ := bootstrapValidatorTest(t, 0, 100) 114 _, addrVals := generateAddresses(app, ctx, 1) 115 116 bondedPool := app.StakingKeeper.GetBondedPool(ctx) 117 notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) 118 119 require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 1234))))) 120 require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 10000))))) 121 122 app.AccountKeeper.SetModuleAccount(ctx, bondedPool) 123 app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) 124 125 // add a validator 126 validator := teststaking.NewValidator(t, addrVals[0], PKs[0]) 127 validator, delSharesCreated := validator.AddTokensFromDel(app.StakingKeeper.TokensFromConsensusPower(ctx, 100)) 128 require.Equal(t, types.Unbonded, validator.Status) 129 require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 100), validator.Tokens) 130 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) 131 validator, found := app.StakingKeeper.GetValidator(ctx, addrVals[0]) 132 require.True(t, found) 133 require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 100), validator.Tokens) 134 135 power := types.GetValidatorsByPowerIndexKey(validator, app.StakingKeeper.PowerReduction(ctx)) 136 require.True(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power)) 137 138 // burn half the delegator shares 139 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validator) 140 validator, burned := validator.RemoveDelShares(delSharesCreated.Quo(sdk.NewDec(2))) 141 require.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 50), burned) 142 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) // update the validator, possibly kicking it out 143 require.False(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power)) 144 145 validator, found = app.StakingKeeper.GetValidator(ctx, addrVals[0]) 146 require.True(t, found) 147 148 power = types.GetValidatorsByPowerIndexKey(validator, app.StakingKeeper.PowerReduction(ctx)) 149 require.True(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power)) 150 } 151 152 func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { 153 numVals := 10 154 maxVals := 5 155 156 // create context, keeper, and pool for tests 157 app, ctx, _, valAddrs := bootstrapValidatorTest(t, 0, 100) 158 159 bondedPool := app.StakingKeeper.GetBondedPool(ctx) 160 notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) 161 162 // create keeper parameters 163 params := app.StakingKeeper.GetParams(ctx) 164 params.MaxValidators = uint32(maxVals) 165 app.StakingKeeper.SetParams(ctx, params) 166 167 // create a random pool 168 require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 1234))))) 169 require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 10000))))) 170 171 app.AccountKeeper.SetModuleAccount(ctx, bondedPool) 172 app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) 173 174 validators := make([]types.Validator, numVals) 175 for i := 0; i < len(validators); i++ { 176 moniker := fmt.Sprintf("val#%d", int64(i)) 177 val := newMonikerValidator(t, valAddrs[i], PKs[i], moniker) 178 delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, int64((i+1)*10)) 179 val, _ = val.AddTokensFromDel(delTokens) 180 181 val = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, val, true) 182 validators[i] = val 183 } 184 185 nextCliffVal := validators[numVals-maxVals+1] 186 187 // remove enough tokens to kick out the validator below the current cliff 188 // validator and next in line cliff validator 189 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, nextCliffVal) 190 shares := app.StakingKeeper.TokensFromConsensusPower(ctx, 21) 191 nextCliffVal, _ = nextCliffVal.RemoveDelShares(shares.ToDec()) 192 _ = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, nextCliffVal, true) 193 194 expectedValStatus := map[int]types.BondStatus{ 195 9: types.Bonded, 8: types.Bonded, 7: types.Bonded, 5: types.Bonded, 4: types.Bonded, 196 0: types.Unbonding, 1: types.Unbonding, 2: types.Unbonding, 3: types.Unbonding, 6: types.Unbonding, 197 } 198 199 // require all the validators have their respective statuses 200 for valIdx, status := range expectedValStatus { 201 valAddr := validators[valIdx].OperatorAddress 202 addr, err := sdk.ValAddressFromBech32(valAddr) 203 assert.NoError(t, err) 204 val, _ := app.StakingKeeper.GetValidator(ctx, addr) 205 206 assert.Equal( 207 t, status, val.GetStatus(), 208 fmt.Sprintf("expected validator at index %v to have status: %s", valIdx, status), 209 ) 210 } 211 } 212 213 func TestSlashToZeroPowerRemoved(t *testing.T) { 214 // initialize setup 215 app, ctx, _, addrVals := bootstrapValidatorTest(t, 100, 20) 216 217 // add a validator 218 validator := teststaking.NewValidator(t, addrVals[0], PKs[0]) 219 valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 100) 220 221 bondedPool := app.StakingKeeper.GetBondedPool(ctx) 222 223 require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), valTokens)))) 224 225 app.AccountKeeper.SetModuleAccount(ctx, bondedPool) 226 227 validator, _ = validator.AddTokensFromDel(valTokens) 228 require.Equal(t, types.Unbonded, validator.Status) 229 require.Equal(t, valTokens, validator.Tokens) 230 err := app.StakingKeeper.SetValidatorByConsAddr(ctx, validator) 231 require.NoError(t, err) 232 validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true) 233 require.Equal(t, valTokens, validator.Tokens, "\nvalidator %v\npool %v", validator, valTokens) 234 235 // slash the validator by 100% 236 app.StakingKeeper.Slash(ctx, sdk.ConsAddress(PKs[0].Address()), 0, 100, sdk.OneDec()) 237 // apply TM updates 238 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, -1) 239 // validator should be unbonding 240 validator, _ = app.StakingKeeper.GetValidator(ctx, addrVals[0]) 241 require.Equal(t, validator.GetStatus(), types.Unbonding) 242 } 243 244 // This function tests UpdateValidator, GetValidator, GetLastValidators, RemoveValidator 245 func TestValidatorBasics(t *testing.T) { 246 app, ctx, _, addrVals := bootstrapValidatorTest(t, 1000, 20) 247 248 // construct the validators 249 var validators [3]types.Validator 250 powers := []int64{9, 8, 7} 251 for i, power := range powers { 252 validators[i] = teststaking.NewValidator(t, addrVals[i], PKs[i]) 253 validators[i].Status = types.Unbonded 254 validators[i].Tokens = sdk.ZeroInt() 255 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 256 257 validators[i], _ = validators[i].AddTokensFromDel(tokens) 258 } 259 assert.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 9), validators[0].Tokens) 260 assert.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 8), validators[1].Tokens) 261 assert.Equal(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 7), validators[2].Tokens) 262 263 // check the empty keeper first 264 _, found := app.StakingKeeper.GetValidator(ctx, addrVals[0]) 265 require.False(t, found) 266 resVals := app.StakingKeeper.GetLastValidators(ctx) 267 require.Zero(t, len(resVals)) 268 269 resVals = app.StakingKeeper.GetValidators(ctx, 2) 270 require.Zero(t, len(resVals)) 271 272 // set and retrieve a record 273 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], true) 274 err := app.StakingKeeper.SetValidatorByConsAddr(ctx, validators[0]) 275 require.NoError(t, err) 276 resVal, found := app.StakingKeeper.GetValidator(ctx, addrVals[0]) 277 require.True(t, found) 278 assert.True(ValEq(t, validators[0], resVal)) 279 280 // retrieve from consensus 281 resVal, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.ConsAddress(PKs[0].Address())) 282 require.True(t, found) 283 assert.True(ValEq(t, validators[0], resVal)) 284 resVal, found = app.StakingKeeper.GetValidatorByConsAddr(ctx, sdk.GetConsAddress(PKs[0])) 285 require.True(t, found) 286 assert.True(ValEq(t, validators[0], resVal)) 287 288 resVals = app.StakingKeeper.GetLastValidators(ctx) 289 require.Equal(t, 1, len(resVals)) 290 assert.True(ValEq(t, validators[0], resVals[0])) 291 assert.Equal(t, types.Bonded, validators[0].Status) 292 assert.True(sdk.IntEq(t, app.StakingKeeper.TokensFromConsensusPower(ctx, 9), validators[0].BondedTokens())) 293 294 // modify a records, save, and retrieve 295 validators[0].Status = types.Bonded 296 validators[0].Tokens = app.StakingKeeper.TokensFromConsensusPower(ctx, 10) 297 validators[0].DelegatorShares = validators[0].Tokens.ToDec() 298 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], true) 299 resVal, found = app.StakingKeeper.GetValidator(ctx, addrVals[0]) 300 require.True(t, found) 301 assert.True(ValEq(t, validators[0], resVal)) 302 303 resVals = app.StakingKeeper.GetLastValidators(ctx) 304 require.Equal(t, 1, len(resVals)) 305 assert.True(ValEq(t, validators[0], resVals[0])) 306 307 // add other validators 308 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], true) 309 validators[2] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[2], true) 310 resVal, found = app.StakingKeeper.GetValidator(ctx, addrVals[1]) 311 require.True(t, found) 312 assert.True(ValEq(t, validators[1], resVal)) 313 resVal, found = app.StakingKeeper.GetValidator(ctx, addrVals[2]) 314 require.True(t, found) 315 assert.True(ValEq(t, validators[2], resVal)) 316 317 resVals = app.StakingKeeper.GetLastValidators(ctx) 318 require.Equal(t, 3, len(resVals)) 319 assert.True(ValEq(t, validators[0], resVals[0])) // order doesn't matter here 320 assert.True(ValEq(t, validators[1], resVals[1])) 321 assert.True(ValEq(t, validators[2], resVals[2])) 322 323 // remove a record 324 325 // shouldn't be able to remove if status is not unbonded 326 assert.PanicsWithValue(t, 327 "cannot call RemoveValidator on bonded or unbonding validators", 328 func() { app.StakingKeeper.RemoveValidator(ctx, validators[1].GetOperator()) }) 329 330 // shouldn't be able to remove if there are still tokens left 331 validators[1].Status = types.Unbonded 332 app.StakingKeeper.SetValidator(ctx, validators[1]) 333 assert.PanicsWithValue(t, 334 "attempting to remove a validator which still contains tokens", 335 func() { app.StakingKeeper.RemoveValidator(ctx, validators[1].GetOperator()) }) 336 337 validators[1].Tokens = sdk.ZeroInt() // ...remove all tokens 338 app.StakingKeeper.SetValidator(ctx, validators[1]) // ...set the validator 339 app.StakingKeeper.RemoveValidator(ctx, validators[1].GetOperator()) // Now it can be removed. 340 _, found = app.StakingKeeper.GetValidator(ctx, addrVals[1]) 341 require.False(t, found) 342 } 343 344 // test how the validators are sorted, tests GetBondedValidatorsByPower 345 func TestGetValidatorSortingUnmixed(t *testing.T) { 346 app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20) 347 348 // initialize some validators into the state 349 amts := []sdk.Int{ 350 sdk.NewIntFromUint64(0), 351 app.StakingKeeper.PowerReduction(ctx).MulRaw(100), 352 app.StakingKeeper.PowerReduction(ctx), 353 app.StakingKeeper.PowerReduction(ctx).MulRaw(400), 354 app.StakingKeeper.PowerReduction(ctx).MulRaw(200), 355 } 356 n := len(amts) 357 var validators [5]types.Validator 358 for i, amt := range amts { 359 validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) 360 validators[i].Status = types.Bonded 361 validators[i].Tokens = amt 362 validators[i].DelegatorShares = sdk.NewDecFromInt(amt) 363 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[i], true) 364 } 365 366 // first make sure everything made it in to the gotValidator group 367 resValidators := app.StakingKeeper.GetBondedValidatorsByPower(ctx) 368 assert.Equal(t, n, len(resValidators)) 369 assert.Equal(t, sdk.NewInt(400).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[0].BondedTokens(), "%v", resValidators) 370 assert.Equal(t, sdk.NewInt(200).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[1].BondedTokens(), "%v", resValidators) 371 assert.Equal(t, sdk.NewInt(100).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[2].BondedTokens(), "%v", resValidators) 372 assert.Equal(t, sdk.NewInt(1).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[3].BondedTokens(), "%v", resValidators) 373 assert.Equal(t, sdk.NewInt(0), resValidators[4].BondedTokens(), "%v", resValidators) 374 assert.Equal(t, validators[3].OperatorAddress, resValidators[0].OperatorAddress, "%v", resValidators) 375 assert.Equal(t, validators[4].OperatorAddress, resValidators[1].OperatorAddress, "%v", resValidators) 376 assert.Equal(t, validators[1].OperatorAddress, resValidators[2].OperatorAddress, "%v", resValidators) 377 assert.Equal(t, validators[2].OperatorAddress, resValidators[3].OperatorAddress, "%v", resValidators) 378 assert.Equal(t, validators[0].OperatorAddress, resValidators[4].OperatorAddress, "%v", resValidators) 379 380 // test a basic increase in voting power 381 validators[3].Tokens = sdk.NewInt(500).Mul(app.StakingKeeper.PowerReduction(ctx)) 382 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) 383 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 384 require.Equal(t, len(resValidators), n) 385 assert.True(ValEq(t, validators[3], resValidators[0])) 386 387 // test a decrease in voting power 388 validators[3].Tokens = sdk.NewInt(300).Mul(app.StakingKeeper.PowerReduction(ctx)) 389 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) 390 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 391 require.Equal(t, len(resValidators), n) 392 assert.True(ValEq(t, validators[3], resValidators[0])) 393 assert.True(ValEq(t, validators[4], resValidators[1])) 394 395 // test equal voting power, different age 396 validators[3].Tokens = sdk.NewInt(200).Mul(app.StakingKeeper.PowerReduction(ctx)) 397 ctx = ctx.WithBlockHeight(10) 398 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) 399 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 400 require.Equal(t, len(resValidators), n) 401 assert.True(ValEq(t, validators[3], resValidators[0])) 402 assert.True(ValEq(t, validators[4], resValidators[1])) 403 404 // no change in voting power - no change in sort 405 ctx = ctx.WithBlockHeight(20) 406 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[4], true) 407 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 408 require.Equal(t, len(resValidators), n) 409 assert.True(ValEq(t, validators[3], resValidators[0])) 410 assert.True(ValEq(t, validators[4], resValidators[1])) 411 412 // change in voting power of both validators, both still in v-set, no age change 413 validators[3].Tokens = sdk.NewInt(300).Mul(app.StakingKeeper.PowerReduction(ctx)) 414 validators[4].Tokens = sdk.NewInt(300).Mul(app.StakingKeeper.PowerReduction(ctx)) 415 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) 416 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 417 require.Equal(t, len(resValidators), n) 418 ctx = ctx.WithBlockHeight(30) 419 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[4], true) 420 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 421 require.Equal(t, len(resValidators), n, "%v", resValidators) 422 assert.True(ValEq(t, validators[3], resValidators[0])) 423 assert.True(ValEq(t, validators[4], resValidators[1])) 424 } 425 426 func TestGetValidatorSortingMixed(t *testing.T) { 427 app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20) 428 bondedPool := app.StakingKeeper.GetBondedPool(ctx) 429 notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) 430 431 require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 501))))) 432 require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), app.StakingKeeper.TokensFromConsensusPower(ctx, 0))))) 433 434 app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) 435 app.AccountKeeper.SetModuleAccount(ctx, bondedPool) 436 437 // now 2 max resValidators 438 params := app.StakingKeeper.GetParams(ctx) 439 params.MaxValidators = 2 440 app.StakingKeeper.SetParams(ctx, params) 441 442 // initialize some validators into the state 443 amts := []sdk.Int{ 444 sdk.NewIntFromUint64(0), 445 app.StakingKeeper.PowerReduction(ctx).MulRaw(100), 446 app.StakingKeeper.PowerReduction(ctx), 447 app.StakingKeeper.PowerReduction(ctx).MulRaw(400), 448 app.StakingKeeper.PowerReduction(ctx).MulRaw(200), 449 } 450 451 var validators [5]types.Validator 452 for i, amt := range amts { 453 validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) 454 validators[i].DelegatorShares = sdk.NewDecFromInt(amt) 455 validators[i].Status = types.Bonded 456 validators[i].Tokens = amt 457 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[i], true) 458 } 459 460 val0, found := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addrs[0])) 461 require.True(t, found) 462 val1, found := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addrs[1])) 463 require.True(t, found) 464 val2, found := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addrs[2])) 465 require.True(t, found) 466 val3, found := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addrs[3])) 467 require.True(t, found) 468 val4, found := app.StakingKeeper.GetValidator(ctx, sdk.ValAddress(addrs[4])) 469 require.True(t, found) 470 require.Equal(t, types.Bonded, val0.Status) 471 require.Equal(t, types.Unbonding, val1.Status) 472 require.Equal(t, types.Unbonding, val2.Status) 473 require.Equal(t, types.Bonded, val3.Status) 474 require.Equal(t, types.Bonded, val4.Status) 475 476 // first make sure everything made it in to the gotValidator group 477 resValidators := app.StakingKeeper.GetBondedValidatorsByPower(ctx) 478 // The validators returned should match the max validators 479 assert.Equal(t, 2, len(resValidators)) 480 assert.Equal(t, sdk.NewInt(400).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[0].BondedTokens(), "%v", resValidators) 481 assert.Equal(t, sdk.NewInt(200).Mul(app.StakingKeeper.PowerReduction(ctx)), resValidators[1].BondedTokens(), "%v", resValidators) 482 assert.Equal(t, validators[3].OperatorAddress, resValidators[0].OperatorAddress, "%v", resValidators) 483 assert.Equal(t, validators[4].OperatorAddress, resValidators[1].OperatorAddress, "%v", resValidators) 484 } 485 486 // TODO separate out into multiple tests 487 func TestGetValidatorsEdgeCases(t *testing.T) { 488 app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20) 489 490 // set max validators to 2 491 params := app.StakingKeeper.GetParams(ctx) 492 nMax := uint32(2) 493 params.MaxValidators = nMax 494 app.StakingKeeper.SetParams(ctx, params) 495 496 // initialize some validators into the state 497 powers := []int64{0, 100, 400, 400} 498 var validators [4]types.Validator 499 for i, power := range powers { 500 moniker := fmt.Sprintf("val#%d", int64(i)) 501 validators[i] = newMonikerValidator(t, sdk.ValAddress(addrs[i]), PKs[i], moniker) 502 503 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 504 validators[i], _ = validators[i].AddTokensFromDel(tokens) 505 506 notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) 507 require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, tokens)))) 508 app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) 509 validators[i] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[i], true) 510 } 511 512 // ensure that the first two bonded validators are the largest validators 513 resValidators := app.StakingKeeper.GetBondedValidatorsByPower(ctx) 514 require.Equal(t, nMax, uint32(len(resValidators))) 515 assert.True(ValEq(t, validators[2], resValidators[0])) 516 assert.True(ValEq(t, validators[3], resValidators[1])) 517 518 // delegate 500 tokens to validator 0 519 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[0]) 520 delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 500) 521 validators[0], _ = validators[0].AddTokensFromDel(delTokens) 522 notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) 523 524 newTokens := sdk.NewCoins() 525 526 require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), newTokens)) 527 app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) 528 529 // test that the two largest validators are 530 // a) validator 0 with 500 tokens 531 // b) validator 2 with 400 tokens (delegated before validator 3) 532 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], true) 533 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 534 require.Equal(t, nMax, uint32(len(resValidators))) 535 assert.True(ValEq(t, validators[0], resValidators[0])) 536 assert.True(ValEq(t, validators[2], resValidators[1])) 537 538 // A validator which leaves the bonded validator set due to a decrease in voting power, 539 // then increases to the original voting power, does not get its spot back in the 540 // case of a tie. 541 // 542 // Order of operations for this test: 543 // - validator 3 enter validator set with 1 new token 544 // - validator 3 removed validator set by removing 201 tokens (validator 2 enters) 545 // - validator 3 adds 200 tokens (equal to validator 2 now) and does not get its spot back 546 547 // validator 3 enters bonded validator set 548 ctx = ctx.WithBlockHeight(40) 549 550 var found bool 551 validators[3], found = app.StakingKeeper.GetValidator(ctx, validators[3].GetOperator()) 552 assert.True(t, found) 553 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[3]) 554 validators[3], _ = validators[3].AddTokensFromDel(app.StakingKeeper.TokensFromConsensusPower(ctx, 1)) 555 556 notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx) 557 newTokens = sdk.NewCoins(sdk.NewCoin(params.BondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 1))) 558 require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), newTokens)) 559 app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) 560 561 validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) 562 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 563 require.Equal(t, nMax, uint32(len(resValidators))) 564 assert.True(ValEq(t, validators[0], resValidators[0])) 565 assert.True(ValEq(t, validators[3], resValidators[1])) 566 567 // validator 3 kicked out temporarily 568 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[3]) 569 rmTokens := validators[3].TokensFromShares(sdk.NewDec(201)).TruncateInt() 570 validators[3], _ = validators[3].RemoveDelShares(sdk.NewDec(201)) 571 572 bondedPool := app.StakingKeeper.GetBondedPool(ctx) 573 require.NoError(t, simapp.FundModuleAccount(app, ctx, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, rmTokens)))) 574 app.AccountKeeper.SetModuleAccount(ctx, bondedPool) 575 576 validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) 577 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 578 require.Equal(t, nMax, uint32(len(resValidators))) 579 assert.True(ValEq(t, validators[0], resValidators[0])) 580 assert.True(ValEq(t, validators[2], resValidators[1])) 581 582 // validator 3 does not get spot back 583 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[3]) 584 validators[3], _ = validators[3].AddTokensFromDel(sdk.NewInt(200)) 585 586 notBondedPool = app.StakingKeeper.GetNotBondedPool(ctx) 587 require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, sdk.NewInt(200))))) 588 app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) 589 590 validators[3] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[3], true) 591 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 592 require.Equal(t, nMax, uint32(len(resValidators))) 593 assert.True(ValEq(t, validators[0], resValidators[0])) 594 assert.True(ValEq(t, validators[2], resValidators[1])) 595 _, exists := app.StakingKeeper.GetValidator(ctx, validators[3].GetOperator()) 596 require.True(t, exists) 597 } 598 599 func TestValidatorBondHeight(t *testing.T) { 600 app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20) 601 602 // now 2 max resValidators 603 params := app.StakingKeeper.GetParams(ctx) 604 params.MaxValidators = 2 605 app.StakingKeeper.SetParams(ctx, params) 606 607 // initialize some validators into the state 608 var validators [3]types.Validator 609 validators[0] = teststaking.NewValidator(t, sdk.ValAddress(PKs[0].Address().Bytes()), PKs[0]) 610 validators[1] = teststaking.NewValidator(t, sdk.ValAddress(addrs[1]), PKs[1]) 611 validators[2] = teststaking.NewValidator(t, sdk.ValAddress(addrs[2]), PKs[2]) 612 613 tokens0 := app.StakingKeeper.TokensFromConsensusPower(ctx, 200) 614 tokens1 := app.StakingKeeper.TokensFromConsensusPower(ctx, 100) 615 tokens2 := app.StakingKeeper.TokensFromConsensusPower(ctx, 100) 616 validators[0], _ = validators[0].AddTokensFromDel(tokens0) 617 validators[1], _ = validators[1].AddTokensFromDel(tokens1) 618 validators[2], _ = validators[2].AddTokensFromDel(tokens2) 619 620 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], true) 621 622 //////////////////////////////////////// 623 // If two validators both increase to the same voting power in the same block, 624 // the one with the first transaction should become bonded 625 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], true) 626 validators[2] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[2], true) 627 628 resValidators := app.StakingKeeper.GetBondedValidatorsByPower(ctx) 629 require.Equal(t, uint32(len(resValidators)), params.MaxValidators) 630 631 assert.True(ValEq(t, validators[0], resValidators[0])) 632 assert.True(ValEq(t, validators[1], resValidators[1])) 633 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[1]) 634 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[2]) 635 delTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 50) 636 validators[1], _ = validators[1].AddTokensFromDel(delTokens) 637 validators[2], _ = validators[2].AddTokensFromDel(delTokens) 638 validators[2] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[2], true) 639 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 640 require.Equal(t, params.MaxValidators, uint32(len(resValidators))) 641 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], true) 642 assert.True(ValEq(t, validators[0], resValidators[0])) 643 assert.True(ValEq(t, validators[2], resValidators[1])) 644 } 645 646 func TestFullValidatorSetPowerChange(t *testing.T) { 647 app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20) 648 params := app.StakingKeeper.GetParams(ctx) 649 max := 2 650 params.MaxValidators = uint32(2) 651 app.StakingKeeper.SetParams(ctx, params) 652 653 // initialize some validators into the state 654 powers := []int64{0, 100, 400, 400, 200} 655 var validators [5]types.Validator 656 for i, power := range powers { 657 validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) 658 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 659 validators[i], _ = validators[i].AddTokensFromDel(tokens) 660 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[i], true) 661 } 662 for i := range powers { 663 var found bool 664 validators[i], found = app.StakingKeeper.GetValidator(ctx, validators[i].GetOperator()) 665 require.True(t, found) 666 } 667 assert.Equal(t, types.Unbonded, validators[0].Status) 668 assert.Equal(t, types.Unbonding, validators[1].Status) 669 assert.Equal(t, types.Bonded, validators[2].Status) 670 assert.Equal(t, types.Bonded, validators[3].Status) 671 assert.Equal(t, types.Unbonded, validators[4].Status) 672 resValidators := app.StakingKeeper.GetBondedValidatorsByPower(ctx) 673 assert.Equal(t, max, len(resValidators)) 674 assert.True(ValEq(t, validators[2], resValidators[0])) // in the order of txs 675 assert.True(ValEq(t, validators[3], resValidators[1])) 676 677 // test a swap in voting power 678 679 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 600) 680 validators[0], _ = validators[0].AddTokensFromDel(tokens) 681 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], true) 682 resValidators = app.StakingKeeper.GetBondedValidatorsByPower(ctx) 683 assert.Equal(t, max, len(resValidators)) 684 assert.True(ValEq(t, validators[0], resValidators[0])) 685 assert.True(ValEq(t, validators[2], resValidators[1])) 686 } 687 688 func TestApplyAndReturnValidatorSetUpdatesAllNone(t *testing.T) { 689 app, ctx, _, _ := bootstrapValidatorTest(t, 1000, 20) 690 691 powers := []int64{10, 20} 692 var validators [2]types.Validator 693 for i, power := range powers { 694 valPubKey := PKs[i+1] 695 valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) 696 697 validators[i] = teststaking.NewValidator(t, valAddr, valPubKey) 698 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 699 validators[i], _ = validators[i].AddTokensFromDel(tokens) 700 } 701 702 // test from nothing to something 703 // tendermintUpdate set: {} -> {c1, c3} 704 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0) 705 app.StakingKeeper.SetValidator(ctx, validators[0]) 706 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[0]) 707 app.StakingKeeper.SetValidator(ctx, validators[1]) 708 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[1]) 709 710 updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 711 validators[0], _ = app.StakingKeeper.GetValidator(ctx, validators[0].GetOperator()) 712 validators[1], _ = app.StakingKeeper.GetValidator(ctx, validators[1].GetOperator()) 713 assert.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1]) 714 assert.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 715 } 716 717 func TestApplyAndReturnValidatorSetUpdatesIdentical(t *testing.T) { 718 app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20) 719 720 powers := []int64{10, 20} 721 var validators [2]types.Validator 722 for i, power := range powers { 723 validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) 724 725 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 726 validators[i], _ = validators[i].AddTokensFromDel(tokens) 727 728 } 729 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false) 730 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false) 731 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 732 733 // test identical, 734 // tendermintUpdate set: {} -> {} 735 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false) 736 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false) 737 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0) 738 } 739 740 func TestApplyAndReturnValidatorSetUpdatesSingleValueChange(t *testing.T) { 741 app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20) 742 743 powers := []int64{10, 20} 744 var validators [2]types.Validator 745 for i, power := range powers { 746 validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) 747 748 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 749 validators[i], _ = validators[i].AddTokensFromDel(tokens) 750 751 } 752 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false) 753 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false) 754 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 755 756 // test single value change 757 // tendermintUpdate set: {} -> {c1'} 758 validators[0].Status = types.Bonded 759 validators[0].Tokens = app.StakingKeeper.TokensFromConsensusPower(ctx, 600) 760 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false) 761 762 updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1) 763 require.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 764 } 765 766 func TestApplyAndReturnValidatorSetUpdatesMultipleValueChange(t *testing.T) { 767 powers := []int64{10, 20} 768 // TODO: use it in other places 769 app, ctx, _, _, validators := initValidators(t, 1000, 20, powers) 770 771 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false) 772 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false) 773 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 774 775 // test multiple value change 776 // tendermintUpdate set: {c1, c3} -> {c1', c3'} 777 delTokens1 := app.StakingKeeper.TokensFromConsensusPower(ctx, 190) 778 delTokens2 := app.StakingKeeper.TokensFromConsensusPower(ctx, 80) 779 validators[0], _ = validators[0].AddTokensFromDel(delTokens1) 780 validators[1], _ = validators[1].AddTokensFromDel(delTokens2) 781 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false) 782 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false) 783 784 updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 785 require.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 786 require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1]) 787 } 788 789 func TestApplyAndReturnValidatorSetUpdatesInserted(t *testing.T) { 790 powers := []int64{10, 20, 5, 15, 25} 791 app, ctx, _, _, validators := initValidators(t, 1000, 20, powers) 792 793 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false) 794 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false) 795 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 796 797 // test validtor added at the beginning 798 // tendermintUpdate set: {} -> {c0} 799 app.StakingKeeper.SetValidator(ctx, validators[2]) 800 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[2]) 801 updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1) 802 validators[2], _ = app.StakingKeeper.GetValidator(ctx, validators[2].GetOperator()) 803 require.Equal(t, validators[2].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 804 805 // test validtor added at the beginning 806 // tendermintUpdate set: {} -> {c0} 807 app.StakingKeeper.SetValidator(ctx, validators[3]) 808 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[3]) 809 updates = applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1) 810 validators[3], _ = app.StakingKeeper.GetValidator(ctx, validators[3].GetOperator()) 811 require.Equal(t, validators[3].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 812 813 // test validtor added at the end 814 // tendermintUpdate set: {} -> {c0} 815 app.StakingKeeper.SetValidator(ctx, validators[4]) 816 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[4]) 817 updates = applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1) 818 validators[4], _ = app.StakingKeeper.GetValidator(ctx, validators[4].GetOperator()) 819 require.Equal(t, validators[4].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 820 } 821 822 func TestApplyAndReturnValidatorSetUpdatesWithCliffValidator(t *testing.T) { 823 app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20) 824 params := types.DefaultParams() 825 params.MaxValidators = 2 826 app.StakingKeeper.SetParams(ctx, params) 827 828 powers := []int64{10, 20, 5} 829 var validators [5]types.Validator 830 for i, power := range powers { 831 validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) 832 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 833 validators[i], _ = validators[i].AddTokensFromDel(tokens) 834 } 835 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false) 836 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false) 837 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 838 839 // test validator added at the end but not inserted in the valset 840 // tendermintUpdate set: {} -> {} 841 keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[2], false) 842 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0) 843 844 // test validator change its power and become a gotValidator (pushing out an existing) 845 // tendermintUpdate set: {} -> {c0, c4} 846 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0) 847 848 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10) 849 validators[2], _ = validators[2].AddTokensFromDel(tokens) 850 app.StakingKeeper.SetValidator(ctx, validators[2]) 851 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[2]) 852 updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 853 validators[2], _ = app.StakingKeeper.GetValidator(ctx, validators[2].GetOperator()) 854 require.Equal(t, validators[0].ABCIValidatorUpdateZero(), updates[1]) 855 require.Equal(t, validators[2].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 856 } 857 858 func TestApplyAndReturnValidatorSetUpdatesPowerDecrease(t *testing.T) { 859 app, ctx, addrs, _ := bootstrapValidatorTest(t, 1000, 20) 860 861 powers := []int64{100, 100} 862 var validators [2]types.Validator 863 for i, power := range powers { 864 validators[i] = teststaking.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) 865 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 866 validators[i], _ = validators[i].AddTokensFromDel(tokens) 867 } 868 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false) 869 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false) 870 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 871 872 // check initial power 873 require.Equal(t, int64(100), validators[0].GetConsensusPower(app.StakingKeeper.PowerReduction(ctx))) 874 require.Equal(t, int64(100), validators[1].GetConsensusPower(app.StakingKeeper.PowerReduction(ctx))) 875 876 // test multiple value change 877 // tendermintUpdate set: {c1, c3} -> {c1', c3'} 878 delTokens1 := app.StakingKeeper.TokensFromConsensusPower(ctx, 20) 879 delTokens2 := app.StakingKeeper.TokensFromConsensusPower(ctx, 30) 880 validators[0], _ = validators[0].RemoveDelShares(delTokens1.ToDec()) 881 validators[1], _ = validators[1].RemoveDelShares(delTokens2.ToDec()) 882 validators[0] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[0], false) 883 validators[1] = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validators[1], false) 884 885 // power has changed 886 require.Equal(t, int64(80), validators[0].GetConsensusPower(app.StakingKeeper.PowerReduction(ctx))) 887 require.Equal(t, int64(70), validators[1].GetConsensusPower(app.StakingKeeper.PowerReduction(ctx))) 888 889 // Tendermint updates should reflect power change 890 updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 891 require.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 892 require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1]) 893 } 894 895 func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) { 896 app, ctx, _, _ := bootstrapValidatorTest(t, 1000, 20) 897 params := app.StakingKeeper.GetParams(ctx) 898 params.MaxValidators = uint32(3) 899 900 app.StakingKeeper.SetParams(ctx, params) 901 902 powers := []int64{100, 100} 903 var validators [2]types.Validator 904 905 // initialize some validators into the state 906 for i, power := range powers { 907 valPubKey := PKs[i+1] 908 valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) 909 910 validators[i] = teststaking.NewValidator(t, valAddr, valPubKey) 911 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 912 validators[i], _ = validators[i].AddTokensFromDel(tokens) 913 914 app.StakingKeeper.SetValidator(ctx, validators[i]) 915 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[i]) 916 } 917 918 // verify initial Tendermint updates are correct 919 updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, len(validators)) 920 validators[0], _ = app.StakingKeeper.GetValidator(ctx, validators[0].GetOperator()) 921 validators[1], _ = app.StakingKeeper.GetValidator(ctx, validators[1].GetOperator()) 922 require.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 923 require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1]) 924 925 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0) 926 927 // update initial validator set 928 for i, power := range powers { 929 930 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[i]) 931 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 932 validators[i], _ = validators[i].AddTokensFromDel(tokens) 933 934 app.StakingKeeper.SetValidator(ctx, validators[i]) 935 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[i]) 936 } 937 938 // add a new validator that goes from zero power, to non-zero power, back to 939 // zero power 940 valPubKey := PKs[len(validators)+1] 941 valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) 942 amt := sdk.NewInt(100) 943 944 validator := teststaking.NewValidator(t, valAddr, valPubKey) 945 validator, _ = validator.AddTokensFromDel(amt) 946 947 app.StakingKeeper.SetValidator(ctx, validator) 948 949 validator, _ = validator.RemoveDelShares(amt.ToDec()) 950 app.StakingKeeper.SetValidator(ctx, validator) 951 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validator) 952 953 // add a new validator that increases in power 954 valPubKey = PKs[len(validators)+2] 955 valAddr = sdk.ValAddress(valPubKey.Address().Bytes()) 956 957 validator = teststaking.NewValidator(t, valAddr, valPubKey) 958 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 500) 959 validator, _ = validator.AddTokensFromDel(tokens) 960 app.StakingKeeper.SetValidator(ctx, validator) 961 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validator) 962 963 // verify initial Tendermint updates are correct 964 updates = applyValidatorSetUpdates(t, ctx, app.StakingKeeper, len(validators)+1) 965 validator, _ = app.StakingKeeper.GetValidator(ctx, validator.GetOperator()) 966 validators[0], _ = app.StakingKeeper.GetValidator(ctx, validators[0].GetOperator()) 967 validators[1], _ = app.StakingKeeper.GetValidator(ctx, validators[1].GetOperator()) 968 require.Equal(t, validator.ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 969 require.Equal(t, validators[0].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1]) 970 require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[2]) 971 } 972 973 func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) { 974 app, ctx, _, _ := bootstrapValidatorTest(t, 1000, 20) 975 params := app.StakingKeeper.GetParams(ctx) 976 params.MaxValidators = uint32(2) 977 978 app.StakingKeeper.SetParams(ctx, params) 979 980 powers := []int64{100, 200, 300} 981 var validators [3]types.Validator 982 983 // initialize some validators into the state 984 for i, power := range powers { 985 moniker := fmt.Sprintf("%d", i) 986 valPubKey := PKs[i+1] 987 valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) 988 989 validators[i] = newMonikerValidator(t, valAddr, valPubKey, moniker) 990 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 991 validators[i], _ = validators[i].AddTokensFromDel(tokens) 992 app.StakingKeeper.SetValidator(ctx, validators[i]) 993 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[i]) 994 } 995 996 // verify initial Tendermint updates are correct 997 updates := applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 2) 998 validators[2], _ = app.StakingKeeper.GetValidator(ctx, validators[2].GetOperator()) 999 validators[1], _ = app.StakingKeeper.GetValidator(ctx, validators[1].GetOperator()) 1000 require.Equal(t, validators[2].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 1001 require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[1]) 1002 1003 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0) 1004 1005 // delegate to validator with lowest power but not enough to bond 1006 ctx = ctx.WithBlockHeight(1) 1007 1008 var found bool 1009 validators[0], found = app.StakingKeeper.GetValidator(ctx, validators[0].GetOperator()) 1010 require.True(t, found) 1011 1012 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[0]) 1013 tokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 1) 1014 validators[0], _ = validators[0].AddTokensFromDel(tokens) 1015 app.StakingKeeper.SetValidator(ctx, validators[0]) 1016 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[0]) 1017 1018 // verify initial Tendermint updates are correct 1019 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0) 1020 1021 // create a series of events that will bond and unbond the validator with 1022 // lowest power in a single block context (height) 1023 ctx = ctx.WithBlockHeight(2) 1024 1025 validators[1], found = app.StakingKeeper.GetValidator(ctx, validators[1].GetOperator()) 1026 require.True(t, found) 1027 1028 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[0]) 1029 validators[0], _ = validators[0].RemoveDelShares(validators[0].DelegatorShares) 1030 app.StakingKeeper.SetValidator(ctx, validators[0]) 1031 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[0]) 1032 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0) 1033 1034 app.StakingKeeper.DeleteValidatorByPowerIndex(ctx, validators[1]) 1035 tokens = app.StakingKeeper.TokensFromConsensusPower(ctx, 250) 1036 validators[1], _ = validators[1].AddTokensFromDel(tokens) 1037 app.StakingKeeper.SetValidator(ctx, validators[1]) 1038 app.StakingKeeper.SetValidatorByPowerIndex(ctx, validators[1]) 1039 1040 // verify initial Tendermint updates are correct 1041 updates = applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 1) 1042 require.Equal(t, validators[1].ABCIValidatorUpdate(app.StakingKeeper.PowerReduction(ctx)), updates[0]) 1043 1044 applyValidatorSetUpdates(t, ctx, app.StakingKeeper, 0) 1045 } 1046 1047 func TestUpdateValidatorCommission(t *testing.T) { 1048 app, ctx, _, addrVals := bootstrapValidatorTest(t, 1000, 20) 1049 ctx = ctx.WithBlockHeader(tmproto.Header{Time: time.Now().UTC()}) 1050 1051 commission1 := types.NewCommissionWithTime( 1052 sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(3, 1), 1053 sdk.NewDecWithPrec(1, 1), time.Now().UTC().Add(time.Duration(-1)*time.Hour), 1054 ) 1055 commission2 := types.NewCommission(sdk.NewDecWithPrec(1, 1), sdk.NewDecWithPrec(3, 1), sdk.NewDecWithPrec(1, 1)) 1056 1057 val1 := teststaking.NewValidator(t, addrVals[0], PKs[0]) 1058 val2 := teststaking.NewValidator(t, addrVals[1], PKs[1]) 1059 1060 val1, _ = val1.SetInitialCommission(commission1) 1061 val2, _ = val2.SetInitialCommission(commission2) 1062 1063 app.StakingKeeper.SetValidator(ctx, val1) 1064 app.StakingKeeper.SetValidator(ctx, val2) 1065 1066 testCases := []struct { 1067 validator types.Validator 1068 newRate sdk.Dec 1069 expectedErr bool 1070 }{ 1071 {val1, sdk.ZeroDec(), true}, 1072 {val2, sdk.NewDecWithPrec(-1, 1), true}, 1073 {val2, sdk.NewDecWithPrec(4, 1), true}, 1074 {val2, sdk.NewDecWithPrec(3, 1), true}, 1075 {val2, sdk.NewDecWithPrec(2, 1), false}, 1076 } 1077 1078 for i, tc := range testCases { 1079 commission, err := app.StakingKeeper.UpdateValidatorCommission(ctx, tc.validator, tc.newRate) 1080 1081 if tc.expectedErr { 1082 require.Error(t, err, "expected error for test case #%d with rate: %s", i, tc.newRate) 1083 } else { 1084 tc.validator.Commission = commission 1085 app.StakingKeeper.SetValidator(ctx, tc.validator) 1086 val, found := app.StakingKeeper.GetValidator(ctx, tc.validator.GetOperator()) 1087 1088 require.True(t, found, 1089 "expected to find validator for test case #%d with rate: %s", i, tc.newRate, 1090 ) 1091 require.NoError(t, err, 1092 "unexpected error for test case #%d with rate: %s", i, tc.newRate, 1093 ) 1094 require.Equal(t, tc.newRate, val.Commission.Rate, 1095 "expected new validator commission rate for test case #%d with rate: %s", i, tc.newRate, 1096 ) 1097 require.Equal(t, ctx.BlockHeader().Time, val.Commission.UpdateTime, 1098 "expected new validator commission update time for test case #%d with rate: %s", i, tc.newRate, 1099 ) 1100 } 1101 } 1102 } 1103 1104 func applyValidatorSetUpdates(t *testing.T, ctx sdk.Context, k keeper.Keeper, expectedUpdatesLen int) []abci.ValidatorUpdate { 1105 t.Helper() 1106 updates, err := k.ApplyAndReturnValidatorSetUpdates(ctx) 1107 require.NoError(t, err) 1108 if expectedUpdatesLen >= 0 { 1109 require.Equal(t, expectedUpdatesLen, len(updates), "%v", updates) 1110 } 1111 return updates 1112 }