cosmos-sdk/x/slashing/keeper.go

95 lines
3.5 KiB
Go
Raw Normal View History

2018-05-23 13:25:56 -07:00
package slashing
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/tendermint/tendermint/crypto"
2018-05-23 13:25:56 -07:00
)
// Keeper of the slashing store
type Keeper struct {
2018-06-01 15:27:37 -07:00
storeKey sdk.StoreKey
cdc *wire.Codec
validatorSet sdk.ValidatorSet
2018-05-23 13:25:56 -07:00
// codespace
codespace sdk.CodespaceType
}
// NewKeeper creates a slashing keeper
2018-06-01 15:27:37 -07:00
func NewKeeper(cdc *wire.Codec, key sdk.StoreKey, vs sdk.ValidatorSet, codespace sdk.CodespaceType) Keeper {
2018-05-23 13:25:56 -07:00
keeper := Keeper{
2018-06-01 15:27:37 -07:00
storeKey: key,
cdc: cdc,
validatorSet: vs,
codespace: codespace,
2018-05-23 13:25:56 -07:00
}
return keeper
}
// handle a validator signing two blocks at the same height
func (k Keeper) handleDoubleSign(ctx sdk.Context, height int64, timestamp int64, pubkey crypto.PubKey) {
logger := ctx.Logger().With("module", "x/slashing")
age := ctx.BlockHeader().Time - timestamp
2018-05-28 15:10:52 -07:00
// Double sign too old
2018-05-23 13:25:56 -07:00
if age > MaxEvidenceAge {
2018-05-25 15:13:29 -07:00
logger.Info(fmt.Sprintf("Ignored double sign from %s at height %d, age of %d past max age of %d", pubkey.Address(), height, age, MaxEvidenceAge))
2018-05-23 13:25:56 -07:00
return
}
2018-05-28 15:10:52 -07:00
// Double sign confirmed
2018-05-25 15:13:29 -07:00
logger.Info(fmt.Sprintf("Confirmed double sign from %s at height %d, age of %d less than max age of %d", pubkey.Address(), height, age, MaxEvidenceAge))
2018-06-01 15:27:37 -07:00
k.validatorSet.Slash(ctx, pubkey, height, SlashFractionDoubleSign)
2018-05-23 13:25:56 -07:00
}
// handle a validator signature, must be called once per validator per block
func (k Keeper) handleValidatorSignature(ctx sdk.Context, pubkey crypto.PubKey, signed bool) {
logger := ctx.Logger().With("module", "x/slashing")
height := ctx.BlockHeight()
if !signed {
2018-05-25 15:13:29 -07:00
logger.Info(fmt.Sprintf("Absent validator %s at height %d", pubkey.Address(), height))
2018-05-23 13:25:56 -07:00
}
address := pubkey.Address()
2018-05-28 15:10:52 -07:00
// Local index, so counts blocks validator *should* have signed
2018-06-10 18:03:52 -07:00
// Will use the 0-value default signing info if not present, except for start height
signInfo, found := k.getValidatorSigningInfo(ctx, address)
if !found {
// If this validator has never been seen before, construct a new SigningInfo with the correct start height
signInfo = NewValidatorSigningInfo(height, 0, 0, 0)
}
2018-05-25 17:05:46 -07:00
index := signInfo.IndexOffset % SignedBlocksWindow
signInfo.IndexOffset++
2018-05-28 15:10:52 -07:00
// Update signed block bit array & counter
2018-05-30 15:32:08 -07:00
// This counter just tracks the sum of the bit array
// That way we avoid needing to read/write the whole array each time
2018-05-23 13:25:56 -07:00
previous := k.getValidatorSigningBitArray(ctx, address, index)
2018-05-28 17:48:29 -07:00
if previous == signed {
2018-05-30 15:32:08 -07:00
// Array value at this index has not changed, no need to update counter
2018-05-28 17:48:29 -07:00
} else if previous && !signed {
2018-05-30 15:32:08 -07:00
// Array value has changed from signed to unsigned, decrement counter
2018-05-23 13:25:56 -07:00
k.setValidatorSigningBitArray(ctx, address, index, false)
signInfo.SignedBlocksCounter--
} else if !previous && signed {
2018-05-30 15:32:08 -07:00
// Array value has changed from unsigned to signed, increment counter
2018-05-23 13:25:56 -07:00
k.setValidatorSigningBitArray(ctx, address, index, true)
signInfo.SignedBlocksCounter++
}
2018-05-28 15:10:52 -07:00
2018-05-23 13:25:56 -07:00
minHeight := signInfo.StartHeight + SignedBlocksWindow
if height > minHeight && signInfo.SignedBlocksCounter < MinSignedPerWindow {
2018-05-28 15:10:52 -07:00
// Downtime confirmed, slash, revoke, and jail the validator
2018-05-25 15:13:29 -07:00
logger.Info(fmt.Sprintf("Validator %s past min height of %d and below signed blocks threshold of %d", pubkey.Address(), minHeight, MinSignedPerWindow))
2018-06-01 15:27:37 -07:00
k.validatorSet.Slash(ctx, pubkey, height, SlashFractionDowntime)
k.validatorSet.Revoke(ctx, pubkey)
2018-05-28 13:08:13 -07:00
signInfo.JailedUntil = ctx.BlockHeader().Time + DowntimeUnbondDuration
2018-05-23 13:25:56 -07:00
}
2018-05-28 17:35:42 -07:00
// Set the updated signing info
k.setValidatorSigningInfo(ctx, address, signInfo)
2018-05-23 13:25:56 -07:00
}