forked from cosmos/cosmos-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
validator_set.go
107 lines (91 loc) · 2.88 KB
/
validator_set.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
package assoc
import (
"bytes"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
)
// ValidatorSet defines
type ValidatorSet struct {
sdk.ValidatorSet
key sdk.KVStoreGetter
cdc *wire.Codec
maxAssoc int
addrLen int
}
var _ sdk.ValidatorSet = ValidatorSet{}
// NewValidatorSet returns new ValidatorSet with underlying ValidatorSet
func NewValidatorSet(cdc *wire.Codec, key sdk.KVStoreGetter, valset sdk.ValidatorSet, maxAssoc int, addrLen int) ValidatorSet {
if maxAssoc < 0 || addrLen < 0 {
panic("Cannot use negative integer for NewValidatorSet")
}
return ValidatorSet{
ValidatorSet: valset,
key: key,
cdc: cdc,
maxAssoc: maxAssoc,
addrLen: addrLen,
}
}
// Implements sdk.ValidatorSet
func (valset ValidatorSet) Validator(ctx sdk.Context, addr sdk.AccAddress) (res sdk.Validator) {
store := valset.key.KVStore(ctx)
base := store.Get(GetBaseKey(addr))
res = valset.ValidatorSet.Validator(ctx, base)
if res == nil {
res = valset.ValidatorSet.Validator(ctx, addr)
}
return
}
// GetBaseKey :: sdk.AccAddress -> sdk.AccAddress
func GetBaseKey(addr sdk.AccAddress) []byte {
return append([]byte{0x00}, addr...)
}
// GetAssocPrefix :: sdk.AccAddress -> (sdk.AccAddress -> byte)
func GetAssocPrefix(base sdk.AccAddress) []byte {
return append([]byte{0x01}, base...)
}
// GetAssocKey :: (sdk.AccAddress, sdk.AccAddress) -> byte
func GetAssocKey(base sdk.AccAddress, assoc sdk.AccAddress) []byte {
return append(append([]byte{0x01}, base...), assoc...)
}
// Associate associates new address with validator address
func (valset ValidatorSet) Associate(ctx sdk.Context, base sdk.AccAddress, assoc sdk.AccAddress) bool {
if len(base) != valset.addrLen || len(assoc) != valset.addrLen {
return false
}
store := valset.key.KVStore(ctx)
// If someone already owns the associated address
if store.Get(GetBaseKey(assoc)) != nil {
return false
}
store.Set(GetBaseKey(assoc), base)
store.Set(GetAssocKey(base, assoc), []byte{0x00})
return true
}
// Dissociate removes association between addresses
func (valset ValidatorSet) Dissociate(ctx sdk.Context, base sdk.AccAddress, assoc sdk.AccAddress) bool {
if len(base) != valset.addrLen || len(assoc) != valset.addrLen {
return false
}
store := valset.key.KVStore(ctx)
// No associated address found for given validator
if !bytes.Equal(store.Get(GetBaseKey(assoc)), base) {
return false
}
store.Delete(GetBaseKey(assoc))
store.Delete(GetAssocKey(base, assoc))
return true
}
// Associations returns all associated addresses with a validator
func (valset ValidatorSet) Associations(ctx sdk.Context, base sdk.AccAddress) (res []sdk.AccAddress) {
store := valset.key.KVStore(ctx)
res = make([]sdk.AccAddress, valset.maxAssoc)
iter := sdk.KVStorePrefixIterator(store, GetAssocPrefix(base))
i := 0
for ; iter.Valid(); iter.Next() {
key := iter.Key()
res[i] = key[len(key)-valset.addrLen:]
i++
}
return res[:i]
}