2019-07-19 06:43:38 -07:00
|
|
|
package keeper
|
2018-05-28 14:24:58 -07:00
|
|
|
|
|
|
|
import (
|
2019-12-02 17:58:14 -08:00
|
|
|
"time"
|
|
|
|
|
2020-02-19 16:04:13 -08:00
|
|
|
gogotypes "github.com/gogo/protobuf/types"
|
|
|
|
|
2018-05-28 14:24:58 -07:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2020-02-19 16:04:13 -08:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/slashing/types"
|
2018-05-28 14:24:58 -07:00
|
|
|
)
|
|
|
|
|
2019-07-22 08:26:42 -07:00
|
|
|
// GetValidatorSigningInfo retruns the ValidatorSigningInfo for a specific validator
|
2019-07-19 06:43:38 -07:00
|
|
|
// ConsAddress
|
|
|
|
func (k Keeper) GetValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress) (info types.ValidatorSigningInfo, found bool) {
|
2018-05-28 14:24:58 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2020-05-13 14:23:00 -07:00
|
|
|
bz := store.Get(types.ValidatorSigningInfoKey(address))
|
2018-05-28 14:24:58 -07:00
|
|
|
if bz == nil {
|
|
|
|
found = false
|
2018-05-30 16:37:38 -07:00
|
|
|
return
|
2018-05-28 14:24:58 -07:00
|
|
|
}
|
2020-03-13 12:58:43 -07:00
|
|
|
k.cdc.MustUnmarshalBinaryBare(bz, &info)
|
2018-05-30 16:37:38 -07:00
|
|
|
found = true
|
2018-05-28 14:24:58 -07:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-12-02 17:58:14 -08:00
|
|
|
// HasValidatorSigningInfo returns if a given validator has signing information
|
|
|
|
// persited.
|
|
|
|
func (k Keeper) HasValidatorSigningInfo(ctx sdk.Context, consAddr sdk.ConsAddress) bool {
|
|
|
|
_, ok := k.GetValidatorSigningInfo(ctx, consAddr)
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2019-07-19 06:43:38 -07:00
|
|
|
// SetValidatorSigningInfo sets the validator signing info to a consensus address key
|
|
|
|
func (k Keeper) SetValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress, info types.ValidatorSigningInfo) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
2020-03-13 12:58:43 -07:00
|
|
|
bz := k.cdc.MustMarshalBinaryBare(&info)
|
2020-05-13 14:23:00 -07:00
|
|
|
store.Set(types.ValidatorSigningInfoKey(address), bz)
|
2019-07-19 06:43:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// IterateValidatorSigningInfos iterates over the stored ValidatorSigningInfo
|
2019-06-05 16:26:17 -07:00
|
|
|
func (k Keeper) IterateValidatorSigningInfos(ctx sdk.Context,
|
|
|
|
handler func(address sdk.ConsAddress, info types.ValidatorSigningInfo) (stop bool)) {
|
|
|
|
|
2018-11-08 16:28:28 -08:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2020-05-13 14:23:00 -07:00
|
|
|
iter := sdk.KVStorePrefixIterator(store, types.ValidatorSigningInfoKeyPrefix)
|
2018-11-11 19:09:12 -08:00
|
|
|
defer iter.Close()
|
2018-11-08 16:28:28 -08:00
|
|
|
for ; iter.Valid(); iter.Next() {
|
2020-05-13 14:23:00 -07:00
|
|
|
address := types.ValidatorSigningInfoAddress(iter.Key())
|
2019-06-05 16:26:17 -07:00
|
|
|
var info types.ValidatorSigningInfo
|
2020-03-13 12:58:43 -07:00
|
|
|
k.cdc.MustUnmarshalBinaryBare(iter.Value(), &info)
|
2018-11-08 16:28:28 -08:00
|
|
|
if handler(address, info) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-19 06:43:38 -07:00
|
|
|
// GetValidatorMissedBlockBitArray gets the bit for the missed blocks array
|
2020-02-19 16:04:13 -08:00
|
|
|
func (k Keeper) GetValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64) bool {
|
2018-05-28 14:24:58 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2020-05-13 14:23:00 -07:00
|
|
|
bz := store.Get(types.ValidatorMissedBlockBitArrayKey(address, index))
|
2020-02-19 16:04:13 -08:00
|
|
|
var missed gogotypes.BoolValue
|
2018-05-28 14:24:58 -07:00
|
|
|
if bz == nil {
|
2018-10-15 12:20:37 -07:00
|
|
|
// lazy: treat empty key as not missed
|
2020-02-19 16:04:13 -08:00
|
|
|
return false
|
2018-05-28 14:24:58 -07:00
|
|
|
}
|
2020-03-13 12:58:43 -07:00
|
|
|
k.cdc.MustUnmarshalBinaryBare(bz, &missed)
|
2020-02-19 16:04:13 -08:00
|
|
|
|
|
|
|
return missed.Value
|
2018-05-28 14:24:58 -07:00
|
|
|
}
|
|
|
|
|
2019-07-19 06:43:38 -07:00
|
|
|
// IterateValidatorMissedBlockBitArray iterates over the signed blocks window
|
|
|
|
// and performs a callback function
|
2019-06-05 16:26:17 -07:00
|
|
|
func (k Keeper) IterateValidatorMissedBlockBitArray(ctx sdk.Context,
|
|
|
|
address sdk.ConsAddress, handler func(index int64, missed bool) (stop bool)) {
|
|
|
|
|
2018-11-08 16:28:28 -08:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
|
|
|
index := int64(0)
|
|
|
|
// Array may be sparse
|
|
|
|
for ; index < k.SignedBlocksWindow(ctx); index++ {
|
2020-02-19 16:04:13 -08:00
|
|
|
var missed gogotypes.BoolValue
|
2020-05-13 14:23:00 -07:00
|
|
|
bz := store.Get(types.ValidatorMissedBlockBitArrayKey(address, index))
|
2018-11-08 16:28:28 -08:00
|
|
|
if bz == nil {
|
|
|
|
continue
|
|
|
|
}
|
2020-02-19 16:04:13 -08:00
|
|
|
|
2020-03-13 12:58:43 -07:00
|
|
|
k.cdc.MustUnmarshalBinaryBare(bz, &missed)
|
2020-02-19 16:04:13 -08:00
|
|
|
if handler(index, missed.Value) {
|
2018-11-08 16:28:28 -08:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-02 17:58:14 -08:00
|
|
|
// JailUntil attempts to set a validator's JailedUntil attribute in its signing
|
|
|
|
// info. It will panic if the signing info does not exist for the validator.
|
|
|
|
func (k Keeper) JailUntil(ctx sdk.Context, consAddr sdk.ConsAddress, jailTime time.Time) {
|
|
|
|
signInfo, ok := k.GetValidatorSigningInfo(ctx, consAddr)
|
|
|
|
if !ok {
|
|
|
|
panic("cannot jail validator that does not have any signing information")
|
|
|
|
}
|
|
|
|
|
|
|
|
signInfo.JailedUntil = jailTime
|
|
|
|
k.SetValidatorSigningInfo(ctx, consAddr, signInfo)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tombstone attempts to tombstone a validator. It will panic if signing info for
|
|
|
|
// the given validator does not exist.
|
|
|
|
func (k Keeper) Tombstone(ctx sdk.Context, consAddr sdk.ConsAddress) {
|
|
|
|
signInfo, ok := k.GetValidatorSigningInfo(ctx, consAddr)
|
|
|
|
if !ok {
|
|
|
|
panic("cannot tombstone validator that does not have any signing information")
|
|
|
|
}
|
|
|
|
|
|
|
|
if signInfo.Tombstoned {
|
|
|
|
panic("cannot tombstone validator that is already tombstoned")
|
|
|
|
}
|
|
|
|
|
|
|
|
signInfo.Tombstoned = true
|
|
|
|
k.SetValidatorSigningInfo(ctx, consAddr, signInfo)
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsTombstoned returns if a given validator by consensus address is tombstoned.
|
|
|
|
func (k Keeper) IsTombstoned(ctx sdk.Context, consAddr sdk.ConsAddress) bool {
|
|
|
|
signInfo, ok := k.GetValidatorSigningInfo(ctx, consAddr)
|
|
|
|
if !ok {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return signInfo.Tombstoned
|
|
|
|
}
|
|
|
|
|
2019-07-19 06:43:38 -07:00
|
|
|
// SetValidatorMissedBlockBitArray sets the bit that checks if the validator has
|
|
|
|
// missed a block in the current window
|
|
|
|
func (k Keeper) SetValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64, missed bool) {
|
2018-05-28 14:24:58 -07:00
|
|
|
store := ctx.KVStore(k.storeKey)
|
2020-03-13 12:58:43 -07:00
|
|
|
bz := k.cdc.MustMarshalBinaryBare(&gogotypes.BoolValue{Value: missed})
|
2020-05-13 14:23:00 -07:00
|
|
|
store.Set(types.ValidatorMissedBlockBitArrayKey(address, index), bz)
|
2018-10-15 12:20:37 -07:00
|
|
|
}
|
|
|
|
|
2019-07-19 06:43:38 -07:00
|
|
|
// clearValidatorMissedBlockBitArray deletes every instance of ValidatorMissedBlockBitArray in the store
|
2018-10-15 12:20:37 -07:00
|
|
|
func (k Keeper) clearValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.ConsAddress) {
|
|
|
|
store := ctx.KVStore(k.storeKey)
|
2020-05-13 14:23:00 -07:00
|
|
|
iter := sdk.KVStorePrefixIterator(store, types.ValidatorMissedBlockBitArrayPrefixKey(address))
|
2018-11-11 19:09:12 -08:00
|
|
|
defer iter.Close()
|
2018-10-15 12:20:37 -07:00
|
|
|
for ; iter.Valid(); iter.Next() {
|
|
|
|
store.Delete(iter.Key())
|
|
|
|
}
|
2018-05-28 14:24:58 -07:00
|
|
|
}
|