Implement ValidatorSet.Slash
This commit is contained in:
parent
366d8f9323
commit
7da5833b81
@ -72,7 +72,6 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, height int64, timestamp int64,
|
||||
}
|
||||
logger.Info(fmt.Sprintf("Confirmed double sign from %v at height %d, age of %d less than max age of %d", pubkey.Address(), height, age, MaxEvidenceAge))
|
||||
k.stakeKeeper.Slash(ctx, pubkey, height, SlashFractionDoubleSign)
|
||||
logger.Info(fmt.Sprintf("Slashed validator %s by fraction %v for double-sign at height %d", pubkey.Address(), SlashFractionDoubleSign, height))
|
||||
}
|
||||
|
||||
// handle a validator signature, must be called once per validator per block
|
||||
@ -99,8 +98,6 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, pubkey crypto.PubKey,
|
||||
if height > minHeight && signInfo.SignedBlocksCounter < MinSignedPerWindow {
|
||||
k.stakeKeeper.Slash(ctx, pubkey, height, SlashFractionDowntime)
|
||||
k.stakeKeeper.ForceUnbond(ctx, pubkey, DowntimeUnbondDuration)
|
||||
logger.Info(fmt.Sprintf("Slashed validator %s by fraction %v and unbonded for downtime at height %d, cannot rebond for %ds",
|
||||
address, SlashFractionDowntime, height, DowntimeUnbondDuration))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ package slashing
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -52,7 +53,7 @@ func createTestInput(t *testing.T) (sdk.Context, bank.Keeper, stake.Keeper, Keep
|
||||
ms.MountStoreWithDB(keySlashing, sdk.StoreTypeIAVL, db)
|
||||
err := ms.LoadLatestVersion()
|
||||
require.Nil(t, err)
|
||||
ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewNopLogger(), nil)
|
||||
ctx := sdk.NewContext(ms, abci.Header{}, false, nil, log.NewTMLogger(os.Stdout), nil)
|
||||
cdc := createTestCodec()
|
||||
accountMapper := auth.NewAccountMapper(cdc, keyAcc, &auth.BaseAccount{})
|
||||
ck := bank.NewKeeper(accountMapper)
|
||||
@ -74,8 +75,9 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||
require.True(t, got.IsOK())
|
||||
_ = sk.Tick(ctx)
|
||||
require.Equal(t, ck.GetCoins(ctx, addr), sdk.Coins{{sk.GetParams(ctx).BondDenom, initCoins - amt}})
|
||||
require.Equal(t, sdk.NewRat(amt), sk.Validator(ctx, addr).GetPower())
|
||||
keeper.handleDoubleSign(ctx, 0, 0, val)
|
||||
// TODO
|
||||
require.Equal(t, sdk.NewRat(amt).Mul(sdk.NewRat(19).Quo(sdk.NewRat(20))), sk.Validator(ctx, addr).GetPower())
|
||||
}
|
||||
|
||||
func TestHandleAbsentValidator(t *testing.T) {
|
||||
|
||||
@ -779,8 +779,28 @@ func (k Keeper) IterateDelegators(ctx sdk.Context, delAddr sdk.Address, fn func(
|
||||
|
||||
// slash a validator
|
||||
func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, height int64, fraction sdk.Rat) {
|
||||
// TODO height ignored for now, see https://github.com/cosmos/cosmos-sdk/pull/1011#issuecomment-390253957
|
||||
val, found := k.GetValidatorByPubKey(ctx, pubkey)
|
||||
if !found {
|
||||
panic(fmt.Errorf("Attempted to slash a nonexistent validator with pubkey %s", pubkey))
|
||||
}
|
||||
sharesToRemove := val.PoolShares.Amount.Mul(fraction)
|
||||
pool := k.GetPool(ctx)
|
||||
val, pool, burned := val.removePoolShares(pool, sharesToRemove)
|
||||
k.setPool(ctx, pool) // update the pool
|
||||
k.updateValidator(ctx, val) // update the validator, possibly kicking it out
|
||||
ctx.Logger().With("module", "x/stake").Info(fmt.Sprintf("Validator %v slashed by fraction %v, removed %v shares and burned %d tokens", pubkey, fraction, sharesToRemove, burned))
|
||||
return
|
||||
}
|
||||
|
||||
// force unbond a validator
|
||||
func (k Keeper) ForceUnbond(ctx sdk.Context, pubkey crypto.PubKey, jailDuration int64) {
|
||||
// TODO Implement
|
||||
/*
|
||||
val, found := k.GetValidatorByPubKey(ctx, pubkey)
|
||||
if !found {
|
||||
ctx.Logger().Info("Validator with pubkey %s not found, cannot force unbond", pubkey)
|
||||
return
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@ -153,6 +153,21 @@ func (v Validator) UpdateStatus(pool Pool, NewStatus sdk.BondStatus) (Validator,
|
||||
return v, pool
|
||||
}
|
||||
|
||||
// Remove & burn pool shares, e.g. when slashing a validator
|
||||
func (v Validator) removePoolShares(pool Pool, amt sdk.Rat) (Validator, Pool, int64) {
|
||||
var tokens int64
|
||||
switch v.Status() {
|
||||
case sdk.Unbonded:
|
||||
pool, tokens = pool.removeSharesUnbonded(amt)
|
||||
case sdk.Unbonding:
|
||||
pool, tokens = pool.removeSharesUnbonding(amt)
|
||||
case sdk.Bonded:
|
||||
pool, tokens = pool.removeSharesBonded(amt)
|
||||
}
|
||||
v.PoolShares.Amount = v.PoolShares.Amount.Sub(amt)
|
||||
return v, pool, tokens
|
||||
}
|
||||
|
||||
// XXX TEST
|
||||
// get the power or potential power for a validator
|
||||
// if bonded, the power is the BondedShares
|
||||
|
||||
Loading…
Reference in New Issue
Block a user