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 }