github.com/Finschia/finschia-sdk@v0.48.1/x/staking/handler_test.go (about) 1 package staking_test 2 3 import ( 4 "strings" 5 "testing" 6 "time" 7 8 octypes "github.com/Finschia/ostracon/types" 9 "github.com/golang/protobuf/proto" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 abci "github.com/tendermint/tendermint/abci/types" 13 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 14 15 cryptocodec "github.com/Finschia/finschia-sdk/crypto/codec" 16 "github.com/Finschia/finschia-sdk/crypto/keys/ed25519" 17 "github.com/Finschia/finschia-sdk/crypto/keys/secp256k1" 18 cryptotypes "github.com/Finschia/finschia-sdk/crypto/types" 19 "github.com/Finschia/finschia-sdk/simapp" 20 "github.com/Finschia/finschia-sdk/testutil/testdata" 21 sdk "github.com/Finschia/finschia-sdk/types" 22 "github.com/Finschia/finschia-sdk/x/staking" 23 "github.com/Finschia/finschia-sdk/x/staking/keeper" 24 "github.com/Finschia/finschia-sdk/x/staking/teststaking" 25 "github.com/Finschia/finschia-sdk/x/staking/types" 26 ) 27 28 func bootstrapHandlerGenesisTest(t *testing.T, power int64, numAddrs int, accAmount sdk.Int) (*simapp.SimApp, sdk.Context, []sdk.AccAddress, []sdk.ValAddress) { 29 _, app, ctx := getBaseSimappWithCustomKeeper() 30 31 addrDels, addrVals := generateAddresses(app, ctx, numAddrs, accAmount) 32 33 amt := app.StakingKeeper.TokensFromConsensusPower(ctx, power) 34 totalSupply := sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), amt.MulRaw(int64(len(addrDels))))) 35 36 notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx) 37 38 // set non bonded pool balance 39 app.AccountKeeper.SetModuleAccount(ctx, notBondedPool) 40 require.NoError(t, simapp.FundModuleAccount(app, ctx, notBondedPool.GetName(), totalSupply)) 41 return app, ctx, addrDels, addrVals 42 } 43 44 func TestValidatorByPowerIndex(t *testing.T) { 45 initPower := int64(1000000) 46 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 10, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 47 validatorAddr, validatorAddr3 := valAddrs[0], valAddrs[1] 48 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 49 50 // create validator 51 initBond := tstaking.CreateValidatorWithValPower(validatorAddr, PKs[0], initPower, true) 52 53 // must end-block 54 updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 55 require.NoError(t, err) 56 require.Equal(t, 1, len(updates)) 57 58 // verify the self-delegation exists 59 bond, found := app.StakingKeeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) 60 require.True(t, found) 61 gotBond := bond.Shares.RoundInt() 62 require.Equal(t, initBond, gotBond) 63 64 // verify that the by power index exists 65 validator, found := app.StakingKeeper.GetValidator(ctx, validatorAddr) 66 require.True(t, found) 67 power := types.GetValidatorsByPowerIndexKey(validator, app.StakingKeeper.PowerReduction(ctx)) 68 require.True(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power)) 69 70 // create a second validator keep it bonded 71 tstaking.CreateValidatorWithValPower(validatorAddr3, PKs[2], initPower, true) 72 73 // must end-block 74 updates, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 75 require.NoError(t, err) 76 require.Equal(t, 1, len(updates)) 77 78 // slash and jail the first validator 79 consAddr0 := sdk.ConsAddress(PKs[0].Address()) 80 app.StakingKeeper.Slash(ctx, consAddr0, 0, initPower, sdk.NewDecWithPrec(5, 1)) 81 app.StakingKeeper.Jail(ctx, consAddr0) 82 app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 83 84 validator, found = app.StakingKeeper.GetValidator(ctx, validatorAddr) 85 require.True(t, found) 86 require.Equal(t, types.Unbonding, validator.Status) // ensure is unbonding 87 require.Equal(t, initBond.QuoRaw(2), validator.Tokens) // ensure tokens slashed 88 app.StakingKeeper.Unjail(ctx, consAddr0) 89 90 // the old power record should have been deleted as the power changed 91 require.False(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power)) 92 93 // but the new power record should have been created 94 validator, found = app.StakingKeeper.GetValidator(ctx, validatorAddr) 95 require.True(t, found) 96 power2 := types.GetValidatorsByPowerIndexKey(validator, app.StakingKeeper.PowerReduction(ctx)) 97 require.True(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power2)) 98 99 // now the new record power index should be the same as the original record 100 power3 := types.GetValidatorsByPowerIndexKey(validator, app.StakingKeeper.PowerReduction(ctx)) 101 require.Equal(t, power2, power3) 102 103 // unbond self-delegation 104 totalBond := validator.TokensFromShares(bond.GetShares()).TruncateInt() 105 res := tstaking.Undelegate(sdk.AccAddress(validatorAddr), validatorAddr, totalBond, true) 106 107 var resData types.MsgUndelegateResponse 108 err = proto.Unmarshal(res.Data, &resData) 109 require.NoError(t, err) 110 111 ctx = ctx.WithBlockTime(resData.CompletionTime) 112 staking.EndBlocker(ctx, app.StakingKeeper) 113 staking.EndBlocker(ctx, app.StakingKeeper) 114 115 // verify that by power key nolonger exists 116 _, found = app.StakingKeeper.GetValidator(ctx, validatorAddr) 117 require.False(t, found) 118 require.False(t, keeper.ValidatorByPowerIndexExists(ctx, app.StakingKeeper, power3)) 119 } 120 121 func TestDuplicatesMsgCreateValidator(t *testing.T) { 122 initPower := int64(1000000) 123 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 10, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 124 125 addr1, addr2 := valAddrs[0], valAddrs[1] 126 pk1, pk2 := PKs[0], PKs[1] 127 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 128 129 valTokens := tstaking.CreateValidatorWithValPower(addr1, pk1, 10, true) 130 app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 131 132 validator := tstaking.CheckValidator(addr1, types.Bonded, false) 133 assert.Equal(t, addr1.String(), validator.OperatorAddress) 134 consKey, err := validator.OcConsPublicKey() 135 require.NoError(t, err) 136 tmPk1, err := cryptocodec.ToOcProtoPublicKey(pk1) 137 require.NoError(t, err) 138 assert.Equal(t, tmPk1, consKey) 139 assert.Equal(t, valTokens, validator.BondedTokens()) 140 assert.Equal(t, valTokens.ToDec(), validator.DelegatorShares) 141 assert.Equal(t, types.Description{}, validator.Description) 142 143 // two validators can't have the same operator address 144 tstaking.CreateValidator(addr1, pk2, valTokens, false) 145 146 // two validators can't have the same pubkey 147 tstaking.CreateValidator(addr2, pk1, valTokens, false) 148 149 // must have different pubkey and operator 150 tstaking.CreateValidator(addr2, pk2, valTokens, true) 151 152 // must end-block 153 updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 154 require.NoError(t, err) 155 require.Equal(t, 1, len(updates)) 156 157 validator = tstaking.CheckValidator(addr2, types.Bonded, false) 158 assert.Equal(t, addr2.String(), validator.OperatorAddress) 159 consPk, err := validator.OcConsPublicKey() 160 require.NoError(t, err) 161 tmPk2, err := cryptocodec.ToOcProtoPublicKey(pk2) 162 require.NoError(t, err) 163 assert.Equal(t, tmPk2, consPk) 164 assert.True(sdk.IntEq(t, valTokens, validator.Tokens)) 165 assert.True(sdk.DecEq(t, valTokens.ToDec(), validator.DelegatorShares)) 166 assert.Equal(t, types.Description{}, validator.Description) 167 } 168 169 func TestInvalidPubKeyTypeMsgCreateValidator(t *testing.T) { 170 initPower := int64(1000) 171 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 1, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 172 ctx = ctx.WithConsensusParams(&abci.ConsensusParams{ 173 Validator: &tmproto.ValidatorParams{PubKeyTypes: []string{octypes.ABCIPubKeyTypeEd25519}}, 174 }) 175 176 addr := valAddrs[0] 177 invalidPk := secp256k1.GenPrivKey().PubKey() 178 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 179 180 // invalid pukKey type should not be allowed 181 tstaking.CreateValidator(addr, invalidPk, sdk.NewInt(10), false) 182 } 183 184 func TestBothPubKeyTypesMsgCreateValidator(t *testing.T) { 185 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, 1000, 2, sdk.NewInt(1000)) 186 ctx = ctx.WithConsensusParams(&abci.ConsensusParams{ 187 Validator: &tmproto.ValidatorParams{PubKeyTypes: []string{octypes.ABCIPubKeyTypeEd25519, octypes.ABCIPubKeyTypeSecp256k1}}, 188 }) 189 190 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 191 192 testCases := []struct { 193 name string 194 addr sdk.ValAddress 195 pk cryptotypes.PubKey 196 }{ 197 { 198 "can create a validator with ed25519 pubkey", 199 valAddrs[0], 200 ed25519.GenPrivKey().PubKey(), 201 }, 202 { 203 "can create a validator with secp256k1 pubkey", 204 valAddrs[1], 205 secp256k1.GenPrivKey().PubKey(), 206 }, 207 } 208 for _, tc := range testCases { 209 t.Run(tc.name, func(*testing.T) { 210 tstaking.CreateValidator(tc.addr, tc.pk, sdk.NewInt(10), true) 211 }) 212 } 213 } 214 215 func TestLegacyValidatorDelegations(t *testing.T) { 216 initPower := int64(1000) 217 app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 218 219 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 220 valAddr := valAddrs[0] 221 valConsPubKey, valConsAddr := PKs[0], sdk.ConsAddress(PKs[0].Address()) 222 delAddr := delAddrs[1] 223 224 // create validator 225 bondAmount := tstaking.CreateValidatorWithValPower(valAddr, valConsPubKey, 10, true) 226 227 // must end-block 228 updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 229 require.NoError(t, err) 230 require.Equal(t, 1, len(updates)) 231 232 // verify the validator exists and has the correct attributes 233 validator := tstaking.CheckValidator(valAddr, types.Bonded, false) 234 require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt()) 235 require.Equal(t, bondAmount, validator.BondedTokens()) 236 237 // delegate tokens to the validator 238 tstaking.Delegate(delAddr, valAddr, bondAmount) 239 240 // verify validator bonded shares 241 validator = tstaking.CheckValidator(valAddr, types.Bonded, false) 242 require.Equal(t, bondAmount.MulRaw(2), validator.DelegatorShares.RoundInt()) 243 require.Equal(t, bondAmount.MulRaw(2), validator.BondedTokens()) 244 245 // unbond validator total self-delegations (which should jail the validator) 246 res := tstaking.Undelegate(sdk.AccAddress(valAddr), valAddr, bondAmount, true) 247 248 var resData types.MsgUndelegateResponse 249 err = proto.Unmarshal(res.Data, &resData) 250 require.NoError(t, err) 251 252 ctx = ctx.WithBlockTime(resData.CompletionTime) 253 tstaking.Ctx = ctx 254 staking.EndBlocker(ctx, app.StakingKeeper) 255 256 // verify the validator record still exists, is jailed, and has correct tokens 257 validator = tstaking.CheckValidator(valAddr, -1, true) 258 require.Equal(t, bondAmount, validator.Tokens) 259 260 // verify delegation still exists 261 bond, found := app.StakingKeeper.GetDelegation(ctx, delAddr, valAddr) 262 require.True(t, found) 263 require.Equal(t, bondAmount, bond.Shares.RoundInt()) 264 require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt()) 265 266 // verify the validator can still self-delegate 267 tstaking.Delegate(sdk.AccAddress(valAddr), valAddr, bondAmount) 268 269 // verify validator bonded shares 270 validator, found = app.StakingKeeper.GetValidator(ctx, valAddr) 271 require.True(t, found) 272 require.Equal(t, bondAmount.MulRaw(2), validator.DelegatorShares.RoundInt()) 273 require.Equal(t, bondAmount.MulRaw(2), validator.Tokens) 274 275 // unjail the validator now that is has non-zero self-delegated shares 276 app.StakingKeeper.Unjail(ctx, valConsAddr) 277 278 // verify the validator can now accept delegations 279 tstaking.Delegate(delAddr, valAddr, bondAmount) 280 281 // verify validator bonded shares 282 validator, found = app.StakingKeeper.GetValidator(ctx, valAddr) 283 require.True(t, found) 284 require.Equal(t, bondAmount.MulRaw(3), validator.DelegatorShares.RoundInt()) 285 require.Equal(t, bondAmount.MulRaw(3), validator.Tokens) 286 287 // verify new delegation 288 bond, found = app.StakingKeeper.GetDelegation(ctx, delAddr, valAddr) 289 require.True(t, found) 290 require.Equal(t, bondAmount.MulRaw(2), bond.Shares.RoundInt()) 291 require.Equal(t, bondAmount.MulRaw(3), validator.DelegatorShares.RoundInt()) 292 } 293 294 func TestIncrementsMsgDelegate(t *testing.T) { 295 initPower := int64(1000) 296 initBond := sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction) 297 app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 298 299 params := app.StakingKeeper.GetParams(ctx) 300 validatorAddr, delegatorAddr := valAddrs[0], delAddrs[1] 301 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 302 303 // first create validator 304 bondAmount := tstaking.CreateValidatorWithValPower(validatorAddr, PKs[0], 10, true) 305 306 // apply TM updates 307 app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 308 309 validator := tstaking.CheckValidator(validatorAddr, types.Bonded, false) 310 require.Equal(t, bondAmount, validator.DelegatorShares.RoundInt()) 311 require.Equal(t, bondAmount, validator.BondedTokens(), "validator: %v", validator) 312 313 tstaking.CheckDelegator(delegatorAddr, validatorAddr, false) 314 315 bond, found := app.StakingKeeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) 316 require.True(t, found) 317 require.Equal(t, bondAmount, bond.Shares.RoundInt()) 318 319 bondedTokens := app.StakingKeeper.TotalBondedTokens(ctx) 320 require.Equal(t, bondAmount, bondedTokens) 321 322 for i := int64(0); i < 5; i++ { 323 ctx = ctx.WithBlockHeight(i) 324 tstaking.Ctx = ctx 325 tstaking.Delegate(delegatorAddr, validatorAddr, bondAmount) 326 327 // Check that the accounts and the bond account have the appropriate values 328 validator, found := app.StakingKeeper.GetValidator(ctx, validatorAddr) 329 require.True(t, found) 330 bond, found := app.StakingKeeper.GetDelegation(ctx, delegatorAddr, validatorAddr) 331 require.True(t, found) 332 333 expBond := bondAmount.MulRaw(i + 1) 334 expDelegatorShares := bondAmount.MulRaw(i + 2) // (1 self delegation) 335 expDelegatorAcc := initBond.Sub(expBond) 336 337 gotBond := bond.Shares.RoundInt() 338 gotDelegatorShares := validator.DelegatorShares.RoundInt() 339 gotDelegatorAcc := app.BankKeeper.GetBalance(ctx, delegatorAddr, params.BondDenom).Amount 340 341 require.Equal(t, expBond, gotBond, 342 "i: %v\nexpBond: %v\ngotBond: %v\nvalidator: %v\nbond: %v\n", 343 i, expBond, gotBond, validator, bond) 344 require.Equal(t, expDelegatorShares, gotDelegatorShares, 345 "i: %v\nexpDelegatorShares: %v\ngotDelegatorShares: %v\nvalidator: %v\nbond: %v\n", 346 i, expDelegatorShares, gotDelegatorShares, validator, bond) 347 require.Equal(t, expDelegatorAcc, gotDelegatorAcc, 348 "i: %v\nexpDelegatorAcc: %v\ngotDelegatorAcc: %v\nvalidator: %v\nbond: %v\n", 349 i, expDelegatorAcc, gotDelegatorAcc, validator, bond) 350 } 351 } 352 353 func TestEditValidatorDecreaseMinSelfDelegation(t *testing.T) { 354 initPower := int64(100) 355 initBond := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction) 356 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 1, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 357 358 validatorAddr := valAddrs[0] 359 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 360 361 // create validator 362 msgCreateValidator := tstaking.CreateValidatorMsg(validatorAddr, PKs[0], initBond) 363 msgCreateValidator.MinSelfDelegation = sdk.NewInt(2) 364 tstaking.Handle(msgCreateValidator, true) 365 366 // must end-block 367 updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 368 require.NoError(t, err) 369 require.Equal(t, 1, len(updates)) 370 371 // verify the self-delegation exists 372 bond, found := app.StakingKeeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) 373 require.True(t, found) 374 gotBond := bond.Shares.RoundInt() 375 require.Equal(t, initBond, gotBond, 376 "initBond: %v\ngotBond: %v\nbond: %v\n", 377 initBond, gotBond, bond) 378 379 newMinSelfDelegation := sdk.OneInt() 380 msgEditValidator := types.NewMsgEditValidator(validatorAddr, types.Description{}, nil, &newMinSelfDelegation) 381 tstaking.Handle(msgEditValidator, false) 382 } 383 384 func TestEditValidatorIncreaseMinSelfDelegationBeyondCurrentBond(t *testing.T) { 385 initPower := int64(100) 386 initBond := sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction) 387 388 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 389 validatorAddr := valAddrs[0] 390 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 391 392 // create validator 393 msgCreateValidator := tstaking.CreateValidatorMsg(validatorAddr, PKs[0], initBond) 394 msgCreateValidator.MinSelfDelegation = sdk.NewInt(2) 395 tstaking.Handle(msgCreateValidator, true) 396 397 // must end-block 398 updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 399 require.NoError(t, err) 400 require.Equal(t, 1, len(updates)) 401 402 // verify the self-delegation exists 403 bond, found := app.StakingKeeper.GetDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) 404 require.True(t, found) 405 gotBond := bond.Shares.RoundInt() 406 require.Equal(t, initBond, gotBond, 407 "initBond: %v\ngotBond: %v\nbond: %v\n", 408 initBond, gotBond, bond) 409 410 newMinSelfDelegation := initBond.Add(sdk.OneInt()) 411 msgEditValidator := types.NewMsgEditValidator(validatorAddr, types.Description{}, nil, &newMinSelfDelegation) 412 tstaking.Handle(msgEditValidator, false) 413 } 414 415 func TestIncrementsMsgUnbond(t *testing.T) { 416 initPower := int64(1000) 417 418 app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 419 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 420 params := app.StakingKeeper.GetParams(ctx) 421 denom := params.BondDenom 422 423 // create validator, delegate 424 validatorAddr, delegatorAddr := valAddrs[0], delAddrs[1] 425 initBond := tstaking.CreateValidatorWithValPower(validatorAddr, PKs[0], initPower, true) 426 427 // initial balance 428 amt1 := app.BankKeeper.GetBalance(ctx, delegatorAddr, denom).Amount 429 430 tstaking.Delegate(delegatorAddr, validatorAddr, initBond) 431 432 // balance should have been subtracted after delegation 433 amt2 := app.BankKeeper.GetBalance(ctx, delegatorAddr, denom).Amount 434 require.True(sdk.IntEq(t, amt1.Sub(initBond), amt2)) 435 436 // apply TM updates 437 app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 438 439 validator, found := app.StakingKeeper.GetValidator(ctx, validatorAddr) 440 require.True(t, found) 441 require.Equal(t, initBond.MulRaw(2), validator.DelegatorShares.RoundInt()) 442 require.Equal(t, initBond.MulRaw(2), validator.BondedTokens()) 443 444 // just send the same msgUnbond multiple times 445 // TODO use decimals here 446 unbondAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)) 447 msgUndelegate := types.NewMsgUndelegate(delegatorAddr, validatorAddr, unbondAmt) 448 numUnbonds := int64(5) 449 450 for i := int64(0); i < numUnbonds; i++ { 451 res := tstaking.Handle(msgUndelegate, true) 452 453 var resData types.MsgUndelegateResponse 454 err := proto.Unmarshal(res.Data, &resData) 455 require.NoError(t, err) 456 457 ctx = ctx.WithBlockTime(resData.CompletionTime) 458 tstaking.Ctx = ctx 459 staking.EndBlocker(ctx, app.StakingKeeper) 460 461 // check that the accounts and the bond account have the appropriate values 462 validator, found = app.StakingKeeper.GetValidator(ctx, validatorAddr) 463 require.True(t, found) 464 bond, found := app.StakingKeeper.GetDelegation(ctx, delegatorAddr, validatorAddr) 465 require.True(t, found) 466 467 expBond := initBond.Sub(unbondAmt.Amount.Mul(sdk.NewInt(i + 1))) 468 expDelegatorShares := initBond.MulRaw(2).Sub(unbondAmt.Amount.Mul(sdk.NewInt(i + 1))) 469 expDelegatorAcc := initBond.Sub(expBond) 470 471 gotBond := bond.Shares.RoundInt() 472 gotDelegatorShares := validator.DelegatorShares.RoundInt() 473 gotDelegatorAcc := app.BankKeeper.GetBalance(ctx, delegatorAddr, params.BondDenom).Amount 474 475 require.Equal(t, expBond, gotBond, 476 "i: %v\nexpBond: %v\ngotBond: %v\nvalidator: %v\nbond: %v\n", 477 i, expBond, gotBond, validator, bond) 478 require.Equal(t, expDelegatorShares, gotDelegatorShares, 479 "i: %v\nexpDelegatorShares: %v\ngotDelegatorShares: %v\nvalidator: %v\nbond: %v\n", 480 i, expDelegatorShares, gotDelegatorShares, validator, bond) 481 require.Equal(t, expDelegatorAcc, gotDelegatorAcc, 482 "i: %v\nexpDelegatorAcc: %v\ngotDelegatorAcc: %v\nvalidator: %v\nbond: %v\n", 483 i, expDelegatorAcc, gotDelegatorAcc, validator, bond) 484 } 485 486 // these are more than we have bonded now 487 errorCases := []sdk.Int{ 488 // 1<<64 - 1, // more than int64 power 489 // 1<<63 + 1, // more than int64 power 490 app.StakingKeeper.TokensFromConsensusPower(ctx, 1<<63-1), 491 app.StakingKeeper.TokensFromConsensusPower(ctx, 1<<31), 492 initBond, 493 } 494 495 for _, c := range errorCases { 496 tstaking.Undelegate(delegatorAddr, validatorAddr, c, false) 497 } 498 499 // should be able to unbond remaining 500 leftBonded := initBond.Sub(unbondAmt.Amount.Mul(sdk.NewInt(numUnbonds))) 501 tstaking.Undelegate(delegatorAddr, validatorAddr, leftBonded, true) 502 } 503 504 func TestMultipleMsgCreateValidator(t *testing.T) { 505 initPower := int64(1000) 506 initTokens := sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction) 507 app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 3, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 508 509 params := app.StakingKeeper.GetParams(ctx) 510 blockTime := time.Now().UTC() 511 ctx = ctx.WithBlockTime(blockTime) 512 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 513 514 validatorAddrs := []sdk.ValAddress{ 515 valAddrs[0], 516 valAddrs[1], 517 valAddrs[2], 518 } 519 delegatorAddrs := []sdk.AccAddress{ 520 delAddrs[0], 521 delAddrs[1], 522 delAddrs[2], 523 } 524 525 // bond them all 526 amt := app.StakingKeeper.TokensFromConsensusPower(ctx, 10) 527 for i, validatorAddr := range validatorAddrs { 528 tstaking.CreateValidator(validatorAddr, PKs[i], amt, true) 529 // verify that the account is bonded 530 validators := app.StakingKeeper.GetValidators(ctx, 100) 531 require.Equal(t, (i + 1), len(validators)) 532 533 val := validators[i] 534 balanceExpd := initTokens.Sub(amt) 535 balanceGot := app.BankKeeper.GetBalance(ctx, delegatorAddrs[i], params.BondDenom).Amount 536 537 require.Equal(t, i+1, len(validators), "expected %d validators got %d, validators: %v", i+1, len(validators), validators) 538 require.Equal(t, amt, val.DelegatorShares.RoundInt(), "expected %d shares, got %d", amt, val.DelegatorShares) 539 require.Equal(t, balanceExpd, balanceGot, "expected account to have %d, got %d", balanceExpd, balanceGot) 540 } 541 542 staking.EndBlocker(ctx, app.StakingKeeper) 543 544 // unbond them all by removing delegation 545 for i, validatorAddr := range validatorAddrs { 546 _, found := app.StakingKeeper.GetValidator(ctx, validatorAddr) 547 require.True(t, found) 548 549 res := tstaking.Undelegate(delegatorAddrs[i], validatorAddr, amt, true) 550 551 var resData types.MsgUndelegateResponse 552 err := proto.Unmarshal(res.Data, &resData) 553 require.NoError(t, err) 554 555 // adds validator into unbonding queue 556 staking.EndBlocker(ctx, app.StakingKeeper) 557 558 // removes validator from queue and set 559 staking.EndBlocker(ctx.WithBlockTime(blockTime.Add(params.UnbondingTime)), app.StakingKeeper) 560 561 // Check that the validator is deleted from state 562 validators := app.StakingKeeper.GetValidators(ctx, 100) 563 require.Equal(t, len(validatorAddrs)-(i+1), len(validators), 564 "expected %d validators got %d", len(validatorAddrs)-(i+1), len(validators)) 565 566 _, found = app.StakingKeeper.GetValidator(ctx, validatorAddr) 567 require.False(t, found) 568 569 gotBalance := app.BankKeeper.GetBalance(ctx, delegatorAddrs[i], params.BondDenom).Amount 570 require.Equal(t, initTokens, gotBalance, "expected account to have %d, got %d", initTokens, gotBalance) 571 } 572 } 573 574 func TestMultipleMsgDelegate(t *testing.T) { 575 initPower := int64(1000) 576 app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 50, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 577 validatorAddr, delegatorAddrs := valAddrs[0], delAddrs[1:] 578 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 579 var amount int64 = 10 580 581 // first make a validator 582 tstaking.CreateValidator(validatorAddr, PKs[0], sdk.NewInt(amount), true) 583 584 // delegate multiple parties 585 for _, delegatorAddr := range delegatorAddrs { 586 tstaking.Delegate(delegatorAddr, validatorAddr, sdk.NewInt(10)) 587 tstaking.CheckDelegator(delegatorAddr, validatorAddr, true) 588 } 589 590 // unbond them all 591 for _, delegatorAddr := range delegatorAddrs { 592 res := tstaking.Undelegate(delegatorAddr, validatorAddr, sdk.NewInt(amount), true) 593 594 var resData types.MsgUndelegateResponse 595 err := proto.Unmarshal(res.Data, &resData) 596 require.NoError(t, err) 597 598 ctx = ctx.WithBlockTime(resData.CompletionTime) 599 staking.EndBlocker(ctx, app.StakingKeeper) 600 tstaking.Ctx = ctx 601 602 // check that the account is unbonded 603 _, found := app.StakingKeeper.GetDelegation(ctx, delegatorAddr, validatorAddr) 604 require.False(t, found) 605 } 606 } 607 608 func TestJailValidator(t *testing.T) { 609 initPower := int64(1000) 610 app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 611 validatorAddr, delegatorAddr := valAddrs[0], delAddrs[1] 612 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 613 var amt int64 = 10 614 615 // create the validator and delegate 616 tstaking.CreateValidator(validatorAddr, PKs[0], sdk.NewInt(amt), true) 617 tstaking.Delegate(delegatorAddr, validatorAddr, sdk.NewInt(amt)) 618 619 // unbond the validators bond portion 620 unamt := sdk.NewInt(amt) 621 res := tstaking.Undelegate(sdk.AccAddress(validatorAddr), validatorAddr, unamt, true) 622 623 var resData types.MsgUndelegateResponse 624 err := proto.Unmarshal(res.Data, &resData) 625 require.NoError(t, err) 626 627 ctx = ctx.WithBlockTime(resData.CompletionTime) 628 staking.EndBlocker(ctx, app.StakingKeeper) 629 tstaking.Ctx = ctx 630 631 tstaking.CheckValidator(validatorAddr, -1, true) 632 633 // test that the delegator can still withdraw their bonds 634 tstaking.Undelegate(delegatorAddr, validatorAddr, unamt, true) 635 636 err = proto.Unmarshal(res.Data, &resData) 637 require.NoError(t, err) 638 639 ctx = ctx.WithBlockTime(resData.CompletionTime) 640 staking.EndBlocker(ctx, app.StakingKeeper) 641 tstaking.Ctx = ctx 642 643 // verify that the pubkey can now be reused 644 tstaking.CreateValidator(validatorAddr, PKs[0], sdk.NewInt(amt), true) 645 } 646 647 func TestValidatorQueue(t *testing.T) { 648 initPower := int64(1000) 649 app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 650 validatorAddr, delegatorAddr := valAddrs[0], delAddrs[1] 651 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 652 653 // set the unbonding time 654 params := app.StakingKeeper.GetParams(ctx) 655 params.UnbondingTime = 7 * time.Second 656 app.StakingKeeper.SetParams(ctx, params) 657 658 // create the validator and make a bond 659 amt := tstaking.CreateValidatorWithValPower(validatorAddr, PKs[0], 10, true) 660 tstaking.Delegate(delegatorAddr, validatorAddr, amt) 661 staking.EndBlocker(ctx, app.StakingKeeper) 662 663 // unbond the all self-delegation to put validator in unbonding state 664 res := tstaking.Undelegate(sdk.AccAddress(validatorAddr), validatorAddr, amt, true) 665 666 var resData types.MsgUndelegateResponse 667 err := proto.Unmarshal(res.Data, &resData) 668 require.NoError(t, err) 669 670 finishTime := resData.CompletionTime 671 672 ctx = tstaking.TurnBlock(finishTime) 673 origHeader := ctx.BlockHeader() 674 675 validator, found := app.StakingKeeper.GetValidator(ctx, validatorAddr) 676 require.True(t, found) 677 require.True(t, validator.IsUnbonding(), "%v", validator) 678 679 // should still be unbonding at time 6 seconds later 680 ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 6)) 681 682 validator, found = app.StakingKeeper.GetValidator(ctx, validatorAddr) 683 require.True(t, found) 684 require.True(t, validator.IsUnbonding(), "%v", validator) 685 686 // should be in unbonded state at time 7 seconds later 687 ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 7)) 688 689 validator, found = app.StakingKeeper.GetValidator(ctx, validatorAddr) 690 require.True(t, found) 691 require.True(t, validator.IsUnbonded(), "%v", validator) 692 } 693 694 func TestUnbondingPeriod(t *testing.T) { 695 initPower := int64(1000) 696 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 1, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 697 validatorAddr := valAddrs[0] 698 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 699 700 // set the unbonding time 701 params := app.StakingKeeper.GetParams(ctx) 702 params.UnbondingTime = 7 * time.Second 703 app.StakingKeeper.SetParams(ctx, params) 704 705 // create the validator 706 amt := tstaking.CreateValidatorWithValPower(validatorAddr, PKs[0], 10, true) 707 staking.EndBlocker(ctx, app.StakingKeeper) 708 709 // begin unbonding 710 tstaking.Undelegate(sdk.AccAddress(validatorAddr), validatorAddr, amt, true) 711 712 origHeader := ctx.BlockHeader() 713 714 _, found := app.StakingKeeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) 715 require.True(t, found, "should not have unbonded") 716 717 // cannot complete unbonding at same time 718 staking.EndBlocker(ctx, app.StakingKeeper) 719 _, found = app.StakingKeeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) 720 require.True(t, found, "should not have unbonded") 721 722 // cannot complete unbonding at time 6 seconds later 723 ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 6)) 724 _, found = app.StakingKeeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) 725 require.True(t, found, "should not have unbonded") 726 727 // can complete unbonding at time 7 seconds later 728 ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 7)) 729 _, found = app.StakingKeeper.GetUnbondingDelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr) 730 require.False(t, found, "should have unbonded") 731 } 732 733 func TestUnbondingFromUnbondingValidator(t *testing.T) { 734 initPower := int64(1000) 735 app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 736 validatorAddr, delegatorAddr := valAddrs[0], delAddrs[1] 737 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 738 739 // create the validator and delegate 740 tstaking.CreateValidator(validatorAddr, PKs[0], sdk.NewInt(10), true) 741 tstaking.Delegate(delegatorAddr, validatorAddr, sdk.NewInt(10)) 742 743 // unbond the validators bond portion 744 unbondAmt := sdk.NewInt(10) 745 res := tstaking.Undelegate(sdk.AccAddress(validatorAddr), validatorAddr, unbondAmt, true) 746 747 // change the ctx to Block Time one second before the validator would have unbonded 748 var resData types.MsgUndelegateResponse 749 err := proto.Unmarshal(res.Data, &resData) 750 require.NoError(t, err) 751 752 ctx = ctx.WithBlockTime(resData.CompletionTime.Add(time.Second * -1)) 753 754 // unbond the delegator from the validator 755 res = tstaking.Undelegate(delegatorAddr, validatorAddr, unbondAmt, true) 756 757 ctx = tstaking.TurnBlockTimeDiff(app.StakingKeeper.UnbondingTime(ctx)) 758 tstaking.Ctx = ctx 759 760 // Check to make sure that the unbonding delegation is no longer in state 761 // (meaning it was deleted in the above EndBlocker) 762 _, found := app.StakingKeeper.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) 763 require.False(t, found, "should be removed from state") 764 } 765 766 func TestRedelegationPeriod(t *testing.T) { 767 initPower := int64(1000) 768 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 769 validatorAddr, validatorAddr2 := valAddrs[0], valAddrs[1] 770 denom := app.StakingKeeper.GetParams(ctx).BondDenom 771 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 772 773 // set the unbonding time 774 params := app.StakingKeeper.GetParams(ctx) 775 params.UnbondingTime = 7 * time.Second 776 app.StakingKeeper.SetParams(ctx, params) 777 // initial balance 778 amt1 := app.BankKeeper.GetBalance(ctx, sdk.AccAddress(validatorAddr), denom).Amount 779 780 // create the validators 781 tstaking.CreateValidator(validatorAddr, PKs[0], sdk.NewInt(10), true) 782 783 // balance should have been subtracted after creation 784 amt2 := app.BankKeeper.GetBalance(ctx, sdk.AccAddress(validatorAddr), denom).Amount 785 require.Equal(t, amt1.Sub(sdk.NewInt(10)), amt2, "expected coins to be subtracted") 786 787 tstaking.CreateValidator(validatorAddr2, PKs[1], sdk.NewInt(10), true) 788 bal1 := app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(validatorAddr)) 789 790 // begin redelegate 791 redAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)) 792 msgBeginRedelegate := types.NewMsgBeginRedelegate(sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2, redAmt) 793 tstaking.Handle(msgBeginRedelegate, true) 794 795 // origin account should not lose tokens as with a regular delegation 796 bal2 := app.BankKeeper.GetAllBalances(ctx, sdk.AccAddress(validatorAddr)) 797 require.Equal(t, bal1, bal2) 798 799 origHeader := ctx.BlockHeader() 800 801 // cannot complete redelegation at same time 802 staking.EndBlocker(ctx, app.StakingKeeper) 803 _, found := app.StakingKeeper.GetRedelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2) 804 require.True(t, found, "should not have unbonded") 805 806 // cannot complete redelegation at time 6 seconds later 807 ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 6)) 808 _, found = app.StakingKeeper.GetRedelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2) 809 require.True(t, found, "should not have unbonded") 810 811 // can complete redelegation at time 7 seconds later 812 ctx = tstaking.TurnBlock(origHeader.Time.Add(time.Second * 7)) 813 _, found = app.StakingKeeper.GetRedelegation(ctx, sdk.AccAddress(validatorAddr), validatorAddr, validatorAddr2) 814 require.False(t, found, "should have unbonded") 815 } 816 817 func TestTransitiveRedelegation(t *testing.T) { 818 initPower := int64(1000) 819 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 3, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 820 821 val1, val2, val3 := valAddrs[0], valAddrs[1], valAddrs[2] 822 blockTime := time.Now().UTC() 823 ctx = ctx.WithBlockTime(blockTime) 824 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 825 826 // create the validators 827 tstaking.CreateValidator(val1, PKs[0], sdk.NewInt(10), true) 828 tstaking.CreateValidator(val2, PKs[1], sdk.NewInt(10), true) 829 tstaking.CreateValidator(val3, PKs[2], sdk.NewInt(10), true) 830 831 // begin redelegate 832 redAmt := sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(10)) 833 msgBeginRedelegate := types.NewMsgBeginRedelegate(sdk.AccAddress(val1), val1, val2, redAmt) 834 tstaking.Handle(msgBeginRedelegate, true) 835 836 // cannot redelegation to next validator while first delegation exists 837 msgBeginRedelegate = types.NewMsgBeginRedelegate(sdk.AccAddress(val1), val2, val3, redAmt) 838 tstaking.Handle(msgBeginRedelegate, false) 839 840 params := app.StakingKeeper.GetParams(ctx) 841 ctx = ctx.WithBlockTime(blockTime.Add(params.UnbondingTime)) 842 tstaking.Ctx = ctx 843 844 // complete first redelegation 845 staking.EndBlocker(ctx, app.StakingKeeper) 846 847 // now should be able to redelegate from the second validator to the third 848 tstaking.Handle(msgBeginRedelegate, true) 849 } 850 851 func TestMultipleRedelegationAtSameTime(t *testing.T) { 852 initPower := int64(1000) 853 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 854 valAddr := valAddrs[0] 855 valAddr2 := valAddrs[1] 856 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 857 858 // set the unbonding time 859 params := app.StakingKeeper.GetParams(ctx) 860 params.UnbondingTime = 1 * time.Second 861 app.StakingKeeper.SetParams(ctx, params) 862 863 // create the validators 864 valTokens := tstaking.CreateValidatorWithValPower(valAddr, PKs[0], 10, true) 865 tstaking.CreateValidator(valAddr2, PKs[1], valTokens, true) 866 867 // end block to bond them 868 staking.EndBlocker(ctx, app.StakingKeeper) 869 870 // begin a redelegate 871 selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator) 872 redAmt := sdk.NewCoin(sdk.DefaultBondDenom, valTokens.QuoRaw(2)) 873 msgBeginRedelegate := types.NewMsgBeginRedelegate(selfDelAddr, valAddr, valAddr2, redAmt) 874 tstaking.Handle(msgBeginRedelegate, true) 875 876 // there should only be one entry in the redelegation object 877 rd, found := app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2) 878 require.True(t, found) 879 require.Len(t, rd.Entries, 1) 880 881 // start a second redelegation at this same time as the first 882 tstaking.Handle(msgBeginRedelegate, true) 883 884 // now there should be two entries 885 rd, found = app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2) 886 require.True(t, found) 887 require.Len(t, rd.Entries, 2) 888 889 // move forward in time, should complete both redelegations 890 ctx = tstaking.TurnBlockTimeDiff(1 * time.Second) 891 rd, found = app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2) 892 require.False(t, found) 893 } 894 895 func TestMultipleRedelegationAtUniqueTimes(t *testing.T) { 896 initPower := int64(1000) 897 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 2, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 898 valAddr := valAddrs[0] 899 valAddr2 := valAddrs[1] 900 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 901 902 // set the unbonding time 903 params := app.StakingKeeper.GetParams(ctx) 904 params.UnbondingTime = 10 * time.Second 905 app.StakingKeeper.SetParams(ctx, params) 906 907 // create the validators 908 valTokens := tstaking.CreateValidatorWithValPower(valAddr, PKs[0], 10, true) 909 tstaking.CreateValidator(valAddr2, PKs[1], valTokens, true) 910 911 // end block to bond them 912 staking.EndBlocker(ctx, app.StakingKeeper) 913 914 // begin a redelegate 915 selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator) 916 redAmt := sdk.NewCoin(sdk.DefaultBondDenom, valTokens.QuoRaw(2)) 917 msgBeginRedelegate := types.NewMsgBeginRedelegate(selfDelAddr, valAddr, valAddr2, redAmt) 918 tstaking.Handle(msgBeginRedelegate, true) 919 920 // move forward in time and start a second redelegation 921 ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second)) 922 tstaking.Ctx = ctx 923 tstaking.Handle(msgBeginRedelegate, true) 924 925 // now there should be two entries 926 rd, found := app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2) 927 require.True(t, found) 928 require.Len(t, rd.Entries, 2) 929 930 // move forward in time, should complete the first redelegation, but not the second 931 ctx = tstaking.TurnBlockTimeDiff(5 * time.Second) 932 rd, found = app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2) 933 require.True(t, found) 934 require.Len(t, rd.Entries, 1) 935 936 // move forward in time, should complete the second redelegation 937 ctx = tstaking.TurnBlockTimeDiff(5 * time.Second) 938 rd, found = app.StakingKeeper.GetRedelegation(ctx, selfDelAddr, valAddr, valAddr2) 939 require.False(t, found) 940 } 941 942 func TestMultipleUnbondingDelegationAtSameTime(t *testing.T) { 943 initPower := int64(1000) 944 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 1, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 945 valAddr := valAddrs[0] 946 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 947 948 // set the unbonding time 949 params := app.StakingKeeper.GetParams(ctx) 950 params.UnbondingTime = 1 * time.Second 951 app.StakingKeeper.SetParams(ctx, params) 952 953 // create the validators 954 valTokens := tstaking.CreateValidatorWithValPower(valAddr, PKs[0], 10, true) 955 956 // end block to bond 957 staking.EndBlocker(ctx, app.StakingKeeper) 958 959 // begin an unbonding delegation 960 selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator) 961 tstaking.Undelegate(selfDelAddr, valAddr, valTokens.QuoRaw(2), true) 962 963 // there should only be one entry in the ubd object 964 ubd, found := app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) 965 require.True(t, found) 966 require.Len(t, ubd.Entries, 1) 967 968 // start a second ubd at this same time as the first 969 tstaking.Undelegate(selfDelAddr, valAddr, valTokens.QuoRaw(2), true) 970 971 // now there should be two entries 972 ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) 973 require.True(t, found) 974 require.Len(t, ubd.Entries, 2) 975 976 // move forwaubd in time, should complete both ubds 977 ctx = tstaking.TurnBlockTimeDiff(1 * time.Second) 978 ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) 979 require.False(t, found) 980 } 981 982 func TestMultipleUnbondingDelegationAtUniqueTimes(t *testing.T) { 983 initPower := int64(1000) 984 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 1, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 985 valAddr := valAddrs[0] 986 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 987 988 // set the unbonding time 989 params := app.StakingKeeper.GetParams(ctx) 990 params.UnbondingTime = 10 * time.Second 991 app.StakingKeeper.SetParams(ctx, params) 992 993 // create the validator 994 valTokens := tstaking.CreateValidatorWithValPower(valAddr, PKs[0], 10, true) 995 996 // end block to bond 997 staking.EndBlocker(ctx, app.StakingKeeper) 998 999 // begin an unbonding delegation 1000 selfDelAddr := sdk.AccAddress(valAddr) // (the validator is it's own delegator) 1001 tstaking.Undelegate(selfDelAddr, valAddr, valTokens.QuoRaw(2), true) 1002 1003 // there should only be one entry in the ubd object 1004 ubd, found := app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) 1005 require.True(t, found) 1006 require.Len(t, ubd.Entries, 1) 1007 1008 // move forwaubd in time and start a second redelegation 1009 ctx = ctx.WithBlockTime(ctx.BlockHeader().Time.Add(5 * time.Second)) 1010 tstaking.Ctx = ctx 1011 tstaking.Undelegate(selfDelAddr, valAddr, valTokens.QuoRaw(2), true) 1012 1013 // now there should be two entries 1014 ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) 1015 require.True(t, found) 1016 require.Len(t, ubd.Entries, 2) 1017 1018 // move forwaubd in time, should complete the first redelegation, but not the second 1019 ctx = tstaking.TurnBlockTimeDiff(5 * time.Second) 1020 ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) 1021 require.True(t, found) 1022 require.Len(t, ubd.Entries, 1) 1023 1024 // move forwaubd in time, should complete the second redelegation 1025 ctx = tstaking.TurnBlockTimeDiff(5 * time.Second) 1026 ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, selfDelAddr, valAddr) 1027 require.False(t, found) 1028 } 1029 1030 func TestUnbondingWhenExcessValidators(t *testing.T) { 1031 initPower := int64(1000) 1032 app, ctx, _, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 3, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 1033 val1 := valAddrs[0] 1034 val2 := valAddrs[1] 1035 val3 := valAddrs[2] 1036 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 1037 1038 // set the unbonding time 1039 params := app.StakingKeeper.GetParams(ctx) 1040 params.MaxValidators = 2 1041 app.StakingKeeper.SetParams(ctx, params) 1042 1043 // add three validators 1044 tstaking.CreateValidatorWithValPower(val1, PKs[0], 50, true) 1045 // apply TM updates 1046 app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 1047 require.Equal(t, 1, len(app.StakingKeeper.GetLastValidators(ctx))) 1048 1049 valTokens2 := tstaking.CreateValidatorWithValPower(val2, PKs[1], 30, true) 1050 app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 1051 require.Equal(t, 2, len(app.StakingKeeper.GetLastValidators(ctx))) 1052 1053 tstaking.CreateValidatorWithValPower(val3, PKs[2], 10, true) 1054 app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 1055 require.Equal(t, 2, len(app.StakingKeeper.GetLastValidators(ctx))) 1056 1057 // unbond the validator-2 1058 tstaking.Undelegate(sdk.AccAddress(val2), val2, valTokens2, true) 1059 // apply TM updates 1060 app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 1061 1062 // because there are extra validators waiting to get in, the queued 1063 // validator (aka. validator-1) should make it into the bonded group, thus 1064 // the total number of validators should stay the same 1065 vals := app.StakingKeeper.GetLastValidators(ctx) 1066 require.Equal(t, 2, len(vals), "vals %v", vals) 1067 tstaking.CheckValidator(val1, types.Bonded, false) 1068 } 1069 1070 func TestBondUnbondRedelegateSlashTwice(t *testing.T) { 1071 initPower := int64(1000) 1072 app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 3, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 1073 valA, valB, del := valAddrs[0], valAddrs[1], delAddrs[2] 1074 consAddr0 := sdk.ConsAddress(PKs[0].Address()) 1075 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 1076 1077 valTokens := tstaking.CreateValidatorWithValPower(valA, PKs[0], 10, true) 1078 tstaking.CreateValidator(valB, PKs[1], valTokens, true) 1079 1080 // delegate 10 stake 1081 tstaking.Delegate(del, valA, valTokens) 1082 1083 // apply Tendermint updates 1084 updates, err := app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 1085 require.NoError(t, err) 1086 require.Equal(t, 2, len(updates)) 1087 1088 // a block passes 1089 ctx = ctx.WithBlockHeight(1) 1090 tstaking.Ctx = ctx 1091 1092 // begin unbonding 4 stake 1093 unbondAmt := app.StakingKeeper.TokensFromConsensusPower(ctx, 4) 1094 tstaking.Undelegate(del, valA, unbondAmt, true) 1095 1096 // begin redelegate 6 stake 1097 redAmt := sdk.NewCoin(sdk.DefaultBondDenom, app.StakingKeeper.TokensFromConsensusPower(ctx, 6)) 1098 msgBeginRedelegate := types.NewMsgBeginRedelegate(del, valA, valB, redAmt) 1099 tstaking.Handle(msgBeginRedelegate, true) 1100 1101 // destination delegation should have 6 shares 1102 delegation, found := app.StakingKeeper.GetDelegation(ctx, del, valB) 1103 require.True(t, found) 1104 require.Equal(t, sdk.NewDecFromInt(redAmt.Amount), delegation.Shares) 1105 1106 // must apply validator updates 1107 updates, err = app.StakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) 1108 require.NoError(t, err) 1109 require.Equal(t, 2, len(updates)) 1110 1111 // slash the validator by half 1112 app.StakingKeeper.Slash(ctx, consAddr0, 0, 20, sdk.NewDecWithPrec(5, 1)) 1113 1114 // unbonding delegation should have been slashed by half 1115 ubd, found := app.StakingKeeper.GetUnbondingDelegation(ctx, del, valA) 1116 require.True(t, found) 1117 require.Len(t, ubd.Entries, 1) 1118 require.Equal(t, unbondAmt.QuoRaw(2), ubd.Entries[0].Balance) 1119 1120 // redelegation should have been slashed by half 1121 redelegation, found := app.StakingKeeper.GetRedelegation(ctx, del, valA, valB) 1122 require.True(t, found) 1123 require.Len(t, redelegation.Entries, 1) 1124 1125 // destination delegation should have been slashed by half 1126 delegation, found = app.StakingKeeper.GetDelegation(ctx, del, valB) 1127 require.True(t, found) 1128 require.Equal(t, sdk.NewDecFromInt(redAmt.Amount.QuoRaw(2)), delegation.Shares) 1129 1130 // validator power should have been reduced by half 1131 validator, found := app.StakingKeeper.GetValidator(ctx, valA) 1132 require.True(t, found) 1133 require.Equal(t, valTokens.QuoRaw(2), validator.GetBondedTokens()) 1134 1135 // slash the validator for an infraction committed after the unbonding and redelegation begin 1136 ctx = ctx.WithBlockHeight(3) 1137 app.StakingKeeper.Slash(ctx, consAddr0, 2, 10, sdk.NewDecWithPrec(5, 1)) 1138 tstaking.Ctx = ctx 1139 1140 // unbonding delegation should be unchanged 1141 ubd, found = app.StakingKeeper.GetUnbondingDelegation(ctx, del, valA) 1142 require.True(t, found) 1143 require.Len(t, ubd.Entries, 1) 1144 require.Equal(t, unbondAmt.QuoRaw(2), ubd.Entries[0].Balance) 1145 1146 // redelegation should be unchanged 1147 redelegation, found = app.StakingKeeper.GetRedelegation(ctx, del, valA, valB) 1148 require.True(t, found) 1149 require.Len(t, redelegation.Entries, 1) 1150 1151 // destination delegation should be unchanged 1152 delegation, found = app.StakingKeeper.GetDelegation(ctx, del, valB) 1153 require.True(t, found) 1154 require.Equal(t, sdk.NewDecFromInt(redAmt.Amount.QuoRaw(2)), delegation.Shares) 1155 1156 // end blocker 1157 staking.EndBlocker(ctx, app.StakingKeeper) 1158 1159 // validator power should have been reduced to zero 1160 // validator should be in unbonding state 1161 validator, _ = app.StakingKeeper.GetValidator(ctx, valA) 1162 require.Equal(t, validator.GetStatus(), types.Unbonding) 1163 } 1164 1165 func TestInvalidMsg(t *testing.T) { 1166 k := keeper.Keeper{} 1167 h := staking.NewHandler(k) 1168 1169 res, err := h(sdk.NewContext(nil, tmproto.Header{}, false, nil), testdata.NewTestMsg()) 1170 require.Error(t, err) 1171 require.Nil(t, res) 1172 require.True(t, strings.Contains(err.Error(), "unrecognized staking message type")) 1173 } 1174 1175 func TestInvalidCoinDenom(t *testing.T) { 1176 initPower := int64(1000) 1177 app, ctx, delAddrs, valAddrs := bootstrapHandlerGenesisTest(t, initPower, 3, sdk.TokensFromConsensusPower(initPower, sdk.DefaultPowerReduction)) 1178 valA, valB, delAddr := valAddrs[0], valAddrs[1], delAddrs[2] 1179 tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper) 1180 1181 valTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 100) 1182 invalidCoin := sdk.NewCoin("churros", valTokens) 1183 validCoin := sdk.NewCoin(sdk.DefaultBondDenom, valTokens) 1184 oneCoin := sdk.NewCoin(sdk.DefaultBondDenom, sdk.OneInt()) 1185 1186 commission := types.NewCommissionRates(sdk.OneDec(), sdk.OneDec(), sdk.ZeroDec()) 1187 msgCreate, err := types.NewMsgCreateValidator(valA, PKs[0], invalidCoin, types.Description{}, commission, sdk.OneInt()) 1188 require.NoError(t, err) 1189 tstaking.Handle(msgCreate, false) 1190 1191 msgCreate, err = types.NewMsgCreateValidator(valA, PKs[0], validCoin, types.Description{}, commission, sdk.OneInt()) 1192 require.NoError(t, err) 1193 tstaking.Handle(msgCreate, true) 1194 1195 msgCreate, err = types.NewMsgCreateValidator(valB, PKs[1], validCoin, types.Description{}, commission, sdk.OneInt()) 1196 require.NoError(t, err) 1197 tstaking.Handle(msgCreate, true) 1198 1199 msgDelegate := types.NewMsgDelegate(delAddr, valA, invalidCoin) 1200 tstaking.Handle(msgDelegate, false) 1201 1202 msgDelegate = types.NewMsgDelegate(delAddr, valA, validCoin) 1203 tstaking.Handle(msgDelegate, true) 1204 1205 msgUndelegate := types.NewMsgUndelegate(delAddr, valA, invalidCoin) 1206 tstaking.Handle(msgUndelegate, false) 1207 1208 msgUndelegate = types.NewMsgUndelegate(delAddr, valA, oneCoin) 1209 tstaking.Handle(msgUndelegate, true) 1210 1211 msgRedelegate := types.NewMsgBeginRedelegate(delAddr, valA, valB, invalidCoin) 1212 tstaking.Handle(msgRedelegate, false) 1213 1214 msgRedelegate = types.NewMsgBeginRedelegate(delAddr, valA, valB, oneCoin) 1215 tstaking.Handle(msgRedelegate, true) 1216 }