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