From a83535aef34443180c7769a3a2ed7ad04b0ef7ca Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Fri, 12 Oct 2018 21:09:23 +0200 Subject: [PATCH] Greater than to greater than or equal to --- docs/spec/slashing/begin-block.md | 2 +- x/slashing/keeper.go | 2 +- x/slashing/keeper_test.go | 85 +++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/docs/spec/slashing/begin-block.md b/docs/spec/slashing/begin-block.md index fb7d04e5dc..2d03fb6a7f 100644 --- a/docs/spec/slashing/begin-block.md +++ b/docs/spec/slashing/begin-block.md @@ -109,7 +109,7 @@ for val in block.Validators: // included in 50% of the recent LastCommits minHeight = signInfo.StartHeight + SIGNED_BLOCKS_WINDOW maxMissed = SIGNED_BLOCKS_WINDOW / 2 - if height > minHeight AND signInfo.MissedBlocksCounter > maxMissed: + if height >= minHeight AND signInfo.MissedBlocksCounter > maxMissed: signInfo.JailedUntil = block.Time + DOWNTIME_UNBOND_DURATION slash & unbond the validator diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 23e30fe1ec..1e0725ae8e 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -128,7 +128,7 @@ func (k Keeper) handleValidatorSignature(ctx sdk.Context, addr crypto.Address, p } minHeight := signInfo.StartHeight + k.SignedBlocksWindow(ctx) maxMissed := k.SignedBlocksWindow(ctx) - k.MinSignedPerWindow(ctx) - if height > minHeight && signInfo.MissedBlocksCounter > maxMissed { + if height >= minHeight && signInfo.MissedBlocksCounter > maxMissed { validator := k.validatorSet.ValidatorByConsAddr(ctx, consAddr) if validator != nil && !validator.GetJailed() { // Downtime confirmed: slash and jail the validator diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index 32469b6d30..9dcaae6e5b 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -364,3 +364,88 @@ func TestHandleAlreadyJailed(t *testing.T) { require.Equal(t, amtInt-1, validator.GetTokens().RoundInt64()) } + +// Test a validator dipping in and out of the validator set +// Ensure that missed blocks are tracked correctly +func TestValidatorDippingInAndOut(t *testing.T) { + + // initial setup + ctx, _, sk, _, keeper := createTestInput(t) + params := sk.GetParams(ctx) + params.MaxValidators = 1 + sk.SetParams(ctx, params) + amtInt := int64(100) + addr, val, amt := addrs[0], pks[0], sdk.NewInt(amtInt) + sh := stake.NewHandler(sk) + got := sh(ctx, newTestMsgCreateValidator(addr, val, amt)) + require.True(t, got.IsOK()) + validatorUpdates := stake.EndBlocker(ctx, sk) + keeper.AddValidators(ctx, validatorUpdates) + + // 100 first blocks OK + height := int64(0) + for ; height < int64(100); height++ { + ctx = ctx.WithBlockHeight(height) + keeper.handleValidatorSignature(ctx, val.Address(), amtInt, true) + } + + // validator kicked out of validator set + newAmt := int64(101) + got = sh(ctx, newTestMsgCreateValidator(addrs[1], pks[1], sdk.NewInt(newAmt))) + require.True(t, got.IsOK()) + validatorUpdates = stake.EndBlocker(ctx, sk) + require.Equal(t, 2, len(validatorUpdates)) + keeper.AddValidators(ctx, validatorUpdates) + validator, _ := sk.GetValidator(ctx, addr) + require.Equal(t, sdk.Unbonding, validator.Status) + + // 600 more blocks happened + height = int64(700) + ctx = ctx.WithBlockHeight(height) + + // validator added back in + got = sh(ctx, newTestMsgDelegate(sdk.AccAddress(addrs[2]), addrs[0], sdk.NewInt(2))) + require.True(t, got.IsOK()) + validatorUpdates = stake.EndBlocker(ctx, sk) + require.Equal(t, 2, len(validatorUpdates)) + validator, _ = sk.GetValidator(ctx, addr) + require.Equal(t, sdk.Bonded, validator.Status) + newAmt = int64(102) + + // validator misses a block + keeper.handleValidatorSignature(ctx, val.Address(), newAmt, false) + height++ + + // shouldn't be jailed/kicked yet + validator, _ = sk.GetValidator(ctx, addr) + require.Equal(t, sdk.Bonded, validator.Status) + + // validator misses 500 blocks + for ; height < int64(1202); height++ { + ctx = ctx.WithBlockHeight(height) + keeper.handleValidatorSignature(ctx, val.Address(), newAmt, false) + } + + // should not yet be jailed & kicked + stake.EndBlocker(ctx, sk) + validator, _ = sk.GetValidator(ctx, addr) + require.Equal(t, sdk.Bonded, validator.Status) + + // validator signs 500 blocks + for ; height < int64(1701); height++ { + ctx = ctx.WithBlockHeight(height) + keeper.handleValidatorSignature(ctx, val.Address(), newAmt, true) + } + + // should have exceeded threshold + signingInfo, found := keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) + require.True(t, found) + require.Equal(t, int64(700), signingInfo.StartHeight) + require.Equal(t, int64(1101), signingInfo.IndexOffset) + require.Equal(t, int64(501), signingInfo.MissedBlocksCounter) + + // should be jailed & kicked + stake.EndBlocker(ctx, sk) + validator, _ = sk.GetValidator(ctx, addr) + require.Equal(t, sdk.Unbonding, validator.Status) +}