pulling in stuff from fee-distr PR
This commit is contained in:
parent
8721dd6ff8
commit
4e4749da9d
|
@ -34,9 +34,9 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result {
|
||||||
return ErrValidatorNotJailed(k.codespace).Result()
|
return ErrValidatorNotJailed(k.codespace).Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
addr := sdk.ConsAddress(validator.GetPubKey().Address())
|
consAddr := sdk.ConsAddress(validator.GetPubKey().Address())
|
||||||
|
|
||||||
info, found := k.getValidatorSigningInfo(ctx, addr)
|
info, found := k.getValidatorSigningInfo(ctx, consAddr)
|
||||||
if !found {
|
if !found {
|
||||||
return ErrNoValidatorForAddress(k.codespace).Result()
|
return ErrNoValidatorForAddress(k.codespace).Result()
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,9 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result {
|
||||||
// update the starting height so the validator can't be immediately jailed
|
// update the starting height so the validator can't be immediately jailed
|
||||||
// again
|
// again
|
||||||
info.StartHeight = ctx.BlockHeight()
|
info.StartHeight = ctx.BlockHeight()
|
||||||
k.setValidatorSigningInfo(ctx, addr, info)
|
k.setValidatorSigningInfo(ctx, consAddr, info)
|
||||||
|
|
||||||
k.validatorSet.Unjail(ctx, validator.GetPubKey())
|
k.validatorSet.Unjail(ctx, consAddr)
|
||||||
|
|
||||||
tags := sdk.NewTags("action", []byte("unjail"), "validator", []byte(msg.ValidatorAddr.String()))
|
tags := sdk.NewTags("action", []byte("unjail"), "validator", []byte(msg.ValidatorAddr.String()))
|
||||||
|
|
||||||
|
|
|
@ -22,25 +22,34 @@ func (k Keeper) onValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddre
|
||||||
k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod)
|
k.addOrUpdateValidatorSlashingPeriod(ctx, slashingPeriod)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper struct for sdk.ValidatorHooks
|
//_________________________________________________________________________________________
|
||||||
type ValidatorHooks struct {
|
|
||||||
|
// Wrapper struct
|
||||||
|
type Hooks struct {
|
||||||
k Keeper
|
k Keeper
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert implementation
|
var _ sdk.StakingHooks = Hooks{}
|
||||||
var _ sdk.ValidatorHooks = ValidatorHooks{}
|
|
||||||
|
|
||||||
// Return a sdk.ValidatorHooks interface over the wrapper struct
|
// Return the wrapper struct
|
||||||
func (k Keeper) ValidatorHooks() sdk.ValidatorHooks {
|
func (k Keeper) Hooks() Hooks {
|
||||||
return ValidatorHooks{k}
|
return Hooks{k}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements sdk.ValidatorHooks
|
// Implements sdk.ValidatorHooks
|
||||||
func (v ValidatorHooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) {
|
func (h Hooks) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) {
|
||||||
v.k.onValidatorBonded(ctx, address)
|
h.k.onValidatorBonded(ctx, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements sdk.ValidatorHooks
|
// Implements sdk.ValidatorHooks
|
||||||
func (v ValidatorHooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) {
|
func (h Hooks) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) {
|
||||||
v.k.onValidatorBeginUnbonding(ctx, address)
|
h.k.onValidatorBeginUnbonding(ctx, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint - unused hooks
|
||||||
|
func (h Hooks) OnValidatorCreated(_ sdk.Context, _ sdk.ValAddress) {}
|
||||||
|
func (h Hooks) OnValidatorCommissionChange(_ sdk.Context, _ sdk.ValAddress) {}
|
||||||
|
func (h Hooks) OnValidatorRemoved(_ sdk.Context, _ sdk.ValAddress) {}
|
||||||
|
func (h Hooks) OnDelegationCreated(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
|
||||||
|
func (h Hooks) OnDelegationSharesModified(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
|
||||||
|
func (h Hooks) OnDelegationRemoved(_ sdk.Context, _ sdk.AccAddress, _ sdk.ValAddress) {}
|
||||||
|
|
|
@ -40,10 +40,10 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio
|
||||||
logger := ctx.Logger().With("module", "x/slashing")
|
logger := ctx.Logger().With("module", "x/slashing")
|
||||||
time := ctx.BlockHeader().Time
|
time := ctx.BlockHeader().Time
|
||||||
age := time.Sub(timestamp)
|
age := time.Sub(timestamp)
|
||||||
address := sdk.ConsAddress(addr)
|
consAddr := sdk.ConsAddress(addr)
|
||||||
pubkey, err := k.getPubkey(ctx, addr)
|
pubkey, err := k.getPubkey(ctx, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("Validator address %v not found", addr))
|
panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Double sign too old
|
// Double sign too old
|
||||||
|
@ -59,37 +59,38 @@ func (k Keeper) handleDoubleSign(ctx sdk.Context, addr crypto.Address, infractio
|
||||||
// Cap the amount slashed to the penalty for the worst infraction
|
// Cap the amount slashed to the penalty for the worst infraction
|
||||||
// within the slashing period when this infraction was committed
|
// within the slashing period when this infraction was committed
|
||||||
fraction := k.SlashFractionDoubleSign(ctx)
|
fraction := k.SlashFractionDoubleSign(ctx)
|
||||||
revisedFraction := k.capBySlashingPeriod(ctx, address, fraction, infractionHeight)
|
revisedFraction := k.capBySlashingPeriod(ctx, consAddr, fraction, infractionHeight)
|
||||||
logger.Info(fmt.Sprintf("Fraction slashed capped by slashing period from %v to %v", fraction, revisedFraction))
|
logger.Info(fmt.Sprintf("Fraction slashed capped by slashing period from %v to %v", fraction, revisedFraction))
|
||||||
|
|
||||||
// Slash validator
|
// Slash validator
|
||||||
k.validatorSet.Slash(ctx, pubkey, infractionHeight, power, revisedFraction)
|
k.validatorSet.Slash(ctx, consAddr, infractionHeight, power, revisedFraction)
|
||||||
|
|
||||||
// Jail validator
|
// Jail validator
|
||||||
k.validatorSet.Jail(ctx, pubkey)
|
k.validatorSet.Jail(ctx, consAddr)
|
||||||
|
|
||||||
// Set validator jail duration
|
// Set validator jail duration
|
||||||
signInfo, found := k.getValidatorSigningInfo(ctx, address)
|
signInfo, found := k.getValidatorSigningInfo(ctx, consAddr)
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Sprintf("Expected signing info for validator %s but not found", address))
|
panic(fmt.Sprintf("Expected signing info for validator %s but not found", consAddr))
|
||||||
}
|
}
|
||||||
signInfo.JailedUntil = time.Add(k.DoubleSignUnbondDuration(ctx))
|
signInfo.JailedUntil = time.Add(k.DoubleSignUnbondDuration(ctx))
|
||||||
k.setValidatorSigningInfo(ctx, address, signInfo)
|
k.setValidatorSigningInfo(ctx, consAddr, signInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle a validator signature, must be called once per validator per block
|
// handle a validator signature, must be called once per validator per block
|
||||||
|
// TODO refactor to take in a consensus address, additionally should maybe just take in the pubkey too
|
||||||
// nolint gocyclo
|
// nolint gocyclo
|
||||||
func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, power int64, signed bool) {
|
func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, power int64, signed bool) {
|
||||||
logger := ctx.Logger().With("module", "x/slashing")
|
logger := ctx.Logger().With("module", "x/slashing")
|
||||||
height := ctx.BlockHeight()
|
height := ctx.BlockHeight()
|
||||||
address := sdk.ConsAddress(addr)
|
consAddr := sdk.ConsAddress(addr)
|
||||||
pubkey, err := k.getPubkey(ctx, addr)
|
pubkey, err := k.getPubkey(ctx, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("Validator address %v not found", addr))
|
panic(fmt.Sprintf("Validator consensus-address %v not found", consAddr))
|
||||||
}
|
}
|
||||||
// Local index, so counts blocks validator *should* have signed
|
// Local index, so counts blocks validator *should* have signed
|
||||||
// Will use the 0-value default signing info if not present, except for start height
|
// Will use the 0-value default signing info if not present, except for start height
|
||||||
signInfo, found := k.getValidatorSigningInfo(ctx, address)
|
signInfo, found := k.getValidatorSigningInfo(ctx, consAddr)
|
||||||
if !found {
|
if !found {
|
||||||
// If this validator has never been seen before, construct a new SigningInfo with the correct start height
|
// If this validator has never been seen before, construct a new SigningInfo with the correct start height
|
||||||
signInfo = NewValidatorSigningInfo(height, 0, time.Unix(0, 0), 0)
|
signInfo = NewValidatorSigningInfo(height, 0, time.Unix(0, 0), 0)
|
||||||
|
@ -100,16 +101,16 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
|
||||||
// Update signed block bit array & counter
|
// Update signed block bit array & counter
|
||||||
// This counter just tracks the sum of the bit array
|
// This counter just tracks the sum of the bit array
|
||||||
// That way we avoid needing to read/write the whole array each time
|
// That way we avoid needing to read/write the whole array each time
|
||||||
previous := k.getValidatorSigningBitArray(ctx, address, index)
|
previous := k.getValidatorSigningBitArray(ctx, consAddr, index)
|
||||||
if previous == signed {
|
if previous == signed {
|
||||||
// Array value at this index has not changed, no need to update counter
|
// Array value at this index has not changed, no need to update counter
|
||||||
} else if previous && !signed {
|
} else if previous && !signed {
|
||||||
// Array value has changed from signed to unsigned, decrement counter
|
// Array value has changed from signed to unsigned, decrement counter
|
||||||
k.setValidatorSigningBitArray(ctx, address, index, false)
|
k.setValidatorSigningBitArray(ctx, consAddr, index, false)
|
||||||
signInfo.SignedBlocksCounter--
|
signInfo.SignedBlocksCounter--
|
||||||
} else if !previous && signed {
|
} else if !previous && signed {
|
||||||
// Array value has changed from unsigned to signed, increment counter
|
// Array value has changed from unsigned to signed, increment counter
|
||||||
k.setValidatorSigningBitArray(ctx, address, index, true)
|
k.setValidatorSigningBitArray(ctx, consAddr, index, true)
|
||||||
signInfo.SignedBlocksCounter++
|
signInfo.SignedBlocksCounter++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,13 +119,13 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
|
||||||
}
|
}
|
||||||
minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx)
|
minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx)
|
||||||
if height > minHeight && signInfo.SignedBlocksCounter < k.MinSignedPerWindow(ctx) {
|
if height > minHeight && signInfo.SignedBlocksCounter < k.MinSignedPerWindow(ctx) {
|
||||||
validator := k.validatorSet.ValidatorByPubKey(ctx, pubkey)
|
validator := k.validatorSet.ValidatorByConsAddr(ctx, consAddr)
|
||||||
if validator != nil && !validator.GetJailed() {
|
if validator != nil && !validator.GetJailed() {
|
||||||
// Downtime confirmed: slash and jail the validator
|
// Downtime confirmed: slash and jail the validator
|
||||||
logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d",
|
logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d",
|
||||||
pubkey.Address(), minHeight, k.MinSignedPerWindow(ctx)))
|
pubkey.Address(), minHeight, k.MinSignedPerWindow(ctx)))
|
||||||
k.validatorSet.Slash(ctx, pubkey, height, power, k.SlashFractionDowntime(ctx))
|
k.validatorSet.Slash(ctx, consAddr, height, power, k.SlashFractionDowntime(ctx))
|
||||||
k.validatorSet.Jail(ctx, pubkey)
|
k.validatorSet.Jail(ctx, consAddr)
|
||||||
signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeUnbondDuration(ctx))
|
signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeUnbondDuration(ctx))
|
||||||
} else {
|
} else {
|
||||||
// Validator was (a) not found or (b) already jailed, don't slash
|
// Validator was (a) not found or (b) already jailed, don't slash
|
||||||
|
@ -134,7 +135,7 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the updated signing info
|
// Set the updated signing info
|
||||||
k.setValidatorSigningInfo(ctx, address, signInfo)
|
k.setValidatorSigningInfo(ctx, consAddr, signInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddValidators adds the validators to the keepers validator addr to pubkey mapping.
|
// AddValidators adds the validators to the keepers validator addr to pubkey mapping.
|
||||||
|
|
|
@ -18,13 +18,16 @@ func init() {
|
||||||
defaultDoubleSignUnbondDuration = 60 * 60
|
defaultDoubleSignUnbondDuration = 60 * 60
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ______________________________________________________________
|
||||||
|
|
||||||
// Test that a validator is slashed correctly
|
// Test that a validator is slashed correctly
|
||||||
// when we discover evidence of infraction
|
// when we discover evidence of infraction
|
||||||
|
// TODO fix this test to not be using the same pubkey/address for signing and operating, it's confusing
|
||||||
func TestHandleDoubleSign(t *testing.T) {
|
func TestHandleDoubleSign(t *testing.T) {
|
||||||
|
|
||||||
// initial setup
|
// initial setup
|
||||||
ctx, ck, sk, _, keeper := createTestInput(t)
|
ctx, ck, sk, _, keeper := createTestInput(t)
|
||||||
sk = sk.WithValidatorHooks(keeper.ValidatorHooks())
|
sk = sk.WithHooks(keeper.Hooks())
|
||||||
amtInt := int64(100)
|
amtInt := int64(100)
|
||||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||||
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt))
|
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt))
|
||||||
|
@ -43,7 +46,7 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||||
// should be jailed
|
// should be jailed
|
||||||
require.True(t, sk.Validator(ctx, addr).GetJailed())
|
require.True(t, sk.Validator(ctx, addr).GetJailed())
|
||||||
// unjail to measure power
|
// unjail to measure power
|
||||||
sk.Unjail(ctx, val)
|
sk.Unjail(ctx, sdk.ConsAddress(addr)) // TODO distinguish cons address
|
||||||
// power should be reduced
|
// power should be reduced
|
||||||
require.Equal(
|
require.Equal(
|
||||||
t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))),
|
t, sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20))),
|
||||||
|
@ -61,14 +64,16 @@ func TestHandleDoubleSign(t *testing.T) {
|
||||||
|
|
||||||
// Test that the amount a validator is slashed for multiple double signs
|
// Test that the amount a validator is slashed for multiple double signs
|
||||||
// is correctly capped by the slashing period in which they were committed
|
// is correctly capped by the slashing period in which they were committed
|
||||||
|
// TODO properly distinguish between consensus and operator address is variable names
|
||||||
func TestSlashingPeriodCap(t *testing.T) {
|
func TestSlashingPeriodCap(t *testing.T) {
|
||||||
|
|
||||||
// initial setup
|
// initial setup
|
||||||
ctx, ck, sk, _, keeper := createTestInput(t)
|
ctx, ck, sk, _, keeper := createTestInput(t)
|
||||||
sk = sk.WithValidatorHooks(keeper.ValidatorHooks())
|
sk = sk.WithHooks(keeper.Hooks())
|
||||||
amtInt := int64(100)
|
amtInt := int64(100)
|
||||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
addr, amt := addrs[0], sdk.NewInt(amtInt)
|
||||||
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, val, amt))
|
valConsPubKey, valConsAddr := pks[0], sdk.ConsAddress(pks[0].Address())
|
||||||
|
got := stake.NewHandler(sk)(ctx, newTestMsgCreateValidator(addr, valConsPubKey, amt))
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
validatorUpdates := stake.EndBlocker(ctx, sk)
|
validatorUpdates := stake.EndBlocker(ctx, sk)
|
||||||
keeper.AddValidators(ctx, validatorUpdates)
|
keeper.AddValidators(ctx, validatorUpdates)
|
||||||
|
@ -76,39 +81,39 @@ func TestSlashingPeriodCap(t *testing.T) {
|
||||||
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
require.True(t, sdk.NewDecFromInt(amt).Equal(sk.Validator(ctx, addr).GetPower()))
|
||||||
|
|
||||||
// handle a signature to set signing info
|
// handle a signature to set signing info
|
||||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true)
|
keeper.handleValidatorSignature(ctx, valConsPubKey.Address(), amtInt, true)
|
||||||
|
|
||||||
// double sign less than max age
|
// double sign less than max age
|
||||||
keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt)
|
keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 0, time.Unix(0, 0), amtInt)
|
||||||
|
|
||||||
// should be jailed
|
// should be jailed
|
||||||
require.True(t, sk.Validator(ctx, addr).GetJailed())
|
require.True(t, sk.Validator(ctx, addr).GetJailed())
|
||||||
// update block height
|
// update block height
|
||||||
ctx = ctx.WithBlockHeight(int64(1))
|
ctx = ctx.WithBlockHeight(int64(1))
|
||||||
// unjail to measure power
|
// unjail to measure power
|
||||||
sk.Unjail(ctx, val)
|
sk.Unjail(ctx, valConsAddr)
|
||||||
// power should be reduced
|
// power should be reduced
|
||||||
expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20)))
|
expectedPower := sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20)))
|
||||||
require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower())
|
require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower())
|
||||||
|
|
||||||
// double sign again, same slashing period
|
// double sign again, same slashing period
|
||||||
keeper.handleDoubleSign(ctx, val.Address(), 0, time.Unix(0, 0), amtInt)
|
keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 0, time.Unix(0, 0), amtInt)
|
||||||
// should be jailed
|
// should be jailed
|
||||||
require.True(t, sk.Validator(ctx, addr).GetJailed())
|
require.True(t, sk.Validator(ctx, addr).GetJailed())
|
||||||
// update block height
|
// update block height
|
||||||
ctx = ctx.WithBlockHeight(int64(2))
|
ctx = ctx.WithBlockHeight(int64(2))
|
||||||
// unjail to measure power
|
// unjail to measure power
|
||||||
sk.Unjail(ctx, val)
|
sk.Unjail(ctx, valConsAddr)
|
||||||
// power should be equal, no more should have been slashed
|
// power should be equal, no more should have been slashed
|
||||||
expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20)))
|
expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(19).Quo(sdk.NewDec(20)))
|
||||||
require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower())
|
require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower())
|
||||||
|
|
||||||
// double sign again, new slashing period
|
// double sign again, new slashing period
|
||||||
keeper.handleDoubleSign(ctx, val.Address(), 2, time.Unix(0, 0), amtInt)
|
keeper.handleDoubleSign(ctx, valConsPubKey.Address(), 2, time.Unix(0, 0), amtInt)
|
||||||
// should be jailed
|
// should be jailed
|
||||||
require.True(t, sk.Validator(ctx, addr).GetJailed())
|
require.True(t, sk.Validator(ctx, addr).GetJailed())
|
||||||
// unjail to measure power
|
// unjail to measure power
|
||||||
sk.Unjail(ctx, val)
|
sk.Unjail(ctx, valConsAddr)
|
||||||
// power should be reduced
|
// power should be reduced
|
||||||
expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20)))
|
expectedPower = sdk.NewDecFromInt(amt).Mul(sdk.NewDec(18).Quo(sdk.NewDec(20)))
|
||||||
require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower())
|
require.Equal(t, expectedPower, sk.Validator(ctx, addr).GetPower())
|
||||||
|
@ -120,7 +125,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||||
|
|
||||||
// initial setup
|
// initial setup
|
||||||
ctx, ck, sk, _, keeper := createTestInput(t)
|
ctx, ck, sk, _, keeper := createTestInput(t)
|
||||||
sk = sk.WithValidatorHooks(keeper.ValidatorHooks())
|
sk = sk.WithHooks(keeper.Hooks())
|
||||||
amtInt := int64(100)
|
amtInt := int64(100)
|
||||||
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt)
|
||||||
sh := stake.NewHandler(sk)
|
sh := stake.NewHandler(sk)
|
||||||
|
@ -162,7 +167,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||||
require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.SignedBlocksCounter)
|
require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx), info.SignedBlocksCounter)
|
||||||
|
|
||||||
// validator should be bonded still
|
// validator should be bonded still
|
||||||
validator, _ := sk.GetValidatorByPubKey(ctx, val)
|
validator, _ := sk.GetValidatorByConsPubKey(ctx, val)
|
||||||
require.Equal(t, sdk.Bonded, validator.GetStatus())
|
require.Equal(t, sdk.Bonded, validator.GetStatus())
|
||||||
pool := sk.GetPool(ctx)
|
pool := sk.GetPool(ctx)
|
||||||
require.Equal(t, amtInt, pool.BondedTokens.RoundInt64())
|
require.Equal(t, amtInt, pool.BondedTokens.RoundInt64())
|
||||||
|
@ -176,7 +181,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||||
require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter)
|
require.Equal(t, keeper.SignedBlocksWindow(ctx)-keeper.MinSignedPerWindow(ctx)-1, info.SignedBlocksCounter)
|
||||||
|
|
||||||
// validator should have been jailed
|
// validator should have been jailed
|
||||||
validator, _ = sk.GetValidatorByPubKey(ctx, val)
|
validator, _ = sk.GetValidatorByConsPubKey(ctx, val)
|
||||||
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
||||||
|
|
||||||
// unrevocation should fail prior to jail expiration
|
// unrevocation should fail prior to jail expiration
|
||||||
|
@ -189,7 +194,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
|
|
||||||
// validator should be rebonded now
|
// validator should be rebonded now
|
||||||
validator, _ = sk.GetValidatorByPubKey(ctx, val)
|
validator, _ = sk.GetValidatorByConsPubKey(ctx, val)
|
||||||
require.Equal(t, sdk.Bonded, validator.GetStatus())
|
require.Equal(t, sdk.Bonded, validator.GetStatus())
|
||||||
|
|
||||||
// validator should have been slashed
|
// validator should have been slashed
|
||||||
|
@ -207,7 +212,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||||
height++
|
height++
|
||||||
ctx = ctx.WithBlockHeight(height)
|
ctx = ctx.WithBlockHeight(height)
|
||||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
|
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
|
||||||
validator, _ = sk.GetValidatorByPubKey(ctx, val)
|
validator, _ = sk.GetValidatorByConsPubKey(ctx, val)
|
||||||
require.Equal(t, sdk.Bonded, validator.GetStatus())
|
require.Equal(t, sdk.Bonded, validator.GetStatus())
|
||||||
|
|
||||||
// 500 signed blocks
|
// 500 signed blocks
|
||||||
|
@ -223,7 +228,7 @@ func TestHandleAbsentValidator(t *testing.T) {
|
||||||
ctx = ctx.WithBlockHeight(height)
|
ctx = ctx.WithBlockHeight(height)
|
||||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
|
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
|
||||||
}
|
}
|
||||||
validator, _ = sk.GetValidatorByPubKey(ctx, val)
|
validator, _ = sk.GetValidatorByConsPubKey(ctx, val)
|
||||||
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +263,7 @@ func TestHandleNewValidator(t *testing.T) {
|
||||||
require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil)
|
require.Equal(t, time.Unix(0, 0).UTC(), info.JailedUntil)
|
||||||
|
|
||||||
// validator should be bonded still, should not have been jailed or slashed
|
// validator should be bonded still, should not have been jailed or slashed
|
||||||
validator, _ := sk.GetValidatorByPubKey(ctx, val)
|
validator, _ := sk.GetValidatorByConsPubKey(ctx, val)
|
||||||
require.Equal(t, sdk.Bonded, validator.GetStatus())
|
require.Equal(t, sdk.Bonded, validator.GetStatus())
|
||||||
pool := sk.GetPool(ctx)
|
pool := sk.GetPool(ctx)
|
||||||
require.Equal(t, int64(100), pool.BondedTokens.RoundInt64())
|
require.Equal(t, int64(100), pool.BondedTokens.RoundInt64())
|
||||||
|
@ -292,7 +297,7 @@ func TestHandleAlreadyJailed(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// validator should have been jailed and slashed
|
// validator should have been jailed and slashed
|
||||||
validator, _ := sk.GetValidatorByPubKey(ctx, val)
|
validator, _ := sk.GetValidatorByConsPubKey(ctx, val)
|
||||||
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
||||||
|
|
||||||
// validator should have been slashed
|
// validator should have been slashed
|
||||||
|
@ -303,7 +308,7 @@ func TestHandleAlreadyJailed(t *testing.T) {
|
||||||
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
|
keeper.handleValidatorSignature(ctx, val.Address(), amtInt, false)
|
||||||
|
|
||||||
// validator should not have been slashed twice
|
// validator should not have been slashed twice
|
||||||
validator, _ = sk.GetValidatorByPubKey(ctx, val)
|
validator, _ = sk.GetValidatorByConsPubKey(ctx, val)
|
||||||
require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64())
|
require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ func TestBeginBlocker(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// validator should be jailed
|
// validator should be jailed
|
||||||
validator, found := sk.GetValidatorByPubKey(ctx, pk)
|
validator, found := sk.GetValidatorByConsPubKey(ctx, pk)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
require.Equal(t, sdk.Unbonding, validator.GetStatus())
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,8 @@ func init() {
|
||||||
fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)")
|
fsDescriptionEdit.String(FlagIdentity, types.DoNotModifyDesc, "optional identity signature (ex. UPort or Keybase)")
|
||||||
fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website")
|
fsDescriptionEdit.String(FlagWebsite, types.DoNotModifyDesc, "optional website")
|
||||||
fsDescriptionEdit.String(FlagDetails, types.DoNotModifyDesc, "optional details")
|
fsDescriptionEdit.String(FlagDetails, types.DoNotModifyDesc, "optional details")
|
||||||
fsValidator.String(FlagAddressValidator, "", "hex address of the validator")
|
fsValidator.String(FlagAddressValidator, "", "bech address of the validator")
|
||||||
fsDelegator.String(FlagAddressDelegator, "", "hex address of the delegator")
|
fsDelegator.String(FlagAddressDelegator, "", "bech address of the delegator")
|
||||||
fsRedelegation.String(FlagAddressValidatorSrc, "", "hex address of the source validator")
|
fsRedelegation.String(FlagAddressValidatorSrc, "", "bech address of the source validator")
|
||||||
fsRedelegation.String(FlagAddressValidatorDst, "", "hex address of the destination validator")
|
fsRedelegation.String(FlagAddressValidatorDst, "", "bech address of the destination validator")
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data types.GenesisState) (res [
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manually set indexes for the first time
|
// Manually set indexes for the first time
|
||||||
keeper.SetValidatorByPubKeyIndex(ctx, validator)
|
keeper.SetValidatorByConsAddr(ctx, validator)
|
||||||
keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool)
|
keeper.SetValidatorByPowerIndex(ctx, validator, data.Pool)
|
||||||
|
|
||||||
if validator.Status == sdk.Bonded {
|
if validator.Status == sdk.Bonded {
|
||||||
|
|
|
@ -68,7 +68,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
|
||||||
if found {
|
if found {
|
||||||
return ErrValidatorOwnerExists(k.Codespace()).Result()
|
return ErrValidatorOwnerExists(k.Codespace()).Result()
|
||||||
}
|
}
|
||||||
_, found = k.GetValidatorByPubKey(ctx, msg.PubKey)
|
_, found = k.GetValidatorByConsPubKey(ctx, msg.PubKey)
|
||||||
if found {
|
if found {
|
||||||
return ErrValidatorPubKeyExists(k.Codespace()).Result()
|
return ErrValidatorPubKeyExists(k.Codespace()).Result()
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
|
||||||
|
|
||||||
validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description)
|
validator := NewValidator(msg.ValidatorAddr, msg.PubKey, msg.Description)
|
||||||
k.SetValidator(ctx, validator)
|
k.SetValidator(ctx, validator)
|
||||||
k.SetValidatorByPubKeyIndex(ctx, validator)
|
k.SetValidatorByConsAddr(ctx, validator)
|
||||||
|
|
||||||
// move coins from the msg.Address account to a (self-delegation) delegator account
|
// move coins from the msg.Address account to a (self-delegation) delegator account
|
||||||
// the validator account and global shares are updated within here
|
// the validator account and global shares are updated within here
|
||||||
|
@ -87,6 +87,11 @@ func handleMsgCreateValidator(ctx sdk.Context, msg types.MsgCreateValidator, k k
|
||||||
return err.Result()
|
return err.Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call the hook if present
|
||||||
|
k.OnValidatorCreated(ctx, validator.OperatorAddr)
|
||||||
|
accAddr := sdk.AccAddress(validator.OperatorAddr)
|
||||||
|
k.OnDelegationCreated(ctx, accAddr, validator.OperatorAddr)
|
||||||
|
|
||||||
tags := sdk.NewTags(
|
tags := sdk.NewTags(
|
||||||
tags.Action, tags.ActionCreateValidator,
|
tags.Action, tags.ActionCreateValidator,
|
||||||
tags.DstValidator, []byte(msg.ValidatorAddr.String()),
|
tags.DstValidator, []byte(msg.ValidatorAddr.String()),
|
||||||
|
@ -146,6 +151,9 @@ func handleMsgDelegate(ctx sdk.Context, msg types.MsgDelegate, k keeper.Keeper)
|
||||||
return err.Result()
|
return err.Result()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call the hook if present
|
||||||
|
k.OnDelegationCreated(ctx, msg.DelegatorAddr, validator.OperatorAddr)
|
||||||
|
|
||||||
tags := sdk.NewTags(
|
tags := sdk.NewTags(
|
||||||
tags.Action, tags.ActionDelegate,
|
tags.Action, tags.ActionDelegate,
|
||||||
tags.Delegator, []byte(msg.DelegatorAddr.String()),
|
tags.Delegator, []byte(msg.DelegatorAddr.String()),
|
||||||
|
|
|
@ -81,8 +81,9 @@ func TestValidatorByPowerIndex(t *testing.T) {
|
||||||
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
require.True(t, got.IsOK(), "expected create-validator to be ok, got %v", got)
|
||||||
|
|
||||||
// slash and jail the first validator
|
// slash and jail the first validator
|
||||||
keeper.Slash(ctx, keep.PKs[0], 0, initBond, sdk.NewDecWithPrec(5, 1))
|
consAddr0 := sdk.ConsAddress(keep.PKs[0].Address())
|
||||||
keeper.Jail(ctx, keep.PKs[0])
|
keeper.Slash(ctx, consAddr0, 0, initBond, sdk.NewDecWithPrec(5, 1))
|
||||||
|
keeper.Jail(ctx, consAddr0)
|
||||||
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
validator, found = keeper.GetValidator(ctx, validatorAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.Equal(t, sdk.Unbonding, validator.Status) // ensure is unbonding
|
require.Equal(t, sdk.Unbonding, validator.Status) // ensure is unbonding
|
||||||
|
@ -198,11 +199,12 @@ func TestLegacyValidatorDelegations(t *testing.T) {
|
||||||
setInstantUnbondPeriod(keeper, ctx)
|
setInstantUnbondPeriod(keeper, ctx)
|
||||||
|
|
||||||
bondAmount := int64(10)
|
bondAmount := int64(10)
|
||||||
valAddr, valPubKey := sdk.ValAddress(keep.Addrs[0]), keep.PKs[0]
|
valAddr := sdk.ValAddress(keep.Addrs[0])
|
||||||
|
valConsPubKey, valConsAddr := keep.PKs[0], sdk.ConsAddress(keep.PKs[0].Address())
|
||||||
delAddr := keep.Addrs[1]
|
delAddr := keep.Addrs[1]
|
||||||
|
|
||||||
// create validator
|
// create validator
|
||||||
msgCreateVal := newTestMsgCreateValidator(valAddr, valPubKey, bondAmount)
|
msgCreateVal := newTestMsgCreateValidator(valAddr, valConsPubKey, bondAmount)
|
||||||
got := handleMsgCreateValidator(ctx, msgCreateVal, keeper)
|
got := handleMsgCreateValidator(ctx, msgCreateVal, keeper)
|
||||||
require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got)
|
require.True(t, got.IsOK(), "expected create validator msg to be ok, got %v", got)
|
||||||
|
|
||||||
|
@ -264,7 +266,7 @@ func TestLegacyValidatorDelegations(t *testing.T) {
|
||||||
require.Equal(t, bondAmount*2, validator.Tokens.RoundInt64())
|
require.Equal(t, bondAmount*2, validator.Tokens.RoundInt64())
|
||||||
|
|
||||||
// unjail the validator now that is has non-zero self-delegated shares
|
// unjail the validator now that is has non-zero self-delegated shares
|
||||||
keeper.Unjail(ctx, valPubKey)
|
keeper.Unjail(ctx, valConsAddr)
|
||||||
|
|
||||||
// verify the validator can now accept delegations
|
// verify the validator can now accept delegations
|
||||||
msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount)
|
msgDelegate = newTestMsgDelegate(delAddr, valAddr, bondAmount)
|
||||||
|
@ -911,6 +913,7 @@ func TestCliffValidator(t *testing.T) {
|
||||||
func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
||||||
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
ctx, _, keeper := keep.CreateTestInput(t, false, 1000)
|
||||||
valA, valB, del := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]), keep.Addrs[2]
|
valA, valB, del := sdk.ValAddress(keep.Addrs[0]), sdk.ValAddress(keep.Addrs[1]), keep.Addrs[2]
|
||||||
|
consAddr0 := sdk.ConsAddress(keep.PKs[0].Address())
|
||||||
|
|
||||||
msgCreateValidator := newTestMsgCreateValidator(valA, keep.PKs[0], 10)
|
msgCreateValidator := newTestMsgCreateValidator(valA, keep.PKs[0], 10)
|
||||||
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
got := handleMsgCreateValidator(ctx, msgCreateValidator, keeper)
|
||||||
|
@ -944,7 +947,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
||||||
require.Equal(t, sdk.NewDec(6), delegation.Shares)
|
require.Equal(t, sdk.NewDec(6), delegation.Shares)
|
||||||
|
|
||||||
// slash the validator by half
|
// slash the validator by half
|
||||||
keeper.Slash(ctx, keep.PKs[0], 0, 20, sdk.NewDecWithPrec(5, 1))
|
keeper.Slash(ctx, consAddr0, 0, 20, sdk.NewDecWithPrec(5, 1))
|
||||||
|
|
||||||
// unbonding delegation should have been slashed by half
|
// unbonding delegation should have been slashed by half
|
||||||
unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA)
|
unbonding, found := keeper.GetUnbondingDelegation(ctx, del, valA)
|
||||||
|
@ -968,7 +971,7 @@ func TestBondUnbondRedelegateSlashTwice(t *testing.T) {
|
||||||
|
|
||||||
// slash the validator for an infraction committed after the unbonding and redelegation begin
|
// slash the validator for an infraction committed after the unbonding and redelegation begin
|
||||||
ctx = ctx.WithBlockHeight(3)
|
ctx = ctx.WithBlockHeight(3)
|
||||||
keeper.Slash(ctx, keep.PKs[0], 2, 10, sdk.NewDecWithPrec(5, 1))
|
keeper.Slash(ctx, consAddr0, 2, 10, sdk.NewDecWithPrec(5, 1))
|
||||||
|
|
||||||
// unbonding delegation should be unchanged
|
// unbonding delegation should be unchanged
|
||||||
unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA)
|
unbonding, found = keeper.GetUnbondingDelegation(ctx, del, valA)
|
||||||
|
|
|
@ -66,6 +66,12 @@ func (k Keeper) SetDelegation(ctx sdk.Context, delegation types.Delegation) {
|
||||||
|
|
||||||
// remove a delegation from store
|
// remove a delegation from store
|
||||||
func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) {
|
func (k Keeper) RemoveDelegation(ctx sdk.Context, delegation types.Delegation) {
|
||||||
|
|
||||||
|
// call the hook if present
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnDelegationRemoved(ctx, delegation.DelegatorAddr, delegation.ValidatorAddr)
|
||||||
|
}
|
||||||
|
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr))
|
store.Delete(GetDelegationKey(delegation.DelegatorAddr, delegation.ValidatorAddr))
|
||||||
}
|
}
|
||||||
|
@ -275,6 +281,11 @@ func (k Keeper) Delegate(ctx sdk.Context, delAddr sdk.AccAddress, bondAmt sdk.Co
|
||||||
k.SetDelegation(ctx, delegation)
|
k.SetDelegation(ctx, delegation)
|
||||||
k.UpdateValidator(ctx, validator)
|
k.UpdateValidator(ctx, validator)
|
||||||
|
|
||||||
|
// call the hook if present
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr)
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,6 +344,11 @@ func (k Keeper) unbond(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValA
|
||||||
k.RemoveValidator(ctx, validator.OperatorAddr)
|
k.RemoveValidator(ctx, validator.OperatorAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call the hook if present
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnDelegationSharesModified(ctx, delegation.DelegatorAddr, validator.OperatorAddr)
|
||||||
|
}
|
||||||
|
|
||||||
return amount, nil
|
return amount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
//nolint
|
||||||
|
package keeper
|
||||||
|
|
||||||
|
import (
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Expose the hooks if present
|
||||||
|
func (k Keeper) OnValidatorCreated(ctx sdk.Context, address sdk.ValAddress) {
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnValidatorCreated(ctx, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (k Keeper) OnValidatorCommissionChange(ctx sdk.Context, address sdk.ValAddress) {
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnValidatorCommissionChange(ctx, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) OnValidatorRemoved(ctx sdk.Context, address sdk.ValAddress) {
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnValidatorRemoved(ctx, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) OnValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) {
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnValidatorBonded(ctx, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) OnValidatorBeginUnbonding(ctx sdk.Context, address sdk.ConsAddress) {
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnValidatorBeginUnbonding(ctx, address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnDelegationCreated(ctx, delAddr, valAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnDelegationSharesModified(ctx, delAddr, valAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Keeper) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnDelegationRemoved(ctx, delAddr, valAddr)
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,11 +10,11 @@ import (
|
||||||
|
|
||||||
// keeper of the stake store
|
// keeper of the stake store
|
||||||
type Keeper struct {
|
type Keeper struct {
|
||||||
storeKey sdk.StoreKey
|
storeKey sdk.StoreKey
|
||||||
storeTKey sdk.StoreKey
|
storeTKey sdk.StoreKey
|
||||||
cdc *codec.Codec
|
cdc *codec.Codec
|
||||||
bankKeeper bank.Keeper
|
bankKeeper bank.Keeper
|
||||||
validatorHooks sdk.ValidatorHooks
|
hooks sdk.StakingHooks
|
||||||
|
|
||||||
// codespace
|
// codespace
|
||||||
codespace sdk.CodespaceType
|
codespace sdk.CodespaceType
|
||||||
|
@ -22,22 +22,22 @@ type Keeper struct {
|
||||||
|
|
||||||
func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
|
func NewKeeper(cdc *codec.Codec, key, tkey sdk.StoreKey, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
|
||||||
keeper := Keeper{
|
keeper := Keeper{
|
||||||
storeKey: key,
|
storeKey: key,
|
||||||
storeTKey: tkey,
|
storeTKey: tkey,
|
||||||
cdc: cdc,
|
cdc: cdc,
|
||||||
bankKeeper: ck,
|
bankKeeper: ck,
|
||||||
validatorHooks: nil,
|
hooks: nil,
|
||||||
codespace: codespace,
|
codespace: codespace,
|
||||||
}
|
}
|
||||||
return keeper
|
return keeper
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the validator hooks
|
// Set the validator hooks
|
||||||
func (k Keeper) WithValidatorHooks(v sdk.ValidatorHooks) Keeper {
|
func (k Keeper) WithHooks(sh sdk.StakingHooks) Keeper {
|
||||||
if k.validatorHooks != nil {
|
if k.hooks != nil {
|
||||||
panic("cannot set validator hooks twice")
|
panic("cannot set validator hooks twice")
|
||||||
}
|
}
|
||||||
k.validatorHooks = v
|
k.hooks = sh
|
||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@ package keeper
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/crypto"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
)
|
)
|
||||||
|
@ -17,7 +15,7 @@ var (
|
||||||
ParamKey = []byte{0x00} // key for parameters relating to staking
|
ParamKey = []byte{0x00} // key for parameters relating to staking
|
||||||
PoolKey = []byte{0x01} // key for the staking pools
|
PoolKey = []byte{0x01} // key for the staking pools
|
||||||
ValidatorsKey = []byte{0x02} // prefix for each key to a validator
|
ValidatorsKey = []byte{0x02} // prefix for each key to a validator
|
||||||
ValidatorsByPubKeyIndexKey = []byte{0x03} // prefix for each key to a validator index, by pubkey
|
ValidatorsByConsAddrKey = []byte{0x03} // prefix for each key to a validator index, by pubkey
|
||||||
ValidatorsBondedIndexKey = []byte{0x04} // prefix for each key to a validator index, for bonded validators
|
ValidatorsBondedIndexKey = []byte{0x04} // prefix for each key to a validator index, for bonded validators
|
||||||
ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power
|
ValidatorsByPowerIndexKey = []byte{0x05} // prefix for each key to a validator index, sorted by power
|
||||||
ValidatorCliffIndexKey = []byte{0x06} // key for the validator index of the cliff validator
|
ValidatorCliffIndexKey = []byte{0x06} // key for the validator index of the cliff validator
|
||||||
|
@ -44,8 +42,8 @@ func GetValidatorKey(operatorAddr sdk.ValAddress) []byte {
|
||||||
|
|
||||||
// gets the key for the validator with pubkey
|
// gets the key for the validator with pubkey
|
||||||
// VALUE: validator operator address ([]byte)
|
// VALUE: validator operator address ([]byte)
|
||||||
func GetValidatorByPubKeyIndexKey(pubkey crypto.PubKey) []byte {
|
func GetValidatorByConsAddrKey(addr sdk.ConsAddress) []byte {
|
||||||
return append(ValidatorsByPubKeyIndexKey, pubkey.Bytes()...)
|
return append(ValidatorsByConsAddrKey, addr.Bytes()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets the key for the current validator group
|
// gets the key for the current validator group
|
||||||
|
|
|
@ -3,10 +3,9 @@ package keeper
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/crypto"
|
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
"github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
|
"github.com/tendermint/tendermint/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Implements ValidatorSet
|
// Implements ValidatorSet
|
||||||
|
@ -60,8 +59,17 @@ func (k Keeper) Validator(ctx sdk.Context, address sdk.ValAddress) sdk.Validator
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the sdk.validator for a particular pubkey
|
// get the sdk.validator for a particular pubkey
|
||||||
func (k Keeper) ValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) sdk.Validator {
|
func (k Keeper) ValidatorByConsAddr(ctx sdk.Context, addr sdk.ConsAddress) sdk.Validator {
|
||||||
val, found := k.GetValidatorByPubKey(ctx, pubkey)
|
val, found := k.GetValidatorByConsAddr(ctx, addr)
|
||||||
|
if !found {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the sdk.validator for a particular pubkey
|
||||||
|
func (k Keeper) ValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) sdk.Validator {
|
||||||
|
val, found := k.GetValidatorByConsPubKey(ctx, consPubKey)
|
||||||
if !found {
|
if !found {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -95,15 +103,16 @@ func (k Keeper) Delegation(ctx sdk.Context, addrDel sdk.AccAddress, addrVal sdk.
|
||||||
return bond
|
return bond
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate through the active validator set and perform the provided function
|
// iterate through all of the delegations from a delegator
|
||||||
func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress, fn func(index int64, delegation sdk.Delegation) (stop bool)) {
|
func (k Keeper) IterateDelegations(ctx sdk.Context, delAddr sdk.AccAddress,
|
||||||
|
fn func(index int64, del sdk.Delegation) (stop bool)) {
|
||||||
|
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
key := GetDelegationsKey(delAddr)
|
delegatorPrefixKey := GetDelegationsKey(delAddr)
|
||||||
iterator := sdk.KVStorePrefixIterator(store, key)
|
iterator := sdk.KVStorePrefixIterator(store, delegatorPrefixKey) //smallest to largest
|
||||||
i := int64(0)
|
for i := int64(0); iterator.Valid(); iterator.Next() {
|
||||||
for ; iterator.Valid(); iterator.Next() {
|
del := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value())
|
||||||
delegation := types.MustUnmarshalDelegation(k.cdc, iterator.Key(), iterator.Value())
|
stop := fn(i, del)
|
||||||
stop := fn(i, delegation) // XXX is this safe will the fields be able to get written to?
|
|
||||||
if stop {
|
if stop {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
types "github.com/cosmos/cosmos-sdk/x/stake/types"
|
types "github.com/cosmos/cosmos-sdk/x/stake/types"
|
||||||
"github.com/tendermint/tendermint/crypto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Slash a validator for an infraction committed at a known height
|
// Slash a validator for an infraction committed at a known height
|
||||||
|
@ -24,7 +23,7 @@ import (
|
||||||
// not at a height in the future
|
// not at a height in the future
|
||||||
//
|
//
|
||||||
// nolint: gocyclo
|
// nolint: gocyclo
|
||||||
func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight int64, power int64, slashFactor sdk.Dec) {
|
func (k Keeper) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeight int64, power int64, slashFactor sdk.Dec) {
|
||||||
logger := ctx.Logger().With("module", "x/stake")
|
logger := ctx.Logger().With("module", "x/stake")
|
||||||
|
|
||||||
if slashFactor.LT(sdk.ZeroDec()) {
|
if slashFactor.LT(sdk.ZeroDec()) {
|
||||||
|
@ -36,7 +35,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
||||||
// ref https://github.com/cosmos/cosmos-sdk/issues/1348
|
// ref https://github.com/cosmos/cosmos-sdk/issues/1348
|
||||||
// ref https://github.com/cosmos/cosmos-sdk/issues/1471
|
// ref https://github.com/cosmos/cosmos-sdk/issues/1471
|
||||||
|
|
||||||
validator, found := k.GetValidatorByPubKey(ctx, pubkey)
|
validator, found := k.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
if !found {
|
if !found {
|
||||||
// If not found, the validator must have been overslashed and removed - so we don't need to do anything
|
// If not found, the validator must have been overslashed and removed - so we don't need to do anything
|
||||||
// NOTE: Correctness dependent on invariant that unbonding delegations / redelegations must also have been completely
|
// NOTE: Correctness dependent on invariant that unbonding delegations / redelegations must also have been completely
|
||||||
|
@ -44,7 +43,7 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
||||||
// Log the slash attempt for future reference (maybe we should tag it too)
|
// Log the slash attempt for future reference (maybe we should tag it too)
|
||||||
logger.Error(fmt.Sprintf(
|
logger.Error(fmt.Sprintf(
|
||||||
"WARNING: Ignored attempt to slash a nonexistent validator with address %s, we recommend you investigate immediately",
|
"WARNING: Ignored attempt to slash a nonexistent validator with address %s, we recommend you investigate immediately",
|
||||||
pubkey.Address()))
|
consAddr))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,36 +124,28 @@ func (k Keeper) Slash(ctx sdk.Context, pubkey crypto.PubKey, infractionHeight in
|
||||||
}
|
}
|
||||||
|
|
||||||
// jail a validator
|
// jail a validator
|
||||||
func (k Keeper) Jail(ctx sdk.Context, pubkey crypto.PubKey) {
|
func (k Keeper) Jail(ctx sdk.Context, consAddr sdk.ConsAddress) {
|
||||||
k.setJailed(ctx, pubkey, true)
|
k.setJailed(ctx, consAddr, true)
|
||||||
validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String())
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
logger := ctx.Logger().With("module", "x/stake")
|
logger := ctx.Logger().With("module", "x/stake")
|
||||||
logger.Info(fmt.Sprintf("validator %s jailed", validatorAddr))
|
logger.Info(fmt.Sprintf("validator %s jailed", consAddr))
|
||||||
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
|
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// unjail a validator
|
// unjail a validator
|
||||||
func (k Keeper) Unjail(ctx sdk.Context, pubkey crypto.PubKey) {
|
func (k Keeper) Unjail(ctx sdk.Context, consAddr sdk.ConsAddress) {
|
||||||
k.setJailed(ctx, pubkey, false)
|
k.setJailed(ctx, consAddr, false)
|
||||||
validatorAddr, err := sdk.ValAddressFromHex(pubkey.Address().String())
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
logger := ctx.Logger().With("module", "x/stake")
|
logger := ctx.Logger().With("module", "x/stake")
|
||||||
logger.Info(fmt.Sprintf("validator %s unjailed", validatorAddr))
|
logger.Info(fmt.Sprintf("validator %s unjailed", consAddr))
|
||||||
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
|
// TODO Return event(s), blocked on https://github.com/tendermint/tendermint/pull/1803
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the jailed flag on a validator
|
// set the jailed flag on a validator
|
||||||
func (k Keeper) setJailed(ctx sdk.Context, pubkey crypto.PubKey, isJailed bool) {
|
func (k Keeper) setJailed(ctx sdk.Context, consAddr sdk.ConsAddress, isJailed bool) {
|
||||||
validator, found := k.GetValidatorByPubKey(ctx, pubkey)
|
validator, found := k.GetValidatorByConsAddr(ctx, sdk.ConsAddress(consAddr))
|
||||||
if !found {
|
if !found {
|
||||||
panic(fmt.Errorf("validator with pubkey %s not found, cannot set jailed to %v", pubkey, isJailed))
|
panic(fmt.Errorf("validator with consensus-Address %s not found, cannot set jailed to %v", consAddr, isJailed))
|
||||||
}
|
}
|
||||||
validator.Jailed = isJailed
|
validator.Jailed = isJailed
|
||||||
k.UpdateValidator(ctx, validator) // update validator, possibly unbonding or bonding it
|
k.UpdateValidator(ctx, validator) // update validator, possibly unbonding or bonding it
|
||||||
|
|
|
@ -27,7 +27,7 @@ func setupHelper(t *testing.T, amt int64) (sdk.Context, Keeper, types.Params) {
|
||||||
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(amt))
|
validator, pool, _ = validator.AddTokensFromDel(pool, sdk.NewInt(amt))
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
validator = keeper.UpdateValidator(ctx, validator)
|
validator = keeper.UpdateValidator(ctx, validator)
|
||||||
keeper.SetValidatorByPubKeyIndex(ctx, validator)
|
keeper.SetValidatorByConsAddr(ctx, validator)
|
||||||
}
|
}
|
||||||
pool = keeper.GetPool(ctx)
|
pool = keeper.GetPool(ctx)
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ func TestRevocation(t *testing.T) {
|
||||||
// setup
|
// setup
|
||||||
ctx, keeper, _ := setupHelper(t, 10)
|
ctx, keeper, _ := setupHelper(t, 10)
|
||||||
addr := addrVals[0]
|
addr := addrVals[0]
|
||||||
pk := PKs[0]
|
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||||
|
|
||||||
// initial state
|
// initial state
|
||||||
val, found := keeper.GetValidator(ctx, addr)
|
val, found := keeper.GetValidator(ctx, addr)
|
||||||
|
@ -50,13 +50,13 @@ func TestRevocation(t *testing.T) {
|
||||||
require.False(t, val.GetJailed())
|
require.False(t, val.GetJailed())
|
||||||
|
|
||||||
// test jail
|
// test jail
|
||||||
keeper.Jail(ctx, pk)
|
keeper.Jail(ctx, consAddr)
|
||||||
val, found = keeper.GetValidator(ctx, addr)
|
val, found = keeper.GetValidator(ctx, addr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.True(t, val.GetJailed())
|
require.True(t, val.GetJailed())
|
||||||
|
|
||||||
// test unjail
|
// test unjail
|
||||||
keeper.Unjail(ctx, pk)
|
keeper.Unjail(ctx, consAddr)
|
||||||
val, found = keeper.GetValidator(ctx, addr)
|
val, found = keeper.GetValidator(ctx, addr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.False(t, val.GetJailed())
|
require.False(t, val.GetJailed())
|
||||||
|
@ -179,24 +179,24 @@ func TestSlashRedelegation(t *testing.T) {
|
||||||
// tests Slash at a future height (must panic)
|
// tests Slash at a future height (must panic)
|
||||||
func TestSlashAtFutureHeight(t *testing.T) {
|
func TestSlashAtFutureHeight(t *testing.T) {
|
||||||
ctx, keeper, _ := setupHelper(t, 10)
|
ctx, keeper, _ := setupHelper(t, 10)
|
||||||
pk := PKs[0]
|
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||||
fraction := sdk.NewDecWithPrec(5, 1)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
require.Panics(t, func() { keeper.Slash(ctx, pk, 1, 10, fraction) })
|
require.Panics(t, func() { keeper.Slash(ctx, consAddr, 1, 10, fraction) })
|
||||||
}
|
}
|
||||||
|
|
||||||
// tests Slash at the current height
|
// tests Slash at the current height
|
||||||
func TestSlashValidatorAtCurrentHeight(t *testing.T) {
|
func TestSlashValidatorAtCurrentHeight(t *testing.T) {
|
||||||
ctx, keeper, _ := setupHelper(t, 10)
|
ctx, keeper, _ := setupHelper(t, 10)
|
||||||
pk := PKs[0]
|
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||||
fraction := sdk.NewDecWithPrec(5, 1)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
|
|
||||||
oldPool := keeper.GetPool(ctx)
|
oldPool := keeper.GetPool(ctx)
|
||||||
validator, found := keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
keeper.Slash(ctx, pk, ctx.BlockHeight(), 10, fraction)
|
keeper.Slash(ctx, consAddr, ctx.BlockHeight(), 10, fraction)
|
||||||
|
|
||||||
// read updated state
|
// read updated state
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
newPool := keeper.GetPool(ctx)
|
newPool := keeper.GetPool(ctx)
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ func TestSlashValidatorAtCurrentHeight(t *testing.T) {
|
||||||
// tests Slash at a previous height with an unbonding delegation
|
// tests Slash at a previous height with an unbonding delegation
|
||||||
func TestSlashWithUnbondingDelegation(t *testing.T) {
|
func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
ctx, keeper, params := setupHelper(t, 10)
|
ctx, keeper, params := setupHelper(t, 10)
|
||||||
pk := PKs[0]
|
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||||
fraction := sdk.NewDecWithPrec(5, 1)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
|
|
||||||
// set an unbonding delegation
|
// set an unbonding delegation
|
||||||
|
@ -227,9 +227,9 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
// slash validator for the first time
|
// slash validator for the first time
|
||||||
ctx = ctx.WithBlockHeight(12)
|
ctx = ctx.WithBlockHeight(12)
|
||||||
oldPool := keeper.GetPool(ctx)
|
oldPool := keeper.GetPool(ctx)
|
||||||
validator, found := keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
keeper.Slash(ctx, pk, 10, 10, fraction)
|
keeper.Slash(ctx, consAddr, 10, 10, fraction)
|
||||||
|
|
||||||
// read updating unbonding delegation
|
// read updating unbonding delegation
|
||||||
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||||
|
@ -241,7 +241,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
// bonded tokens burned
|
// bonded tokens burned
|
||||||
require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
||||||
// read updated validator
|
// read updated validator
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// power decreased by 3 - 6 stake originally bonded at the time of infraction
|
// power decreased by 3 - 6 stake originally bonded at the time of infraction
|
||||||
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
||||||
|
@ -251,7 +251,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
|
|
||||||
// slash validator again
|
// slash validator again
|
||||||
ctx = ctx.WithBlockHeight(13)
|
ctx = ctx.WithBlockHeight(13)
|
||||||
keeper.Slash(ctx, pk, 9, 10, fraction)
|
keeper.Slash(ctx, consAddr, 9, 10, fraction)
|
||||||
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// balance decreased again
|
// balance decreased again
|
||||||
|
@ -261,7 +261,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
// bonded tokens burned again
|
// bonded tokens burned again
|
||||||
require.Equal(t, int64(6), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
require.Equal(t, int64(6), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
||||||
// read updated validator
|
// read updated validator
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// power decreased by 3 again
|
// power decreased by 3 again
|
||||||
require.Equal(t, sdk.NewDec(4), validator.GetPower())
|
require.Equal(t, sdk.NewDec(4), validator.GetPower())
|
||||||
|
@ -271,7 +271,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
// on the unbonding delegation, but it will slash stake bonded since the infraction
|
// on the unbonding delegation, but it will slash stake bonded since the infraction
|
||||||
// this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440
|
// this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440
|
||||||
ctx = ctx.WithBlockHeight(13)
|
ctx = ctx.WithBlockHeight(13)
|
||||||
keeper.Slash(ctx, pk, 9, 10, fraction)
|
keeper.Slash(ctx, consAddr, 9, 10, fraction)
|
||||||
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// balance unchanged
|
// balance unchanged
|
||||||
|
@ -281,7 +281,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
// bonded tokens burned again
|
// bonded tokens burned again
|
||||||
require.Equal(t, int64(9), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
require.Equal(t, int64(9), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
||||||
// read updated validator
|
// read updated validator
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// power decreased by 3 again
|
// power decreased by 3 again
|
||||||
require.Equal(t, sdk.NewDec(1), validator.GetPower())
|
require.Equal(t, sdk.NewDec(1), validator.GetPower())
|
||||||
|
@ -291,7 +291,7 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
// on the unbonding delegation, but it will slash stake bonded since the infraction
|
// on the unbonding delegation, but it will slash stake bonded since the infraction
|
||||||
// this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440
|
// this may not be the desirable behaviour, ref https://github.com/cosmos/cosmos-sdk/issues/1440
|
||||||
ctx = ctx.WithBlockHeight(13)
|
ctx = ctx.WithBlockHeight(13)
|
||||||
keeper.Slash(ctx, pk, 9, 10, fraction)
|
keeper.Slash(ctx, consAddr, 9, 10, fraction)
|
||||||
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
ubd, found = keeper.GetUnbondingDelegation(ctx, addrDels[0], addrVals[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// balance unchanged
|
// balance unchanged
|
||||||
|
@ -303,14 +303,14 @@ func TestSlashWithUnbondingDelegation(t *testing.T) {
|
||||||
// read updated validator
|
// read updated validator
|
||||||
// power decreased by 1 again, validator is out of stake
|
// power decreased by 1 again, validator is out of stake
|
||||||
// ergo validator should have been removed from the store
|
// ergo validator should have been removed from the store
|
||||||
_, found = keeper.GetValidatorByPubKey(ctx, pk)
|
_, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tests Slash at a previous height with a redelegation
|
// tests Slash at a previous height with a redelegation
|
||||||
func TestSlashWithRedelegation(t *testing.T) {
|
func TestSlashWithRedelegation(t *testing.T) {
|
||||||
ctx, keeper, params := setupHelper(t, 10)
|
ctx, keeper, params := setupHelper(t, 10)
|
||||||
pk := PKs[0]
|
consAddr := sdk.ConsAddress(PKs[0].Address())
|
||||||
fraction := sdk.NewDecWithPrec(5, 1)
|
fraction := sdk.NewDecWithPrec(5, 1)
|
||||||
|
|
||||||
// set a redelegation
|
// set a redelegation
|
||||||
|
@ -343,9 +343,9 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
// slash validator
|
// slash validator
|
||||||
ctx = ctx.WithBlockHeight(12)
|
ctx = ctx.WithBlockHeight(12)
|
||||||
oldPool := keeper.GetPool(ctx)
|
oldPool := keeper.GetPool(ctx)
|
||||||
validator, found := keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found := keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
keeper.Slash(ctx, pk, 10, 10, fraction)
|
keeper.Slash(ctx, consAddr, 10, 10, fraction)
|
||||||
|
|
||||||
// read updating redelegation
|
// read updating redelegation
|
||||||
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||||
|
@ -357,7 +357,7 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
// bonded tokens burned
|
// bonded tokens burned
|
||||||
require.Equal(t, int64(5), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
require.Equal(t, int64(5), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
||||||
// read updated validator
|
// read updated validator
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// power decreased by 2 - 4 stake originally bonded at the time of infraction
|
// power decreased by 2 - 4 stake originally bonded at the time of infraction
|
||||||
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
// was still bonded at the time of discovery and was slashed by half, 4 stake
|
||||||
|
@ -367,9 +367,9 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
|
|
||||||
// slash the validator again
|
// slash the validator again
|
||||||
ctx = ctx.WithBlockHeight(12)
|
ctx = ctx.WithBlockHeight(12)
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
require.NotPanics(t, func() { keeper.Slash(ctx, pk, 10, 10, sdk.OneDec()) })
|
require.NotPanics(t, func() { keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec()) })
|
||||||
|
|
||||||
// read updating redelegation
|
// read updating redelegation
|
||||||
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||||
|
@ -381,16 +381,16 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
// seven bonded tokens burned
|
// seven bonded tokens burned
|
||||||
require.Equal(t, int64(12), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
require.Equal(t, int64(12), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
||||||
// read updated validator
|
// read updated validator
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// power decreased by 4
|
// power decreased by 4
|
||||||
require.Equal(t, sdk.NewDec(4), validator.GetPower())
|
require.Equal(t, sdk.NewDec(4), validator.GetPower())
|
||||||
|
|
||||||
// slash the validator again, by 100%
|
// slash the validator again, by 100%
|
||||||
ctx = ctx.WithBlockHeight(12)
|
ctx = ctx.WithBlockHeight(12)
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, pk)
|
validator, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
keeper.Slash(ctx, pk, 10, 10, sdk.OneDec())
|
keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec())
|
||||||
|
|
||||||
// read updating redelegation
|
// read updating redelegation
|
||||||
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||||
|
@ -403,16 +403,16 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
||||||
// read updated validator
|
// read updated validator
|
||||||
// validator decreased to zero power, should have been removed from the store
|
// validator decreased to zero power, should have been removed from the store
|
||||||
_, found = keeper.GetValidatorByPubKey(ctx, pk)
|
_, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
|
|
||||||
// slash the validator again, by 100%
|
// slash the validator again, by 100%
|
||||||
// no stake remains to be slashed
|
// no stake remains to be slashed
|
||||||
ctx = ctx.WithBlockHeight(12)
|
ctx = ctx.WithBlockHeight(12)
|
||||||
// validator no longer in the store
|
// validator no longer in the store
|
||||||
_, found = keeper.GetValidatorByPubKey(ctx, pk)
|
_, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
keeper.Slash(ctx, pk, 10, 10, sdk.OneDec())
|
keeper.Slash(ctx, consAddr, 10, 10, sdk.OneDec())
|
||||||
|
|
||||||
// read updating redelegation
|
// read updating redelegation
|
||||||
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
rd, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||||
|
@ -425,7 +425,7 @@ func TestSlashWithRedelegation(t *testing.T) {
|
||||||
require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
require.Equal(t, int64(16), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
||||||
// read updated validator
|
// read updated validator
|
||||||
// power still zero, still not in the store
|
// power still zero, still not in the store
|
||||||
_, found = keeper.GetValidatorByPubKey(ctx, pk)
|
_, found = keeper.GetValidatorByConsAddr(ctx, consAddr)
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,9 +472,10 @@ func TestSlashBoth(t *testing.T) {
|
||||||
// slash validator
|
// slash validator
|
||||||
ctx = ctx.WithBlockHeight(12)
|
ctx = ctx.WithBlockHeight(12)
|
||||||
oldPool := keeper.GetPool(ctx)
|
oldPool := keeper.GetPool(ctx)
|
||||||
validator, found := keeper.GetValidatorByPubKey(ctx, PKs[0])
|
validator, found := keeper.GetValidatorByConsPubKey(ctx, PKs[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
keeper.Slash(ctx, PKs[0], 10, 10, fraction)
|
consAddr0 := sdk.ConsAddress(PKs[0].Address())
|
||||||
|
keeper.Slash(ctx, consAddr0, 10, 10, fraction)
|
||||||
|
|
||||||
// read updating redelegation
|
// read updating redelegation
|
||||||
rdA, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
rdA, found = keeper.GetRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1])
|
||||||
|
@ -488,7 +489,7 @@ func TestSlashBoth(t *testing.T) {
|
||||||
// bonded tokens burned
|
// bonded tokens burned
|
||||||
require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
require.Equal(t, int64(3), oldPool.BondedTokens.Sub(newPool.BondedTokens).RoundInt64())
|
||||||
// read updated validator
|
// read updated validator
|
||||||
validator, found = keeper.GetValidatorByPubKey(ctx, PKs[0])
|
validator, found = keeper.GetValidatorByConsPubKey(ctx, PKs[0])
|
||||||
require.True(t, found)
|
require.True(t, found)
|
||||||
// power not decreased, all stake was bonded since
|
// power not decreased, all stake was bonded since
|
||||||
require.Equal(t, sdk.NewDec(10), validator.GetPower())
|
require.Equal(t, sdk.NewDec(10), validator.GetPower())
|
||||||
|
|
|
@ -58,14 +58,25 @@ func (k Keeper) GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator ty
|
||||||
return validator, true
|
return validator, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// get a single validator by pubkey
|
// get a single validator by consensus address
|
||||||
func (k Keeper) GetValidatorByPubKey(ctx sdk.Context, pubkey crypto.PubKey) (validator types.Validator, found bool) {
|
func (k Keeper) GetValidatorByConsAddr(ctx sdk.Context, consAddr sdk.ConsAddress) (validator types.Validator, found bool) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
addr := store.Get(GetValidatorByPubKeyIndexKey(pubkey))
|
opAddr := store.Get(GetValidatorByConsAddrKey(consAddr))
|
||||||
if addr == nil {
|
if opAddr == nil {
|
||||||
return validator, false
|
return validator, false
|
||||||
}
|
}
|
||||||
return k.GetValidator(ctx, addr)
|
return k.GetValidator(ctx, opAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a single validator by pubkey
|
||||||
|
func (k Keeper) GetValidatorByConsPubKey(ctx sdk.Context, consPubKey crypto.PubKey) (validator types.Validator, found bool) {
|
||||||
|
store := ctx.KVStore(k.storeKey)
|
||||||
|
consAddr := sdk.ConsAddress(consPubKey.Address())
|
||||||
|
opAddr := store.Get(GetValidatorByConsAddrKey(consAddr))
|
||||||
|
if opAddr == nil {
|
||||||
|
return validator, false
|
||||||
|
}
|
||||||
|
return k.GetValidator(ctx, opAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the main record holding validator details
|
// set the main record holding validator details
|
||||||
|
@ -76,9 +87,11 @@ func (k Keeper) SetValidator(ctx sdk.Context, validator types.Validator) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// validator index
|
// validator index
|
||||||
func (k Keeper) SetValidatorByPubKeyIndex(ctx sdk.Context, validator types.Validator) {
|
// TODO change to SetValidatorByConsAddr? used for retrieving from ConsPubkey as well- kinda confusing
|
||||||
|
func (k Keeper) SetValidatorByConsAddr(ctx sdk.Context, validator types.Validator) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
store.Set(GetValidatorByPubKeyIndexKey(validator.ConsPubKey), validator.OperatorAddr)
|
consAddr := sdk.ConsAddress(validator.OperatorAddr.Bytes())
|
||||||
|
store.Set(GetValidatorByConsAddrKey(consAddr), validator.OperatorAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validator index
|
// validator index
|
||||||
|
@ -622,8 +635,8 @@ func (k Keeper) beginUnbondingValidator(ctx sdk.Context, validator types.Validat
|
||||||
store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr))
|
store.Delete(GetValidatorsBondedIndexKey(validator.OperatorAddr))
|
||||||
|
|
||||||
// call the unbond hook if present
|
// call the unbond hook if present
|
||||||
if k.validatorHooks != nil {
|
if k.hooks != nil {
|
||||||
k.validatorHooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress())
|
k.hooks.OnValidatorBeginUnbonding(ctx, validator.ConsAddress())
|
||||||
}
|
}
|
||||||
|
|
||||||
// return updated validator
|
// return updated validator
|
||||||
|
@ -657,8 +670,8 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
|
||||||
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI)
|
tstore.Set(GetTendermintUpdatesTKey(validator.OperatorAddr), bzABCI)
|
||||||
|
|
||||||
// call the bond hook if present
|
// call the bond hook if present
|
||||||
if k.validatorHooks != nil {
|
if k.hooks != nil {
|
||||||
k.validatorHooks.OnValidatorBonded(ctx, validator.ConsAddress())
|
k.hooks.OnValidatorBonded(ctx, validator.ConsAddress())
|
||||||
}
|
}
|
||||||
|
|
||||||
// return updated validator
|
// return updated validator
|
||||||
|
@ -668,6 +681,11 @@ func (k Keeper) bondValidator(ctx sdk.Context, validator types.Validator) types.
|
||||||
// remove the validator record and associated indexes
|
// remove the validator record and associated indexes
|
||||||
func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
|
func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
|
||||||
|
|
||||||
|
// call the hook if present
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnValidatorRemoved(ctx, address)
|
||||||
|
}
|
||||||
|
|
||||||
// first retrieve the old validator record
|
// first retrieve the old validator record
|
||||||
validator, found := k.GetValidator(ctx, address)
|
validator, found := k.GetValidator(ctx, address)
|
||||||
if !found {
|
if !found {
|
||||||
|
@ -678,7 +696,7 @@ func (k Keeper) RemoveValidator(ctx sdk.Context, address sdk.ValAddress) {
|
||||||
store := ctx.KVStore(k.storeKey)
|
store := ctx.KVStore(k.storeKey)
|
||||||
pool := k.GetPool(ctx)
|
pool := k.GetPool(ctx)
|
||||||
store.Delete(GetValidatorKey(address))
|
store.Delete(GetValidatorKey(address))
|
||||||
store.Delete(GetValidatorByPubKeyIndexKey(validator.ConsPubKey))
|
store.Delete(GetValidatorByConsAddrKey(sdk.ConsAddress(validator.ConsPubKey.Address())))
|
||||||
store.Delete(GetValidatorsByPowerIndexKey(validator, pool))
|
store.Delete(GetValidatorsByPowerIndexKey(validator, pool))
|
||||||
|
|
||||||
// delete from the current and power weighted validator groups if the validator
|
// delete from the current and power weighted validator groups if the validator
|
||||||
|
@ -727,3 +745,36 @@ func ensureValidatorFound(found bool, ownerAddr []byte) {
|
||||||
panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr))
|
panic(fmt.Sprintf("validator record not found for address: %X\n", ownerAddr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//__________________________________________________________________________
|
||||||
|
|
||||||
|
// XXX remove this code - this is should be superceded by commission work that bez is doing
|
||||||
|
// get a single validator
|
||||||
|
func (k Keeper) UpdateValidatorCommission(ctx sdk.Context, addr sdk.ValAddress, newCommission sdk.Dec) sdk.Error {
|
||||||
|
|
||||||
|
// call the hook if present
|
||||||
|
if k.hooks != nil {
|
||||||
|
k.hooks.OnValidatorCommissionChange(ctx, addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
validator, found := k.GetValidator(ctx, addr)
|
||||||
|
|
||||||
|
// check for errors
|
||||||
|
switch {
|
||||||
|
case !found:
|
||||||
|
return types.ErrNoValidatorFound(k.Codespace())
|
||||||
|
case newCommission.LT(sdk.ZeroDec()):
|
||||||
|
return types.ErrCommissionNegative(k.Codespace())
|
||||||
|
case newCommission.GT(validator.CommissionMax):
|
||||||
|
return types.ErrCommissionBeyondMax(k.Codespace())
|
||||||
|
//case rateChange(Commission) > CommissionMaxChange: // XXX XXX XXX TODO implementation
|
||||||
|
//return types.ErrCommissionPastRate(k.Codespace())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO adjust all the commission terms appropriately
|
||||||
|
|
||||||
|
validator.Commission = newCommission
|
||||||
|
|
||||||
|
k.SetValidator(ctx, validator)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -260,12 +260,13 @@ func TestSlashToZeroPowerRemoved(t *testing.T) {
|
||||||
require.Equal(t, sdk.Unbonded, validator.Status)
|
require.Equal(t, sdk.Unbonded, validator.Status)
|
||||||
require.Equal(t, int64(100), validator.Tokens.RoundInt64())
|
require.Equal(t, int64(100), validator.Tokens.RoundInt64())
|
||||||
keeper.SetPool(ctx, pool)
|
keeper.SetPool(ctx, pool)
|
||||||
keeper.SetValidatorByPubKeyIndex(ctx, validator)
|
keeper.SetValidatorByConsAddr(ctx, validator)
|
||||||
validator = keeper.UpdateValidator(ctx, validator)
|
validator = keeper.UpdateValidator(ctx, validator)
|
||||||
require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool)
|
require.Equal(t, int64(100), validator.Tokens.RoundInt64(), "\nvalidator %v\npool %v", validator, pool)
|
||||||
|
|
||||||
// slash the validator by 100%
|
// slash the validator by 100%
|
||||||
keeper.Slash(ctx, PKs[0], 0, 100, sdk.OneDec())
|
consAddr0 := sdk.ConsAddress(PKs[0].Address())
|
||||||
|
keeper.Slash(ctx, consAddr0, 0, 100, sdk.OneDec())
|
||||||
// validator should have been deleted
|
// validator should have been deleted
|
||||||
_, found := keeper.GetValidator(ctx, addrVals[0])
|
_, found := keeper.GetValidator(ctx, addrVals[0])
|
||||||
require.False(t, found)
|
require.False(t, found)
|
||||||
|
|
|
@ -35,7 +35,7 @@ var (
|
||||||
NewKeeper = keeper.NewKeeper
|
NewKeeper = keeper.NewKeeper
|
||||||
|
|
||||||
GetValidatorKey = keeper.GetValidatorKey
|
GetValidatorKey = keeper.GetValidatorKey
|
||||||
GetValidatorByPubKeyIndexKey = keeper.GetValidatorByPubKeyIndexKey
|
GetValidatorByConsAddrKey = keeper.GetValidatorByConsAddrKey
|
||||||
GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey
|
GetValidatorsBondedIndexKey = keeper.GetValidatorsBondedIndexKey
|
||||||
GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey
|
GetValidatorsByPowerIndexKey = keeper.GetValidatorsByPowerIndexKey
|
||||||
GetTendermintUpdatesTKey = keeper.GetTendermintUpdatesTKey
|
GetTendermintUpdatesTKey = keeper.GetTendermintUpdatesTKey
|
||||||
|
@ -44,7 +44,7 @@ var (
|
||||||
ParamKey = keeper.ParamKey
|
ParamKey = keeper.ParamKey
|
||||||
PoolKey = keeper.PoolKey
|
PoolKey = keeper.PoolKey
|
||||||
ValidatorsKey = keeper.ValidatorsKey
|
ValidatorsKey = keeper.ValidatorsKey
|
||||||
ValidatorsByPubKeyIndexKey = keeper.ValidatorsByPubKeyIndexKey
|
ValidatorsByConsAddrKey = keeper.ValidatorsByConsAddrKey
|
||||||
ValidatorsBondedIndexKey = keeper.ValidatorsBondedIndexKey
|
ValidatorsBondedIndexKey = keeper.ValidatorsBondedIndexKey
|
||||||
ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey
|
ValidatorsByPowerIndexKey = keeper.ValidatorsByPowerIndexKey
|
||||||
ValidatorCliffIndexKey = keeper.ValidatorCliffIndexKey
|
ValidatorCliffIndexKey = keeper.ValidatorCliffIndexKey
|
||||||
|
|
|
@ -22,6 +22,5 @@ func init() {
|
||||||
cdc := codec.New()
|
cdc := codec.New()
|
||||||
RegisterCodec(cdc)
|
RegisterCodec(cdc)
|
||||||
codec.RegisterCrypto(cdc)
|
codec.RegisterCrypto(cdc)
|
||||||
MsgCdc = cdc
|
MsgCdc = cdc.Seal()
|
||||||
//MsgCdc = cdc.Seal() //TODO use when upgraded to go-amino 0.9.10
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ var _ sdk.Delegation = Delegation{}
|
||||||
// nolint - for sdk.Delegation
|
// nolint - for sdk.Delegation
|
||||||
func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr }
|
func (d Delegation) GetDelegator() sdk.AccAddress { return d.DelegatorAddr }
|
||||||
func (d Delegation) GetValidator() sdk.ValAddress { return d.ValidatorAddr }
|
func (d Delegation) GetValidator() sdk.ValAddress { return d.ValidatorAddr }
|
||||||
func (d Delegation) GetBondShares() sdk.Dec { return d.Shares }
|
func (d Delegation) GetShares() sdk.Dec { return d.Shares }
|
||||||
|
|
||||||
// HumanReadableString returns a human readable string representation of a
|
// HumanReadableString returns a human readable string representation of a
|
||||||
// Delegation. An error is returned if the Delegation's delegator or validator
|
// Delegation. An error is returned if the Delegation's delegator or validator
|
||||||
|
|
|
@ -65,6 +65,14 @@ func ErrCommissionHuge(codespace sdk.CodespaceType) sdk.Error {
|
||||||
return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than 100%")
|
return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than 100%")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ErrCommissionBeyondMax(codespace sdk.CodespaceType) sdk.Error {
|
||||||
|
return sdk.NewError(codespace, CodeInvalidValidator, "commission cannot be more than preset commission maximum")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ErrCommissionPastRate(codespace sdk.CodespaceType) sdk.Error {
|
||||||
|
return sdk.NewError(codespace, CodeInvalidValidator, "commission change is greater than the commission rate, please wait before changing your commission more")
|
||||||
|
}
|
||||||
|
|
||||||
func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error {
|
func ErrNilDelegatorAddr(codespace sdk.CodespaceType) sdk.Error {
|
||||||
return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil")
|
return sdk.NewError(codespace, CodeInvalidInput, "delegator address is nil")
|
||||||
}
|
}
|
||||||
|
|
|
@ -470,12 +470,14 @@ func (v Validator) IsUnbonded(ctx sdk.Context) bool {
|
||||||
var _ sdk.Validator = Validator{}
|
var _ sdk.Validator = Validator{}
|
||||||
|
|
||||||
// nolint - for sdk.Validator
|
// nolint - for sdk.Validator
|
||||||
func (v Validator) GetJailed() bool { return v.Jailed }
|
func (v Validator) GetJailed() bool { return v.Jailed }
|
||||||
func (v Validator) GetMoniker() string { return v.Description.Moniker }
|
func (v Validator) GetMoniker() string { return v.Description.Moniker }
|
||||||
func (v Validator) GetStatus() sdk.BondStatus { return v.Status }
|
func (v Validator) GetStatus() sdk.BondStatus { return v.Status }
|
||||||
func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr }
|
func (v Validator) GetOperator() sdk.ValAddress { return v.OperatorAddr }
|
||||||
func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey }
|
func (v Validator) GetPubKey() crypto.PubKey { return v.ConsPubKey }
|
||||||
func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() }
|
func (v Validator) GetConsAddr() sdk.ConsAddress { return sdk.ConsAddress(v.ConsPubKey.Address()) }
|
||||||
func (v Validator) GetTokens() sdk.Dec { return v.Tokens }
|
func (v Validator) GetPower() sdk.Dec { return v.BondedTokens() }
|
||||||
func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares }
|
func (v Validator) GetTokens() sdk.Dec { return v.Tokens }
|
||||||
func (v Validator) GetBondHeight() int64 { return v.BondHeight }
|
func (v Validator) GetCommission() sdk.Dec { return v.Commission }
|
||||||
|
func (v Validator) GetDelegatorShares() sdk.Dec { return v.DelegatorShares }
|
||||||
|
func (v Validator) GetBondHeight() int64 { return v.BondHeight }
|
||||||
|
|
Loading…
Reference in New Issue