github.com/reapchain/go-reapchain@v0.2.15-0.20210609012950-9735c110c705/consensus/podc/validator/default.go (about)

     1  // Copyright 2017 AMIS Technologies
     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  	"math"
    21  	"reflect"
    22  	"sort"
    23  	"sync"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/consensus/podc"
    27  )
    28  
    29  type defaultValidator struct {
    30  	address common.Address
    31  	tag common.Tag
    32  	qrnd uint64
    33  }
    34  
    35  func (val *defaultValidator) Address() common.Address {
    36  	return val.address
    37  }
    38  
    39  func (val *defaultValidator) String() string {
    40  	return val.Address().String()
    41  }
    42  
    43  func (val *defaultValidator) Tag() common.Tag {
    44  	return val.tag
    45  }
    46  
    47  func (val *defaultValidator) SetAddress(a common.Address) {
    48  	val.address = a
    49  }
    50  
    51  func (val *defaultValidator) SetTag(t common.Tag) {
    52  	val.tag = t
    53  }
    54  
    55  func (val *defaultValidator) SetQrnd(q uint64) {
    56  	val.qrnd = q
    57  }
    58  
    59  func (val *defaultValidator) Qrnd() uint64 {
    60  	return val.qrnd
    61  }
    62  // ----------------------------------------------------------------------------
    63  
    64  type defaultSet struct {
    65  	validators  podc.Validators
    66  	proposer    podc.Validator  //Front node in paper ..
    67  	validatorMu sync.RWMutex
    68  
    69  	selector podc.ProposalSelector
    70  }
    71  
    72  func newDefaultSet(addrs []common.Address, selector podc.ProposalSelector) *defaultSet {
    73  	valSet := &defaultSet{}
    74  
    75  	// init validators
    76  	valSet.validators = make([]podc.Validator, len(addrs))
    77  	for i, addr := range addrs {
    78  		valSet.validators[i] = New(addr)
    79  	}
    80  	// sort validator
    81  	sort.Sort(valSet.validators)
    82  	// init proposer
    83  	if valSet.Size() > 0 {
    84  		valSet.proposer = valSet.GetByIndex(0)
    85  	}
    86  	//set proposal selector
    87  	valSet.selector = selector
    88  
    89  	return valSet
    90  }
    91  
    92  func (valSet *defaultSet) Size() int {
    93  	valSet.validatorMu.RLock()
    94  	defer valSet.validatorMu.RUnlock()
    95  	return len(valSet.validators)
    96  }
    97  
    98  func (valSet *defaultSet) List() []podc.Validator {
    99  	valSet.validatorMu.RLock()
   100  	defer valSet.validatorMu.RUnlock()
   101  	return valSet.validators
   102  }
   103  
   104  func (valSet *defaultSet) GetByIndex(i uint64) podc.Validator {
   105  	valSet.validatorMu.RLock()
   106  	defer valSet.validatorMu.RUnlock()
   107  	if i < uint64(valSet.Size()) {
   108  		return valSet.validators[i]
   109  	}
   110  	return nil
   111  }
   112  
   113  func (valSet *defaultSet) GetByAddress(addr common.Address) (int, podc.Validator) {
   114  	for i, val := range valSet.List() {
   115  		if addr == val.Address() {
   116  			return i, val
   117  		}
   118  	}
   119  	return -1, nil
   120  }
   121  
   122  func (valSet *defaultSet) GetProposer() podc.Validator {
   123  	return valSet.proposer
   124  }
   125  
   126  func (valSet *defaultSet) IsProposer(address common.Address) bool {
   127  	_, val := valSet.GetByAddress(address)
   128  	return reflect.DeepEqual(valSet.GetProposer(), val)  //
   129  }
   130  
   131  func (valSet *defaultSet) CalcProposer(lastProposer common.Address, round uint64 ) {
   132  	valSet.validatorMu.RLock()
   133  	defer valSet.validatorMu.RUnlock()
   134  	valSet.proposer = valSet.selector(valSet, lastProposer, round )
   135  }
   136  //func (valSet *defaultSet) CalcProposer(lastProposer common.Address, round uint64) {
   137  //	valSet.validatorMu.RLock()
   138  //	defer valSet.validatorMu.RUnlock()
   139  //	valSet.proposer = valSet.selector(valSet, lastProposer, round )
   140  //}
   141  func calcSeed(valSet podc.ValidatorSet, proposer common.Address, round uint64) uint64 {
   142  	offset := 0
   143  	if idx, val := valSet.GetByAddress(proposer); val != nil {
   144  		offset = idx
   145  	}
   146  	return uint64(offset) + round
   147  }
   148  
   149  func emptyAddress(addr common.Address) bool {
   150  	return addr == common.Address{}
   151  }
   152  
   153  func roundRobinProposer(valSet podc.ValidatorSet, proposer common.Address, round uint64 ) podc.Validator {
   154  	if valSet.Size() == 0 {
   155  		return nil
   156  	}
   157  	seed := uint64(0)
   158  	if emptyAddress(proposer) {
   159  		seed = round
   160  	} else {
   161  		seed = calcSeed(valSet, proposer, round) + 1
   162  	}
   163  	pick := seed % uint64(valSet.Size())
   164  	//if valSet.GetByIndex(pick).Address() == qman {
   165  	//	return valSet.GetByIndex(pick + 1)
   166  	//}
   167  	return valSet.GetByIndex(pick)
   168  }
   169  
   170  func stickyProposer(valSet podc.ValidatorSet, proposer common.Address, round uint64 ) podc.Validator {
   171  	if valSet.Size() == 0 {
   172  		return nil
   173  	}
   174  	seed := uint64(0)
   175  	if emptyAddress(proposer) {
   176  		seed = round
   177  	} else {
   178  		seed = calcSeed(valSet, proposer, round)
   179  	}
   180  	pick := seed % uint64(valSet.Size())
   181  	return valSet.GetByIndex(pick)
   182  }
   183  
   184  func qrfProposer(valSet podc.ValidatorSet, proposer common.Address, round uint64 ) podc.Validator {
   185  	if valSet.Size() == 0 {
   186  		return nil
   187  	}
   188  	seed := uint64(0)
   189  	if emptyAddress(proposer) {
   190  		seed = round
   191  	} else {
   192  		seed = calcSeed(valSet, proposer, round)
   193  	}
   194  	pick := seed % uint64(valSet.Size())
   195  	return valSet.GetByIndex(pick)
   196  }
   197  
   198  
   199  func (valSet *defaultSet) AddValidator(address common.Address) bool {
   200  	valSet.validatorMu.Lock()
   201  	defer valSet.validatorMu.Unlock()
   202  	for _, v := range valSet.validators {
   203  		if v.Address() == address {
   204  			return false
   205  		}
   206  	}
   207  	valSet.validators = append(valSet.validators, New(address))
   208  	// TODO: we may not need to re-sort it again
   209  	// sort validator
   210  	sort.Sort(valSet.validators)
   211  	return true
   212  }
   213  
   214  func (valSet *defaultSet) RemoveValidator(address common.Address) bool {
   215  	valSet.validatorMu.Lock()
   216  	defer valSet.validatorMu.Unlock()
   217  
   218  	for i, v := range valSet.validators {
   219  		if v.Address() == address {
   220  			valSet.validators = append(valSet.validators[:i], valSet.validators[i+1:]...)
   221  			return true
   222  		}
   223  	}
   224  	return false
   225  }
   226  
   227  func (valSet *defaultSet) Copy() podc.ValidatorSet {
   228  	valSet.validatorMu.Lock()
   229  	defer valSet.validatorMu.Unlock()
   230  
   231  	addresses := make([]common.Address, 0, len(valSet.validators))
   232  	for _, v := range valSet.validators {
   233  		addresses = append(addresses, v.Address())
   234  	}
   235  	return newDefaultSet(addresses, valSet.selector)
   236  }
   237  
   238  func (valSet *defaultSet) F() int { return int(math.Ceil(float64(valSet.Size())/3)) - 1 }