-
Notifications
You must be signed in to change notification settings - Fork 3.6k
/
signing_info.go
158 lines (134 loc) · 5.33 KB
/
signing_info.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package keeper
import (
"time"
gogotypes "github.com/gogo/protobuf/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/slashing/types"
)
// GetValidatorSigningInfo retruns the ValidatorSigningInfo for a specific validator
// ConsAddress
func (k Keeper) GetValidatorSigningInfo(ctx sdk.Context, address sdk.ConsAddress) (info types.ValidatorSigningInfo, found bool) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.ValidatorSigningInfoKey(address))
if bz == nil {
found = false
return
}
k.cdc.MustUnmarshalBinaryBare(bz, &info)
found = true
return
}
// 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
}
// 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)
bz := k.cdc.MustMarshalBinaryBare(&info)
store.Set(types.ValidatorSigningInfoKey(address), bz)
}
// IterateValidatorSigningInfos iterates over the stored ValidatorSigningInfo
func (k Keeper) IterateValidatorSigningInfos(ctx sdk.Context,
handler func(address sdk.ConsAddress, info types.ValidatorSigningInfo) (stop bool)) {
store := ctx.KVStore(k.storeKey)
iter := sdk.KVStorePrefixIterator(store, types.ValidatorSigningInfoKeyPrefix)
defer iter.Close()
for ; iter.Valid(); iter.Next() {
address := types.ValidatorSigningInfoAddress(iter.Key())
var info types.ValidatorSigningInfo
k.cdc.MustUnmarshalBinaryBare(iter.Value(), &info)
if handler(address, info) {
break
}
}
}
// GetValidatorMissedBlockBitArray gets the bit for the missed blocks array
func (k Keeper) GetValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.ConsAddress, index int64) bool {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.ValidatorMissedBlockBitArrayKey(address, index))
var missed gogotypes.BoolValue
if bz == nil {
// lazy: treat empty key as not missed
return false
}
k.cdc.MustUnmarshalBinaryBare(bz, &missed)
return missed.Value
}
// IterateValidatorMissedBlockBitArray iterates over the signed blocks window
// and performs a callback function
func (k Keeper) IterateValidatorMissedBlockBitArray(ctx sdk.Context,
address sdk.ConsAddress, handler func(index int64, missed bool) (stop bool)) {
store := ctx.KVStore(k.storeKey)
index := int64(0)
// Array may be sparse
for ; index < k.SignedBlocksWindow(ctx); index++ {
var missed gogotypes.BoolValue
bz := store.Get(types.ValidatorMissedBlockBitArrayKey(address, index))
if bz == nil {
continue
}
k.cdc.MustUnmarshalBinaryBare(bz, &missed)
if handler(index, missed.Value) {
break
}
}
}
// GetValidatorMissedBlocks returns array of missed blocks for given validator Cons address
func (k Keeper) GetValidatorMissedBlocks(ctx sdk.Context, address sdk.ConsAddress) []types.MissedBlock {
missedBlocks := []types.MissedBlock{}
k.IterateValidatorMissedBlockBitArray(ctx, address, func(index int64, missed bool) (stop bool) {
missedBlocks = append(missedBlocks, types.NewMissedBlock(index, missed))
return false
})
return missedBlocks
}
// 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
}
// 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) {
store := ctx.KVStore(k.storeKey)
bz := k.cdc.MustMarshalBinaryBare(&gogotypes.BoolValue{Value: missed})
store.Set(types.ValidatorMissedBlockBitArrayKey(address, index), bz)
}
// clearValidatorMissedBlockBitArray deletes every instance of ValidatorMissedBlockBitArray in the store
func (k Keeper) clearValidatorMissedBlockBitArray(ctx sdk.Context, address sdk.ConsAddress) {
store := ctx.KVStore(k.storeKey)
iter := sdk.KVStorePrefixIterator(store, types.ValidatorMissedBlockBitArrayPrefixKey(address))
defer iter.Close()
for ; iter.Valid(); iter.Next() {
store.Delete(iter.Key())
}
}