From 83f7a4cb7b56c845eb355f521d4d72a0ecfbdf2d Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Mon, 15 Oct 2018 23:01:29 +0200 Subject: [PATCH] Bugfix; update slashing spec --- docs/spec/slashing/begin-block.md | 10 ++++++---- docs/spec/slashing/hooks.md | 11 +++++++++++ docs/spec/slashing/state.md | 8 ++++---- docs/spec/slashing/transactions.md | 4 ---- x/slashing/handler.go | 6 +----- x/slashing/hooks.go | 2 +- x/slashing/keeper_test.go | 4 ++-- 7 files changed, 25 insertions(+), 20 deletions(-) diff --git a/docs/spec/slashing/begin-block.md b/docs/spec/slashing/begin-block.md index fb7d04e5dc..43691b38d2 100644 --- a/docs/spec/slashing/begin-block.md +++ b/docs/spec/slashing/begin-block.md @@ -93,14 +93,14 @@ for val in block.Validators: index := signInfo.IndexOffset % SIGNED_BLOCKS_WINDOW signInfo.IndexOffset++ - previous = SigningBitArray.Get(val.Address, index) + previous = MissedBlockBitArray.Get(val.Address, index) // update counter if array has changed if !previous and val in block.AbsentValidators: - SigningBitArray.Set(val.Address, index, true) + MissedBlockBitArray.Set(val.Address, index, true) signInfo.MissedBlocksCounter++ else if previous and val not in block.AbsentValidators: - SigningBitArray.Set(val.Address, index, false) + MissedBlockBitArray.Set(val.Address, index, false) signInfo.MissedBlocksCounter-- // else previous == val not in block.AbsentValidators, no change @@ -111,7 +111,9 @@ for val in block.Validators: maxMissed = SIGNED_BLOCKS_WINDOW / 2 if height > minHeight AND signInfo.MissedBlocksCounter > maxMissed: signInfo.JailedUntil = block.Time + DOWNTIME_UNBOND_DURATION - + signInfo.IndexOffset = 0 + signInfo.MissedBlocksCounter = 0 + clearMissedBlockBitArray() slash & unbond the validator SigningInfo.Set(val.Address, signInfo) diff --git a/docs/spec/slashing/hooks.md b/docs/spec/slashing/hooks.md index 36dde61f94..1888c1d2f8 100644 --- a/docs/spec/slashing/hooks.md +++ b/docs/spec/slashing/hooks.md @@ -12,6 +12,17 @@ and `SlashedSoFar` of `0`: ``` onValidatorBonded(address sdk.ValAddress) + signingInfo, found = getValidatorSigningInfo(address) + if !found { + signingInfo = ValidatorSigningInfo { + StartHeight : CurrentHeight, + IndexOffset : 0, + JailedUntil : time.Unix(0, 0), + MissedBloskCounter : 0 + } + setValidatorSigningInfo(signingInfo) + } + slashingPeriod = SlashingPeriod{ ValidatorAddr : address, StartHeight : CurrentHeight, diff --git a/docs/spec/slashing/state.md b/docs/spec/slashing/state.md index fe6f39f5c6..9a9a188ff2 100644 --- a/docs/spec/slashing/state.md +++ b/docs/spec/slashing/state.md @@ -17,18 +17,18 @@ Information about validator activity is tracked in a `ValidatorSigningInfo`. It is indexed in the store as follows: - SigningInfo: ` 0x01 | ValTendermintAddr -> amino(valSigningInfo)` -- SigningBitArray: ` 0x02 | ValTendermintAddr | LittleEndianUint64(signArrayIndex) -> VarInt(didSign)` +- MissedBlocksBitArray: ` 0x02 | ValTendermintAddr | LittleEndianUint64(signArrayIndex) -> VarInt(didMiss)` The first map allows us to easily lookup the recent signing info for a validator, according to the Tendermint validator address. The second map acts as -a bit-array of size `SIGNED_BLOCKS_WINDOW` that tells us if the validator signed for a given index in the bit-array. +a bit-array of size `SIGNED_BLOCKS_WINDOW` that tells us if the validator missed the block for a given index in the bit-array. The index in the bit-array is given as little endian uint64. The result is a `varint` that takes on `0` or `1`, where `0` indicates the -validator did not sign the corresponding block, and `1` indicates they did. +validator did not miss (did sign) the corresponding block, and `1` indicates they missed the block (did not sign). -Note that the SigningBitArray is not explicitly initialized up-front. Keys are +Note that the MissedBlocksBitArray is not explicitly initialized up-front. Keys are added as we progress through the first `SIGNED_BLOCKS_WINDOW` blocks for a newly bonded validator. diff --git a/docs/spec/slashing/transactions.md b/docs/spec/slashing/transactions.md index be33ee0965..c33e96047d 100644 --- a/docs/spec/slashing/transactions.md +++ b/docs/spec/slashing/transactions.md @@ -25,10 +25,6 @@ handleMsgUnjail(tx TxUnjail) if block time < info.JailedUntil fail with "Validator still jailed, cannot unjail until period has expired" - // Update the start height so the validator won't be immediately unbonded again - info.StartHeight = BlockHeight - setValidatorSigningInfo(info) - validator.Jailed = false setValidator(validator) diff --git a/x/slashing/handler.go b/x/slashing/handler.go index 740166d2af..701577080e 100644 --- a/x/slashing/handler.go +++ b/x/slashing/handler.go @@ -46,11 +46,7 @@ func handleMsgUnjail(ctx sdk.Context, msg MsgUnjail, k Keeper) sdk.Result { return ErrValidatorJailed(k.codespace).Result() } - // update the starting height so the validator can't be immediately jailed - // again - info.StartHeight = ctx.BlockHeight() - k.setValidatorSigningInfo(ctx, consAddr, info) - + // unjail the validator k.validatorSet.Unjail(ctx, consAddr) tags := sdk.NewTags("action", []byte("unjail"), "validator", []byte(msg.ValidatorAddr.String())) diff --git a/x/slashing/hooks.go b/x/slashing/hooks.go index 3710e4072d..6695369284 100644 --- a/x/slashing/hooks.go +++ b/x/slashing/hooks.go @@ -16,8 +16,8 @@ func (k Keeper) onValidatorBonded(ctx sdk.Context, address sdk.ConsAddress) { JailedUntil: time.Unix(0, 0), MissedBlocksCounter: 0, } + k.setValidatorSigningInfo(ctx, address, signingInfo) } - k.setValidatorSigningInfo(ctx, address, signingInfo) // Create a new slashing period when a validator is bonded slashingPeriod := ValidatorSlashingPeriod{ diff --git a/x/slashing/keeper_test.go b/x/slashing/keeper_test.go index d1cc44408b..0af3936b2a 100644 --- a/x/slashing/keeper_test.go +++ b/x/slashing/keeper_test.go @@ -245,10 +245,10 @@ func TestHandleAbsentValidator(t *testing.T) { pool = sk.GetPool(ctx) require.Equal(t, amtInt-slashAmt-secondSlashAmt, pool.BondedTokens.RoundInt64()) - // validator start height should have been changed + // validator start height should not have been changed info, found = keeper.getValidatorSigningInfo(ctx, sdk.ConsAddress(val.Address())) require.True(t, found) - require.Equal(t, height, info.StartHeight) + require.Equal(t, int64(0), info.StartHeight) // we've missed 2 blocks more than the maximum, so the counter was reset to 0 at 1 block more and is now 1 require.Equal(t, int64(1), info.MissedBlocksCounter)