github.com/bloxroute-labs/bor@v0.1.4/consensus/bor/validator.go (about) 1 package bor 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "errors" 7 "fmt" 8 "math/big" 9 "sort" 10 "strings" 11 12 "github.com/maticnetwork/bor/common" 13 ) 14 15 // Validator represets 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 ID uint64 `json:"ID"` 20 Address common.Address `json:"signer"` 21 VotingPower int64 `json:"power"` 22 ProposerPriority int64 `json:"accum"` 23 } 24 25 // NewValidator creates new validator 26 func NewValidator(address common.Address, votingPower int64) *Validator { 27 return &Validator{ 28 Address: address, 29 VotingPower: votingPower, 30 ProposerPriority: 0, 31 } 32 } 33 34 // Creates a new copy of the validator so we can mutate ProposerPriority. 35 // Panics if the validator is nil. 36 func (v *Validator) Copy() *Validator { 37 vCopy := *v 38 return &vCopy 39 } 40 41 // Returns the one with higher ProposerPriority. 42 func (v *Validator) CompareProposerPriority(other *Validator) *Validator { 43 if v == nil { 44 return other 45 } 46 if v.ProposerPriority > other.ProposerPriority { 47 return v 48 } else if v.ProposerPriority < other.ProposerPriority { 49 return other 50 } else { 51 result := bytes.Compare(v.Address.Bytes(), other.Address.Bytes()) 52 if result < 0 { 53 return v 54 } else if result > 0 { 55 return other 56 } else { 57 panic("Cannot compare identical validators") 58 return nil 59 } 60 } 61 } 62 63 func (v *Validator) String() string { 64 if v == nil { 65 return "nil-Validator" 66 } 67 return fmt.Sprintf("Validator{%v Power:%v Priority:%v}", 68 v.Address.Hex(), 69 v.VotingPower, 70 v.ProposerPriority) 71 } 72 73 // ValidatorListString returns a prettified validator list for logging purposes. 74 func ValidatorListString(vals []*Validator) string { 75 chunks := make([]string, len(vals)) 76 for i, val := range vals { 77 chunks[i] = fmt.Sprintf("%s:%d", val.Address, val.VotingPower) 78 } 79 80 return strings.Join(chunks, ",") 81 } 82 83 // Bytes computes the unique encoding of a validator with a given voting power. 84 // These are the bytes that gets hashed in consensus. It excludes address 85 // as its redundant with the pubkey. This also excludes ProposerPriority 86 // which changes every round. 87 func (v *Validator) Bytes() []byte { 88 b, err := json.Marshal(v) 89 if err != nil { 90 return b 91 } 92 return nil 93 } 94 95 // HeaderBytes return header bytes 96 func (v *Validator) HeaderBytes() []byte { 97 result := make([]byte, 40) 98 copy(result[:20], v.Address.Bytes()) 99 copy(result[20:], v.PowerBytes()) 100 return result 101 } 102 103 // PowerBytes return power bytes 104 func (v *Validator) PowerBytes() []byte { 105 powerBytes := big.NewInt(0).SetInt64(v.VotingPower).Bytes() 106 result := make([]byte, 20) 107 copy(result[20-len(powerBytes):], powerBytes) 108 return result 109 } 110 111 // MinimalVal returns block number of last validator update 112 func (v *Validator) MinimalVal() MinimalVal { 113 return MinimalVal{ 114 ID: v.ID, 115 VotingPower: uint64(v.VotingPower), 116 Signer: v.Address, 117 } 118 } 119 120 // ParseValidators returns validator set bytes 121 func ParseValidators(validatorsBytes []byte) ([]*Validator, error) { 122 if len(validatorsBytes)%40 != 0 { 123 return nil, errors.New("Invalid validators bytes") 124 } 125 126 result := make([]*Validator, len(validatorsBytes)/40) 127 for i := 0; i < len(validatorsBytes); i += 40 { 128 address := make([]byte, 20) 129 power := make([]byte, 20) 130 131 copy(address, validatorsBytes[i:i+20]) 132 copy(power, validatorsBytes[i+20:i+40]) 133 134 result[i/40] = NewValidator(common.BytesToAddress(address), big.NewInt(0).SetBytes(power).Int64()) 135 } 136 137 return result, nil 138 } 139 140 // --- 141 142 // MinimalVal is the minimal validator representation 143 // Used to send validator information to bor validator contract 144 type MinimalVal struct { 145 ID uint64 `json:"ID"` 146 VotingPower uint64 `json:"power"` // TODO add 10^-18 here so that we dont overflow easily 147 Signer common.Address `json:"signer"` 148 } 149 150 // SortMinimalValByAddress sorts validators 151 func SortMinimalValByAddress(a []MinimalVal) []MinimalVal { 152 sort.Slice(a, func(i, j int) bool { 153 return bytes.Compare(a[i].Signer.Bytes(), a[j].Signer.Bytes()) < 0 154 }) 155 return a 156 } 157 158 // ValidatorsToMinimalValidators converts array of validators to minimal validators 159 func ValidatorsToMinimalValidators(vals []Validator) (minVals []MinimalVal) { 160 for _, val := range vals { 161 minVals = append(minVals, val.MinimalVal()) 162 } 163 return 164 }