github.com/adoriasoft/tendermint@v0.34.0-dev1.0.20200722151356-96d84601a75a/types/validator.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "strings" 8 9 "github.com/tendermint/tendermint/crypto" 10 ce "github.com/tendermint/tendermint/crypto/encoding" 11 tmrand "github.com/tendermint/tendermint/libs/rand" 12 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 13 ) 14 15 // Volatile state for each Validator 16 // NOTE: The ProposerPriority is not included in Validator.Hash(); 17 // make sure to update that method if changes are made here 18 type Validator struct { 19 Address Address `json:"address"` 20 PubKey crypto.PubKey `json:"pub_key"` 21 VotingPower int64 `json:"voting_power"` 22 23 ProposerPriority int64 `json:"proposer_priority"` 24 } 25 26 func NewValidator(pubKey crypto.PubKey, votingPower int64) *Validator { 27 return &Validator{ 28 Address: pubKey.Address(), 29 PubKey: pubKey, 30 VotingPower: votingPower, 31 ProposerPriority: 0, 32 } 33 } 34 35 func (v *Validator) ValidateBasic() error { 36 if v == nil { 37 return errors.New("nil validator") 38 } 39 if v.PubKey == nil { 40 return errors.New("validator does not have a public key") 41 } 42 43 if v.VotingPower < 0 { 44 return errors.New("validator has negative voting power") 45 } 46 47 if len(v.Address) != crypto.AddressSize { 48 return fmt.Errorf("validator address is the wrong size: %v", v.Address) 49 } 50 51 return nil 52 } 53 54 // Creates a new copy of the validator so we can mutate ProposerPriority. 55 // Panics if the validator is nil. 56 func (v *Validator) Copy() *Validator { 57 vCopy := *v 58 return &vCopy 59 } 60 61 // Returns the one with higher ProposerPriority. 62 func (v *Validator) CompareProposerPriority(other *Validator) *Validator { 63 if v == nil { 64 return other 65 } 66 switch { 67 case v.ProposerPriority > other.ProposerPriority: 68 return v 69 case v.ProposerPriority < other.ProposerPriority: 70 return other 71 default: 72 result := bytes.Compare(v.Address, other.Address) 73 switch { 74 case result < 0: 75 return v 76 case result > 0: 77 return other 78 default: 79 panic("Cannot compare identical validators") 80 } 81 } 82 } 83 84 func (v *Validator) String() string { 85 if v == nil { 86 return "nil-Validator" 87 } 88 return fmt.Sprintf("Validator{%v %v VP:%v A:%v}", 89 v.Address, 90 v.PubKey, 91 v.VotingPower, 92 v.ProposerPriority) 93 } 94 95 // ValidatorListString returns a prettified validator list for logging purposes. 96 func ValidatorListString(vals []*Validator) string { 97 chunks := make([]string, len(vals)) 98 for i, val := range vals { 99 chunks[i] = fmt.Sprintf("%s:%d", val.Address, val.VotingPower) 100 } 101 102 return strings.Join(chunks, ",") 103 } 104 105 // Bytes computes the unique encoding of a validator with a given voting power. 106 // These are the bytes that gets hashed in consensus. It excludes address 107 // as its redundant with the pubkey. This also excludes ProposerPriority 108 // which changes every round. 109 func (v *Validator) Bytes() []byte { 110 pk, err := ce.PubKeyToProto(v.PubKey) 111 if err != nil { 112 panic(err) 113 } 114 115 pbv := tmproto.SimpleValidator{ 116 PubKey: &pk, 117 VotingPower: v.VotingPower, 118 } 119 120 bz, err := pbv.Marshal() 121 if err != nil { 122 panic(err) 123 } 124 return bz 125 } 126 127 // ToProto converts Valiator to protobuf 128 func (v *Validator) ToProto() (*tmproto.Validator, error) { 129 if v == nil { 130 return nil, errors.New("nil validator") 131 } 132 133 pk, err := ce.PubKeyToProto(v.PubKey) 134 if err != nil { 135 return nil, err 136 } 137 138 vp := tmproto.Validator{ 139 Address: v.Address, 140 PubKey: pk, 141 VotingPower: v.VotingPower, 142 ProposerPriority: v.ProposerPriority, 143 } 144 145 return &vp, nil 146 } 147 148 // FromProto sets a protobuf Validator to the given pointer. 149 // It returns an error if the public key is invalid. 150 func ValidatorFromProto(vp *tmproto.Validator) (*Validator, error) { 151 if vp == nil { 152 return nil, errors.New("nil validator") 153 } 154 155 pk, err := ce.PubKeyFromProto(vp.PubKey) 156 if err != nil { 157 return nil, err 158 } 159 v := new(Validator) 160 v.Address = vp.GetAddress() 161 v.PubKey = pk 162 v.VotingPower = vp.GetVotingPower() 163 v.ProposerPriority = vp.GetProposerPriority() 164 165 return v, nil 166 } 167 168 //---------------------------------------- 169 // RandValidator 170 171 // RandValidator returns a randomized validator, useful for testing. 172 // UNSTABLE 173 func RandValidator(randPower bool, minPower int64) (*Validator, PrivValidator) { 174 privVal := NewMockPV() 175 votePower := minPower 176 if randPower { 177 votePower += int64(tmrand.Uint32()) 178 } 179 pubKey, err := privVal.GetPubKey() 180 if err != nil { 181 panic(fmt.Errorf("could not retrieve pubkey %w", err)) 182 } 183 val := NewValidator(pubKey, votePower) 184 return val, privVal 185 }