Clear array when validator is jailed
This commit is contained in:
parent
096a8bb9ec
commit
9ec35a0ae4
|
@ -9,9 +9,7 @@ import (
|
||||||
func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) {
|
func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) {
|
||||||
// Update the signing info start height or create a new signing info
|
// Update the signing info start height or create a new signing info
|
||||||
signingInfo, found := k.getValidatorSigningInfo(ctx, address)
|
signingInfo, found := k.getValidatorSigningInfo(ctx, address)
|
||||||
if found {
|
if !found {
|
||||||
signingInfo.StartHeight = ctx.BlockHeight()
|
|
||||||
} else {
|
|
||||||
signingInfo = ValidatorSigningInfo{
|
signingInfo = ValidatorSigningInfo{
|
||||||
StartHeight: ctx.BlockHeight(),
|
StartHeight: ctx.BlockHeight(),
|
||||||
IndexOffset: 0,
|
IndexOffset: 0,
|
||||||
|
|
|
@ -144,6 +144,10 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p
|
||||||
k.validatorSet.Slash(ctx, consAddr, distributionHeight, power, k.SlashFractionDowntime(ctx))
|
k.validatorSet.Slash(ctx, consAddr, distributionHeight, power, k.SlashFractionDowntime(ctx))
|
||||||
k.validatorSet.Jail(ctx, consAddr)
|
k.validatorSet.Jail(ctx, consAddr)
|
||||||
signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeUnbondDuration(ctx))
|
signInfo.JailedUntil = ctx.BlockHeader().Time.Add(k.DowntimeUnbondDuration(ctx))
|
||||||
|
// We need to reset the counter & array so that the validator won't be immediately slashed for downtime upon rebonding.
|
||||||
|
signInfo.MissedBlocksCounter = 0
|
||||||
|
signInfo.IndexOffset = 0
|
||||||
|
k.clearValidatorMissedBlockBitArray(ctx, consAddr)
|
||||||
} 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
|
||||||
logger.Info(fmt.Sprintf("Validator %s would have been slashed for downtime, but was either not found in store or already jailed",
|
logger.Info(fmt.Sprintf("Validator %s would have been slashed for downtime, but was either not found in store or already jailed",
|
||||||
|
|
|
@ -380,6 +380,7 @@ func TestValidatorDippingInAndOut(t *testing.T) {
|
||||||
sk.SetParams(ctx, params)
|
sk.SetParams(ctx, params)
|
||||||
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)
|
||||||
|
consAddr := sdk.ConsAddress(addr)
|
||||||
sh := stake.NewHandler(sk)
|
sh := stake.NewHandler(sk)
|
||||||
got := sh(ctx, newTestMsgCreateValidator(addr, val, amt))
|
got := sh(ctx, newTestMsgCreateValidator(addr, val, amt))
|
||||||
require.True(t, got.IsOK())
|
require.True(t, got.IsOK())
|
||||||
|
@ -425,31 +426,48 @@ func TestValidatorDippingInAndOut(t *testing.T) {
|
||||||
require.Equal(t, sdk.Bonded, validator.Status)
|
require.Equal(t, sdk.Bonded, validator.Status)
|
||||||
|
|
||||||
// validator misses 501 blocks
|
// validator misses 501 blocks
|
||||||
for ; height < int64(1203); height++ {
|
for ; height < int64(1201); height++ {
|
||||||
ctx = ctx.WithBlockHeight(height)
|
ctx = ctx.WithBlockHeight(height)
|
||||||
keeper.handleValidatorSignature(ctx, val.Address(), newAmt, false)
|
keeper.handleValidatorSignature(ctx, val.Address(), newAmt, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// should not yet be jailed & kicked
|
// should now be jailed & kicked
|
||||||
|
stake.EndBlocker(ctx, sk)
|
||||||
|
validator, _ = sk.GetValidator(ctx, addr)
|
||||||
|
require.Equal(t, sdk.Unbonding, validator.Status)
|
||||||
|
|
||||||
|
signInfo, found := keeper.getValidatorSigningInfo(ctx, consAddr)
|
||||||
|
require.True(t, found)
|
||||||
|
require.Equal(t, int64(0), signInfo.MissedBlocksCounter)
|
||||||
|
require.Equal(t, int64(0), signInfo.IndexOffset)
|
||||||
|
// array should be cleared
|
||||||
|
for offset := int64(0); offset < keeper.SignedBlocksWindow(ctx); offset++ {
|
||||||
|
missed := keeper.getValidatorMissedBlockBitArray(ctx, consAddr, offset)
|
||||||
|
require.False(t, missed)
|
||||||
|
}
|
||||||
|
|
||||||
|
// some blocks pass
|
||||||
|
height = int64(5000)
|
||||||
|
ctx = ctx.WithBlockHeight(height)
|
||||||
|
|
||||||
|
// validator rejoins and starts signing again
|
||||||
|
sk.Unjail(ctx, consAddr)
|
||||||
|
keeper.handleValidatorSignature(ctx, val.Address(), newAmt, true)
|
||||||
|
|
||||||
|
// validator should not be kicked
|
||||||
stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
validator, _ = sk.GetValidator(ctx, addr)
|
validator, _ = sk.GetValidator(ctx, addr)
|
||||||
require.Equal(t, sdk.Bonded, validator.Status)
|
require.Equal(t, sdk.Bonded, validator.Status)
|
||||||
|
|
||||||
// validator signs 500 blocks
|
// validator misses 501 blocks
|
||||||
for ; height < int64(1702); height++ {
|
for height = int64(5001); height < int64(5503); height++ {
|
||||||
ctx = ctx.WithBlockHeight(height)
|
ctx = ctx.WithBlockHeight(height)
|
||||||
keeper.handleValidatorSignature(ctx, val.Address(), newAmt, true)
|
keeper.handleValidatorSignature(ctx, val.Address(), newAmt, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// should have exceeded threshold
|
// validator should now be jailed & kicked
|
||||||
signingInfo, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address()))
|
|
||||||
require.True(t, found)
|
|
||||||
require.Equal(t, int64(700), signingInfo.StartHeight)
|
|
||||||
require.Equal(t, int64(1102), signingInfo.IndexOffset)
|
|
||||||
require.Equal(t, int64(501), signingInfo.MissedBlocksCounter)
|
|
||||||
|
|
||||||
// should be jailed & kicked
|
|
||||||
stake.EndBlocker(ctx, sk)
|
stake.EndBlocker(ctx, sk)
|
||||||
validator, _ = sk.GetValidator(ctx, addr)
|
validator, _ = sk.GetValidator(ctx, addr)
|
||||||
require.Equal(t, sdk.Unbonding, validator.Status)
|
require.Equal(t, sdk.Unbonding, validator.Status)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue