diff --git a/.pending/improvements/sdk/4629-Added-event-that-get b/.pending/improvements/sdk/4629-Added-event-that-get new file mode 100644 index 0000000000..ba115e55f7 --- /dev/null +++ b/.pending/improvements/sdk/4629-Added-event-that-get @@ -0,0 +1 @@ +#4629 Added warning event that gets emitted if validator misses a block. \ No newline at end of file diff --git a/docs/spec/slashing/04_begin_block.md b/docs/spec/slashing/04_begin_block.md index e54d9a210b..f7437ab281 100644 --- a/docs/spec/slashing/04_begin_block.md +++ b/docs/spec/slashing/04_begin_block.md @@ -84,7 +84,9 @@ single slashing period is capped as described in [overview.md](overview.md) unde ## Uptime tracking -At the beginning of each block, we update the signing info for each validator and check if they've dipped below the liveness threshold over the tracked window. If so, they will be slashed by `LivenessSlashAmount` and will be Jailed for `LivenessJailPeriod`. Liveness slashes do NOT lead to a tombstombing. +At the beginning of each block, we update the signing info for each validator and check if they've dipped below the liveness threshold over the tracked window. If so, they will be slashed by `LivenessSlashAmount` and will be Jailed for `LivenessJailPeriod`. Liveness slashes do NOT lead to a tombstombing. + +If a validator misses a block, a warning event will get emitted. ``` height := block.Height @@ -108,6 +110,18 @@ for val in block.Validators: signInfo.MissedBlocksCounter-- // else previous == val not in block.AbsentValidators, no change + // Emit warning events if Validator misses block + if val in block.AbsentValidators { + ctx.EventManager().EmitEvent( + NewEvent( + EventTypeLiveness, + NewAttribute(AttributeKeyAddress, consAddr), + NewAttribute(AttributeKeyMissedBlocks, signInfo.MissedBlocksCounter), + NewAttribute(AttributeKeyHeight, ctx.BlockHeight()) + ), + ) + } + // validator must be active for at least SIGNED_BLOCKS_WINDOW // before they can be automatically unbonded for failing to be // included in 50% of the recent LastCommits diff --git a/docs/spec/slashing/06_events.md b/docs/spec/slashing/06_events.md index a98e6529d1..7891ebfe5a 100644 --- a/docs/spec/slashing/06_events.md +++ b/docs/spec/slashing/06_events.md @@ -13,6 +13,12 @@ The slashing module emits the following events/tags: - [0] Only included if the validator is jailed. +| Type | Attribute Key | Attribute Value | +|----------|---------------|-----------------------------| +| liveness | address | {validatorConsensusAddress} | +| liveness | missed_blocks | {missedBlocksCounter} | +| liveness | height | {blockHeight} | + ## Handlers ### MsgUnjail diff --git a/types/context.go b/types/context.go index 32486d4842..364d56d3dd 100644 --- a/types/context.go +++ b/types/context.go @@ -311,4 +311,4 @@ func (pst *thePast) getOp(ver int64) (Op, bool) { return Op{}, false } return pst.ops[ver-1], true -} \ No newline at end of file +} diff --git a/x/slashing/keeper.go b/x/slashing/keeper.go index 91234d495b..cd0bad0038 100644 --- a/x/slashing/keeper.go +++ b/x/slashing/keeper.go @@ -184,6 +184,15 @@ func (k Keeper) HandleValidatorSignature(ctx sdk.Context, addr crypto.Address, p } if missed { + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.EventTypeLiveness, + sdk.NewAttribute(types.AttributeKeyAddress, consAddr.String()), + sdk.NewAttribute(types.AttributeKeyMissedBlocks, fmt.Sprintf("%d", signInfo.MissedBlocksCounter)), + sdk.NewAttribute(types.AttributeKeyHeight, fmt.Sprintf("%d", height)), + ), + ) + logger.Info(fmt.Sprintf("Absent validator %s (%v) at height %d, %d missed, threshold %d", addr, pubkey, height, signInfo.MissedBlocksCounter, k.MinSignedPerWindow(ctx))) } diff --git a/x/slashing/types/events.go b/x/slashing/types/events.go index 08e2daaa70..2ba4020bd3 100644 --- a/x/slashing/types/events.go +++ b/x/slashing/types/events.go @@ -2,12 +2,15 @@ package types // Slashing module event types var ( - EventTypeSlash = "slash" + EventTypeSlash = "slash" + EventTypeLiveness = "liveness" - AttributeKeyAddress = "address" - AttributeKeyPower = "power" - AttributeKeyReason = "reason" - AttributeKeyJailed = "jailed" + AttributeKeyAddress = "address" + AttributeKeyHeight = "height" + AttributeKeyPower = "power" + AttributeKeyReason = "reason" + AttributeKeyJailed = "jailed" + AttributeKeyMissedBlocks = "missed_blocks" AttributeValueDoubleSign = "double_sign" AttributeValueMissingSignature = "missing_signature"