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