default.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  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. package validator
  17. import (
  18. "math"
  19. "reflect"
  20. "sync"
  21. "github.com/ethereum/go-ethereum/common"
  22. "github.com/ethereum/go-ethereum/consensus/istanbul"
  23. )
  24. type defaultValidator struct {
  25. address common.Address
  26. }
  27. func (val *defaultValidator) Address() common.Address {
  28. return val.address
  29. }
  30. func (val *defaultValidator) String() string {
  31. return val.Address().String()
  32. }
  33. // ----------------------------------------------------------------------------
  34. type defaultSet struct {
  35. validators istanbul.Validators
  36. policy *istanbul.ProposerPolicy
  37. proposer istanbul.Validator
  38. validatorMu sync.RWMutex
  39. selector istanbul.ProposalSelector
  40. }
  41. func newDefaultSet(addrs []common.Address, policy *istanbul.ProposerPolicy) *defaultSet {
  42. valSet := &defaultSet{}
  43. valSet.policy = policy
  44. // init validators
  45. valSet.validators = make([]istanbul.Validator, len(addrs))
  46. for i, addr := range addrs {
  47. valSet.validators[i] = New(addr)
  48. }
  49. valSet.SortValidators()
  50. // init proposer
  51. if valSet.Size() > 0 {
  52. valSet.proposer = valSet.GetByIndex(0)
  53. }
  54. valSet.selector = roundRobinProposer
  55. if policy.Id == istanbul.Sticky {
  56. valSet.selector = stickyProposer
  57. }
  58. policy.RegisterValidatorSet(valSet)
  59. return valSet
  60. }
  61. func (valSet *defaultSet) Size() int {
  62. valSet.validatorMu.RLock()
  63. defer valSet.validatorMu.RUnlock()
  64. return len(valSet.validators)
  65. }
  66. func (valSet *defaultSet) List() []istanbul.Validator {
  67. valSet.validatorMu.RLock()
  68. defer valSet.validatorMu.RUnlock()
  69. return valSet.validators
  70. }
  71. func (valSet *defaultSet) GetByIndex(i uint64) istanbul.Validator {
  72. valSet.validatorMu.RLock()
  73. defer valSet.validatorMu.RUnlock()
  74. if i < uint64(valSet.Size()) {
  75. return valSet.validators[i]
  76. }
  77. return nil
  78. }
  79. func (valSet *defaultSet) GetByAddress(addr common.Address) (int, istanbul.Validator) {
  80. for i, val := range valSet.List() {
  81. if addr == val.Address() {
  82. return i, val
  83. }
  84. }
  85. return -1, nil
  86. }
  87. func (valSet *defaultSet) GetProposer() istanbul.Validator {
  88. return valSet.proposer
  89. }
  90. func (valSet *defaultSet) IsProposer(address common.Address) bool {
  91. _, val := valSet.GetByAddress(address)
  92. return reflect.DeepEqual(valSet.GetProposer(), val)
  93. }
  94. func (valSet *defaultSet) CalcProposer(lastProposer common.Address, round uint64) {
  95. valSet.validatorMu.RLock()
  96. defer valSet.validatorMu.RUnlock()
  97. valSet.proposer = valSet.selector(valSet, lastProposer, round)
  98. }
  99. // ValidatorSetSorter sorts the validators based on the configured By function
  100. func (valSet *defaultSet) SortValidators() {
  101. valSet.Policy().By.Sort(valSet.validators)
  102. }
  103. func calcSeed(valSet istanbul.ValidatorSet, proposer common.Address, round uint64) uint64 {
  104. offset := 0
  105. if idx, val := valSet.GetByAddress(proposer); val != nil {
  106. offset = idx
  107. }
  108. return uint64(offset) + round
  109. }
  110. func emptyAddress(addr common.Address) bool {
  111. return addr == common.Address{}
  112. }
  113. func roundRobinProposer(valSet istanbul.ValidatorSet, proposer common.Address, round uint64) istanbul.Validator {
  114. if valSet.Size() == 0 {
  115. return nil
  116. }
  117. seed := uint64(0)
  118. if emptyAddress(proposer) {
  119. seed = round
  120. } else {
  121. seed = calcSeed(valSet, proposer, round) + 1
  122. }
  123. pick := seed % uint64(valSet.Size())
  124. return valSet.GetByIndex(pick)
  125. }
  126. func stickyProposer(valSet istanbul.ValidatorSet, proposer common.Address, round uint64) istanbul.Validator {
  127. if valSet.Size() == 0 {
  128. return nil
  129. }
  130. seed := uint64(0)
  131. if emptyAddress(proposer) {
  132. seed = round
  133. } else {
  134. seed = calcSeed(valSet, proposer, round)
  135. }
  136. pick := seed % uint64(valSet.Size())
  137. return valSet.GetByIndex(pick)
  138. }
  139. func (valSet *defaultSet) AddValidator(address common.Address) bool {
  140. valSet.validatorMu.Lock()
  141. defer valSet.validatorMu.Unlock()
  142. for _, v := range valSet.validators {
  143. if v.Address() == address {
  144. return false
  145. }
  146. }
  147. valSet.validators = append(valSet.validators, New(address))
  148. // TODO: we may not need to re-sort it again
  149. // sort validator
  150. valSet.SortValidators()
  151. return true
  152. }
  153. func (valSet *defaultSet) RemoveValidator(address common.Address) bool {
  154. valSet.validatorMu.Lock()
  155. defer valSet.validatorMu.Unlock()
  156. for i, v := range valSet.validators {
  157. if v.Address() == address {
  158. valSet.validators = append(valSet.validators[:i], valSet.validators[i+1:]...)
  159. return true
  160. }
  161. }
  162. return false
  163. }
  164. func (valSet *defaultSet) Copy() istanbul.ValidatorSet {
  165. valSet.validatorMu.RLock()
  166. defer valSet.validatorMu.RUnlock()
  167. addresses := make([]common.Address, 0, len(valSet.validators))
  168. for _, v := range valSet.validators {
  169. addresses = append(addresses, v.Address())
  170. }
  171. return NewSet(addresses, valSet.policy)
  172. }
  173. func (valSet *defaultSet) F() int { return int(math.Ceil(float64(valSet.Size())/3)) - 1 }
  174. func (valSet *defaultSet) Policy() istanbul.ProposerPolicy { return *valSet.policy }