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