Skip to content

Commit

Permalink
Merge PR #2163: Validator unbonding state
Browse files Browse the repository at this point in the history
  • Loading branch information
cwgoes authored Sep 1, 2018
2 parents 309a74e + f0c13bb commit d214952
Show file tree
Hide file tree
Showing 13 changed files with 579 additions and 85 deletions.
2 changes: 2 additions & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ BREAKING CHANGES
* [x/stake] \#1901 Validator type's Owner field renamed to Operator; Validator's GetOwner() renamed accordingly to comply with the SDK's Validator interface.
* [docs] [#2001](https://github.com/cosmos/cosmos-sdk/pull/2001) Update slashing spec for slashing period
* [x/stake, x/slashing] [#1305](https://github.com/cosmos/cosmos-sdk/issues/1305) - Rename "revoked" to "jailed"
* [x/stake] [#1676] Revoked and jailed validators put into the unbonding state
* [x/stake] [#1877] Redelegations/unbonding-delegation from unbonding validator have reduced time
* [x/stake] \#2040 Validator operator type has now changed to `sdk.ValAddress`
* A new bech32 prefix has been introduced for Tendermint signing keys and
addresses, `cosmosconspub` and `cosmoscons` respectively.
Expand Down
6 changes: 3 additions & 3 deletions x/slashing/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func TestHandleAbsentValidator(t *testing.T) {

// validator should have been jailed
validator, _ = sk.GetValidatorByPubKey(ctx, val)
require.Equal(t, sdk.Unbonded, validator.GetStatus())
require.Equal(t, sdk.Unbonding, validator.GetStatus())

// unrevocation should fail prior to jail expiration
got = slh(ctx, NewMsgUnjail(sdk.ValAddress(addr)))
Expand Down Expand Up @@ -224,7 +224,7 @@ func TestHandleAbsentValidator(t *testing.T) {
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
}
validator, _ = sk.GetValidatorByPubKey(ctx, val)
require.Equal(t, sdk.Unbonded, validator.GetStatus())
require.Equal(t, sdk.Unbonding, validator.GetStatus())
}

// Test a new validator entering the validator set
Expand Down Expand Up @@ -293,7 +293,7 @@ func TestHandleAlreadyJailed(t *testing.T) {

// validator should have been jailed and slashed
validator, _ := sk.GetValidatorByPubKey(ctx, val)
require.Equal(t, sdk.Unbonded, validator.GetStatus())
require.Equal(t, sdk.Unbonding, validator.GetStatus())

// validator should have been slashed
require.Equal(t, int64(amtInt-1), validator.GetTokens().RoundInt64())
Expand Down
2 changes: 1 addition & 1 deletion x/slashing/tick_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,5 @@ func TestBeginBlocker(t *testing.T) {
// validator should be jailed
validator, found := sk.GetValidatorByPubKey(ctx, pk)
require.True(t, found)
require.Equal(t, sdk.Unbonded, validator.GetStatus())
require.Equal(t, sdk.Unbonding, validator.GetStatus())
}
4 changes: 2 additions & 2 deletions x/stake/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ func TestValidatorByPowerIndex(t *testing.T) {
keeper.Jail(ctx, keep.PKs[0])
validator, found = keeper.GetValidator(ctx, validatorAddr)
require.True(t, found)
require.Equal(t, sdk.Unbonded, validator.Status) // ensure is unbonded
require.Equal(t, int64(500000), validator.Tokens.RoundInt64()) // ensure is unbonded
require.Equal(t, sdk.Unbonding, validator.Status) // ensure is unbonding
require.Equal(t, int64(500000), validator.Tokens.RoundInt64()) // ensure tokens slashed

// the old power record should have been deleted as the power changed
require.False(t, keep.ValidatorByPowerIndexExists(ctx, keeper, power))
Expand Down
46 changes: 44 additions & 2 deletions x/stake/keeper/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"bytes"
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/stake/types"
Expand Down Expand Up @@ -313,6 +314,32 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA

//______________________________________________________________________________________________________

// get info for begin functions: MinTime and CreationHeight
func (k Keeper) getBeginInfo(ctx sdk.Context, params types.Params, valSrcAddr sdk.ValAddress) (
minTime time.Time, height int64, completeNow bool) {

validator, found := k.GetValidator(ctx, valSrcAddr)
switch {
case !found || validator.Status == sdk.Bonded:

// the longest wait - just unbonding period from now
minTime = ctx.BlockHeader().Time.Add(params.UnbondingTime)
height = ctx.BlockHeader().Height
return minTime, height, false

case validator.IsUnbonded(ctx):
return minTime, height, true

case validator.Status == sdk.Unbonding:
minTime = validator.UnbondingMinTime
height = validator.UnbondingHeight
return minTime, height, false

default:
panic("unknown validator status")
}
}

// complete unbonding an unbonding record
func (k Keeper) BeginUnbonding(ctx sdk.Context,
delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec) sdk.Error {
Expand All @@ -330,12 +357,22 @@ func (k Keeper) BeginUnbonding(ctx sdk.Context,

// create the unbonding delegation
params := k.GetParams(ctx)
minTime := ctx.BlockHeader().Time.Add(params.UnbondingTime)
minTime, height, completeNow := k.getBeginInfo(ctx, params, valAddr)
balance := sdk.Coin{params.BondDenom, returnAmount.RoundInt()}

// no need to create the ubd object just complete now
if completeNow {
_, _, err := k.coinKeeper.AddCoins(ctx, delAddr, sdk.Coins{balance})
if err != nil {
return err
}
return nil
}

ubd := types.UnbondingDelegation{
DelegatorAddr: delAddr,
ValidatorAddr: valAddr,
CreationHeight: height,
MinTime: minTime,
Balance: balance,
InitialBalance: balance,
Expand Down Expand Up @@ -392,12 +429,17 @@ func (k Keeper) BeginRedelegation(ctx sdk.Context, delAddr sdk.AccAddress,
}

// create the unbonding delegation
minTime := ctx.BlockHeader().Time.Add(params.UnbondingTime)
minTime, height, completeNow := k.getBeginInfo(ctx, params, valSrcAddr)

if completeNow { // no need to create the redelegation object
return nil
}

red := types.Redelegation{
DelegatorAddr: delAddr,
ValidatorSrcAddr: valSrcAddr,
ValidatorDstAddr: valDstAddr,
CreationHeight: height,
MinTime: minTime,
SharesDst: sharesCreated,
SharesSrc: sharesAmount,
Expand Down
Loading

0 comments on commit d214952

Please sign in to comment.