github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/validator/default.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package validator 18 19 import ( 20 "encoding/json" 21 "io" 22 "math" 23 "math/big" 24 "sync" 25 26 "github.com/ethereum/go-ethereum/common" 27 "github.com/ethereum/go-ethereum/consensus/istanbul" 28 blscrypto "github.com/ethereum/go-ethereum/crypto/bls" 29 "github.com/ethereum/go-ethereum/rlp" 30 ) 31 32 type defaultValidator struct { 33 address common.Address 34 blsPublicKey blscrypto.SerializedPublicKey 35 } 36 37 func newValidatorFromData(data *istanbul.ValidatorData) *defaultValidator { 38 return &defaultValidator{ 39 address: data.Address, 40 blsPublicKey: data.BLSPublicKey, 41 } 42 } 43 44 func (val *defaultValidator) AsData() *istanbul.ValidatorData { 45 return &istanbul.ValidatorData{ 46 Address: val.address, 47 BLSPublicKey: val.blsPublicKey, 48 } 49 } 50 51 func (val *defaultValidator) Address() common.Address { return val.address } 52 func (val *defaultValidator) BLSPublicKey() blscrypto.SerializedPublicKey { return val.blsPublicKey } 53 func (val *defaultValidator) String() string { return val.Address().String() } 54 55 func (val *defaultValidator) Serialize() ([]byte, error) { return rlp.EncodeToBytes(val) } 56 57 // JSON Encoding ----------------------------------------------------------------------- 58 59 func (val *defaultValidator) MarshalJSON() ([]byte, error) { return json.Marshal(val.AsData()) } 60 func (val *defaultValidator) UnmarshalJSON(b []byte) error { 61 var data istanbul.ValidatorData 62 if err := json.Unmarshal(b, &data); err != nil { 63 return err 64 } 65 *val = *newValidatorFromData(&data) 66 return nil 67 } 68 69 // RLP Encoding ----------------------------------------------------------------------- 70 71 func (val *defaultValidator) EncodeRLP(w io.Writer) error { return rlp.Encode(w, val.AsData()) } 72 func (val *defaultValidator) DecodeRLP(stream *rlp.Stream) error { 73 var v istanbul.ValidatorData 74 if err := stream.Decode(&v); err != nil { 75 return err 76 } 77 78 *val = *newValidatorFromData(&v) 79 return nil 80 } 81 82 // ---------------------------------------------------------------------------- 83 84 type defaultSet struct { 85 validators []istanbul.Validator 86 validatorMu sync.RWMutex 87 // This is set when we call `getOrderedValidators` 88 // TODO Rename to `EpochState` that has validators & randomness 89 randomness common.Hash 90 } 91 92 func newDefaultSet(validators []istanbul.ValidatorData) *defaultSet { 93 return &defaultSet{ 94 validators: mapDataToValidators(validators), 95 } 96 } 97 98 // We include the optimization described at https://arxiv.org/pdf/1901.07160.pdf as “PM-6” and 99 // discussed in Lemma 22. For values of N=3F for integer F=1,2,3,.. we can tolerate a quorum 100 // size one smaller than anticipated by Q = N - F. The intersection of any two sets of Q 101 // nodes of N=3F must contain an honest validator. 102 // 103 // For example, with N=9, F=2, Q=6. Any two sets of Q=6 from N=9 nodes must overlap 104 // by >9-6=3 nodes. At least 3-F=3-2=1 must be honest. 105 // 106 // 1 2 3 4 5 6 7 8 9 107 // x x x x x x 108 // y y y y y y 109 // F F H 110 // 111 // For N=10, F=3, Q=7. Any two sets of Q=7 nodes from N=10 must overlap by >4 nodes. 112 // At least 4-F=4-3=1 must be honest. 113 // 114 // 1 2 3 4 5 6 7 8 9 10 115 // x x x x x x x 116 // y y y y y y y 117 // F F F H 118 119 func (valSet *defaultSet) F() int { return int(math.Ceil(float64(valSet.Size())/3)) - 1 } 120 func (valSet *defaultSet) MinQuorumSize() int { return int(math.Ceil(float64(2*valSet.Size()) / 3)) } 121 122 func (valSet *defaultSet) SetRandomness(seed common.Hash) { valSet.randomness = seed } 123 func (valSet *defaultSet) GetRandomness() common.Hash { return valSet.randomness } 124 125 func (valSet *defaultSet) Size() int { 126 valSet.validatorMu.RLock() 127 defer valSet.validatorMu.RUnlock() 128 129 return len(valSet.validators) 130 } 131 132 func (valSet *defaultSet) List() []istanbul.Validator { 133 valSet.validatorMu.RLock() 134 defer valSet.validatorMu.RUnlock() 135 return valSet.validators 136 } 137 138 func (valSet *defaultSet) GetByIndex(i uint64) istanbul.Validator { 139 valSet.validatorMu.RLock() 140 defer valSet.validatorMu.RUnlock() 141 if i < uint64(valSet.Size()) { 142 return valSet.validators[i] 143 } 144 return nil 145 } 146 147 func (valSet *defaultSet) GetByAddress(addr common.Address) (int, istanbul.Validator) { 148 for i, val := range valSet.List() { 149 if addr == val.Address() { 150 return i, val 151 } 152 } 153 return -1, nil 154 } 155 156 func (valSet *defaultSet) ContainsByAddress(addr common.Address) bool { 157 i, _ := valSet.GetByAddress(addr) 158 return i != -1 159 } 160 161 func (valSet *defaultSet) GetIndex(addr common.Address) int { 162 i, _ := valSet.GetByAddress(addr) 163 return i 164 } 165 166 func (valSet *defaultSet) AddValidators(validators []istanbul.ValidatorData) bool { 167 newValidators := make([]istanbul.Validator, 0, len(validators)) 168 newAddressesMap := make(map[common.Address]bool) 169 for i := range validators { 170 newAddressesMap[validators[i].Address] = true 171 newValidators = append(newValidators, newValidatorFromData(&validators[i])) 172 } 173 174 valSet.validatorMu.Lock() 175 defer valSet.validatorMu.Unlock() 176 177 // Verify that the validators to add is not already in the valset 178 for _, v := range valSet.validators { 179 if _, ok := newAddressesMap[v.Address()]; ok { 180 return false 181 } 182 } 183 184 valSet.validators = append(valSet.validators, newValidators...) 185 186 return true 187 } 188 189 func (valSet *defaultSet) RemoveValidators(removedValidators *big.Int) bool { 190 if removedValidators.BitLen() == 0 { 191 return true 192 } 193 194 if removedValidators.BitLen() > len(valSet.validators) { 195 return false 196 } 197 198 valSet.validatorMu.Lock() 199 defer valSet.validatorMu.Unlock() 200 201 // Using this method to filter the validators list: https://github.com/golang/go/wiki/SliceTricks#filtering-without-allocating, so that no 202 // new memory will be allocated 203 tempList := valSet.validators[:0] 204 for i, v := range valSet.validators { 205 if removedValidators.Bit(i) == 0 { 206 tempList = append(tempList, v) 207 } 208 } 209 210 valSet.validators = tempList 211 return true 212 } 213 214 func (valSet *defaultSet) Copy() istanbul.ValidatorSet { 215 valSet.validatorMu.RLock() 216 defer valSet.validatorMu.RUnlock() 217 newValSet := NewSet(mapValidatorsToData(valSet.validators)) 218 newValSet.SetRandomness(valSet.randomness) 219 return newValSet 220 } 221 222 func (valSet *defaultSet) AsData() *istanbul.ValidatorSetData { 223 valSet.validatorMu.RLock() 224 defer valSet.validatorMu.RUnlock() 225 return &istanbul.ValidatorSetData{ 226 Validators: mapValidatorsToData(valSet.validators), 227 Randomness: valSet.randomness, 228 } 229 } 230 231 // JSON Encoding ----------------------------------------------------------------------- 232 233 func (val *defaultSet) MarshalJSON() ([]byte, error) { return json.Marshal(val.AsData()) } 234 235 func (val *defaultSet) UnmarshalJSON(b []byte) error { 236 var data istanbul.ValidatorSetData 237 if err := json.Unmarshal(b, &data); err != nil { 238 return err 239 } 240 *val = *newDefaultSet(data.Validators) 241 val.SetRandomness(data.Randomness) 242 return nil 243 } 244 245 // RLP Encoding ----------------------------------------------------------------------- 246 247 func (val *defaultSet) EncodeRLP(w io.Writer) error { return rlp.Encode(w, val.AsData()) } 248 249 func (val *defaultSet) DecodeRLP(stream *rlp.Stream) error { 250 var data istanbul.ValidatorSetData 251 if err := stream.Decode(&data); err != nil { 252 return err 253 } 254 *val = *newDefaultSet(data.Validators) 255 val.SetRandomness(data.Randomness) 256 return nil 257 } 258 259 func (val *defaultSet) Serialize() ([]byte, error) { return rlp.EncodeToBytes(val) } 260 261 // Utility Functions 262 263 func mapValidatorsToData(validators []istanbul.Validator) []istanbul.ValidatorData { 264 validatorsData := make([]istanbul.ValidatorData, len(validators)) 265 for i, v := range validators { 266 validatorsData[i] = *v.AsData() 267 } 268 return validatorsData 269 } 270 271 func mapDataToValidators(data []istanbul.ValidatorData) []istanbul.Validator { 272 validators := make([]istanbul.Validator, len(data)) 273 for i, v := range data { 274 validators[i] = newValidatorFromData(&v) 275 } 276 return validators 277 }