diff --git a/x/stake/handler_test.go b/x/stake/handler_test.go index b18b3c98b2..fd4e55e089 100644 --- a/x/stake/handler_test.go +++ b/x/stake/handler_test.go @@ -560,6 +560,52 @@ func TestTransitiveRedelegation(t *testing.T) { require.True(t, got.IsOK(), "expected no error") } +func TestCliffValidator(t *testing.T) { + ctx, _, keeper := keep.CreateTestInput(t, false, 1000) + validatorAddr, validatorAddr2, validatorAddr3 := keep.Addrs[0], keep.Addrs[1], keep.Addrs[2] + + // set the unbonding time + params := keeper.GetParams(ctx) + params.UnbondingTime = 0 + params.MaxValidators = 2 + keeper.SetParams(ctx, params) + + // create the validators + msgCreateValidator := newTestMsgCreateValidator(validatorAddr, keep.PKs[0], 10) + got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + + msgCreateValidator = newTestMsgCreateValidator(validatorAddr2, keep.PKs[1], 5) + got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + + msgCreateValidator = newTestMsgCreateValidator(validatorAddr3, keep.PKs[2], 10) + got = handleMsgCreateValidator(ctx, msgCreateValidator, keeper) + require.True(t, got.IsOK(), "expected no error on runMsgCreateValidator") + + // initially should be the third validator + cliffVal := keeper.GetCliffValidator(ctx) + require.Equal(t, validatorAddr3, sdk.Address(cliffVal)) + + // unbond the third validator + msgBeginUnbonding := NewMsgBeginUnbonding(validatorAddr3, validatorAddr3, sdk.NewRat(10)) + got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) + require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") + + // unbond the second validator + msgBeginUnbonding = NewMsgBeginUnbonding(validatorAddr2, validatorAddr2, sdk.NewRat(5)) + got = handleMsgBeginUnbonding(ctx, msgBeginUnbonding, keeper) + require.True(t, got.IsOK(), "expected no error on runMsgBeginUnbonding") + + // get bonded validators - should just be one + vals := keeper.GetValidatorsBonded(ctx) + require.Equal(t, 1, len(vals)) + + // cliff now should be empty + cliffVal = keeper.GetCliffValidator(ctx) + require.Equal(t, nil, cliffVal) +} + func TestBondUnbondRedelegateSlashTwice(t *testing.T) { ctx, _, keeper := keep.CreateTestInput(t, false, 1000) valA, valB, del := keep.Addrs[0], keep.Addrs[1], keep.Addrs[2] diff --git a/x/stake/keeper/validator.go b/x/stake/keeper/validator.go index 0d556f7dc4..109dd4a3cd 100644 --- a/x/stake/keeper/validator.go +++ b/x/stake/keeper/validator.go @@ -254,7 +254,7 @@ func (k Keeper) UpdateValidator(ctx sdk.Context, validator types.Validator) type // efficiency case: // if was unbonded/or is a new validator - and the new power is less than the cliff validator - cliffPower := k.getCliffValidatorPower(ctx) + cliffPower := k.GetCliffValidatorPower(ctx) if cliffPower != nil && (!oldFound || (oldFound && oldValidator.Status() == sdk.Unbonded)) && bytes.Compare(valPower, cliffPower) == -1 { //(valPower < cliffPower @@ -288,7 +288,7 @@ func (k Keeper) UpdateBondedValidators(ctx sdk.Context, store := ctx.KVStore(k.storeKey) kickCliffValidator := false - oldCliffValidatorAddr := k.getCliffValidator(ctx) + oldCliffValidatorAddr := k.GetCliffValidator(ctx) // add the actual validator power sorted store maxValidators := k.GetParams(ctx).MaxValidators @@ -510,13 +510,13 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.Address) { //__________________________________________________________________________ // get the current validator on the cliff -func (k Keeper) getCliffValidator(ctx sdk.Context) []byte { +func (k Keeper) GetCliffValidator(ctx sdk.Context) []byte { store := ctx.KVStore(k.storeKey) return store.Get(ValidatorCliffIndexKey) } // get the current power of the validator on the cliff -func (k Keeper) getCliffValidatorPower(ctx sdk.Context) []byte { +func (k Keeper) GetCliffValidatorPower(ctx sdk.Context) []byte { store := ctx.KVStore(k.storeKey) return store.Get(ValidatorPowerCliffKey) }