-
Notifications
You must be signed in to change notification settings - Fork 180
/
validator.go
158 lines (138 loc) · 3.82 KB
/
validator.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 types
import (
"bytes"
"errors"
"fmt"
"strings"
"github.com/okex/exchain/libs/tendermint/crypto"
ce "github.com/okex/exchain/libs/tendermint/crypto/encoding"
tmrand "github.com/okex/exchain/libs/tendermint/libs/rand"
tmproto "github.com/okex/exchain/libs/tendermint/proto/types"
)
// Volatile state for each Validator
// NOTE: The ProposerPriority is not included in Validator.Hash();
// make sure to update that method if changes are made here
type Validator struct {
Address Address `json:"address"`
PubKey crypto.PubKey `json:"pub_key"`
VotingPower int64 `json:"voting_power"`
ProposerPriority int64 `json:"proposer_priority"`
}
func NewValidator(pubKey crypto.PubKey, votingPower int64) *Validator {
return &Validator{
Address: pubKey.Address(),
PubKey: pubKey,
VotingPower: votingPower,
ProposerPriority: 0,
}
}
// Creates a new copy of the validator so we can mutate ProposerPriority.
// Panics if the validator is nil.
func (v *Validator) Copy() *Validator {
vCopy := *v
return &vCopy
}
// Returns the one with higher ProposerPriority.
func (v *Validator) CompareProposerPriority(other *Validator) *Validator {
if v == nil {
return other
}
switch {
case v.ProposerPriority > other.ProposerPriority:
return v
case v.ProposerPriority < other.ProposerPriority:
return other
default:
result := bytes.Compare(v.Address, other.Address)
switch {
case result < 0:
return v
case result > 0:
return other
default:
panic("Cannot compare identical validators")
}
}
}
func (v *Validator) String() string {
if v == nil {
return "nil-Validator"
}
return fmt.Sprintf("Validator{%v %v VP:%v A:%v}",
v.Address,
v.PubKey,
v.VotingPower,
v.ProposerPriority)
}
// ValidatorListString returns a prettified validator list for logging purposes.
func ValidatorListString(vals []*Validator) string {
chunks := make([]string, len(vals))
for i, val := range vals {
chunks[i] = fmt.Sprintf("%s:%d", val.Address, val.VotingPower)
}
return strings.Join(chunks, ",")
}
// Bytes computes the unique encoding of a validator with a given voting power.
// These are the bytes that gets hashed in consensus. It excludes address
// as its redundant with the pubkey. This also excludes ProposerPriority
// which changes every round.
func (v *Validator) Bytes() []byte {
return cdcEncode(struct {
PubKey crypto.PubKey
VotingPower int64
}{
v.PubKey,
v.VotingPower,
})
}
// ToProto converts Valiator to protobuf
func (v *Validator) ToProto() (*tmproto.Validator, error) {
if v == nil {
return nil, errors.New("nil validator")
}
pk, err := ce.PubKeyToProto(v.PubKey)
if err != nil {
return nil, err
}
vp := tmproto.Validator{
Address: v.Address,
PubKey: pk,
VotingPower: v.VotingPower,
ProposerPriority: v.ProposerPriority,
}
return &vp, nil
}
// FromProto sets a protobuf Validator to the given pointer.
// It returns an error if the public key is invalid.
func ValidatorFromProto(vp *tmproto.Validator) (*Validator, error) {
if vp == nil {
return nil, errors.New("nil validator")
}
pk, err := ce.PubKeyFromProto(&vp.PubKey)
if err != nil {
return nil, err
}
v := new(Validator)
v.Address = vp.GetAddress()
v.PubKey = pk
v.VotingPower = vp.GetVotingPower()
v.ProposerPriority = vp.GetProposerPriority()
return v, nil
}
//----------------------------------------
// RandValidator
// RandValidator returns a randomized validator, useful for testing.
// UNSTABLE
func RandValidator(randPower bool, minPower int64) (*Validator, PrivValidator) {
privVal := NewMockPV()
votePower := minPower
if randPower {
votePower += int64(tmrand.Uint32())
}
pubKey, err := privVal.GetPubKey()
if err != nil {
panic(fmt.Errorf("could not retrieve pubkey %w", err))
}
val := NewValidator(pubKey, votePower)
return val, privVal
}