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  }