github.com/elastos/Elastos.ELA.SideChain.ETH@v0.2.2/dpos/producers.go (about) 1 // Copyright (c) 2017-2019 The Elastos Foundation 2 // Use of this source code is governed by an MIT 3 // license that can be found in the LICENSE file. 4 // 5 6 package dpos 7 8 import ( 9 "bytes" 10 "sort" 11 "sync" 12 13 "github.com/elastos/Elastos.ELA/dpos/p2p/peer" 14 15 "github.com/elastos/Elastos.ELA.SideChain.ESC/common" 16 ) 17 18 var defaultCRCSignerNumber = 12 19 var zero = common.Hex2Bytes("000000000000000000000000000000000000000000000000000000000000000000") 20 21 type Producers struct { 22 totalProducers int 23 producers [][]byte 24 dutyIndex uint32 25 workingHeight uint64 26 spvHeight uint64 27 28 nextTotalProducers int 29 nextProducers []peer.PID 30 mtx sync.Mutex 31 } 32 33 func NewProducers(producers [][]byte, startHeight uint64) *Producers { 34 producer := &Producers{ 35 dutyIndex: 0, 36 workingHeight: startHeight, 37 } 38 defaultCRCSignerNumber = len(producers) 39 producer.UpdateProducers(producers, len(producers), 0) 40 return producer 41 } 42 43 func (p *Producers) UpdateProducers(producers [][]byte, totalCount int, spvHeight uint64) error { 44 p.mtx.Lock() 45 defer p.mtx.Unlock() 46 p.producers = make([][]byte, len(producers)) 47 copy(p.producers, producers) 48 p.totalProducers = totalCount 49 p.spvHeight = spvHeight 50 return nil 51 } 52 53 func (p *Producers) ChangeCurrentProducers(changeHeight uint64, spvHeight uint64) { 54 p.mtx.Lock() 55 defer p.mtx.Unlock() 56 p.producers = make([][]byte, len(p.nextProducers)) 57 58 for i, signer := range p.nextProducers { 59 if bytes.Equal(signer[:], zero) { 60 continue 61 } 62 p.producers[i] = make([]byte, len(signer)) 63 copy(p.producers[i][:], signer[:]) 64 } 65 p.SetWorkingHeight(changeHeight) 66 p.totalProducers = p.nextTotalProducers 67 p.spvHeight = spvHeight 68 69 } 70 71 func (p *Producers) SetWorkingHeight(changeHeight uint64) { 72 p.workingHeight = changeHeight 73 } 74 75 func (p *Producers) UpdateNextProducers(producers []peer.PID, totalCount int) error { 76 p.mtx.Lock() 77 defer p.mtx.Unlock() 78 79 sort.Slice(producers, func(i, j int) bool { 80 return bytes.Compare(producers[i][:], producers[j][:]) < 0 81 }) 82 p.nextProducers = []peer.PID{} 83 p.nextProducers = make([]peer.PID, len(producers)) 84 copy(p.nextProducers[:], producers[:]) 85 p.nextTotalProducers = totalCount 86 return nil 87 } 88 89 func (p *Producers) GetNeedConnectArbiters() []peer.PID { 90 p.mtx.Lock() 91 defer p.mtx.Unlock() 92 pids := make([]peer.PID, 0) 93 for _, producer := range p.producers { 94 var pid peer.PID 95 copy(pid[:], producer) 96 pids = append(pids, pid) 97 } 98 99 for _, producer := range p.nextProducers { 100 var pid peer.PID 101 copy(pid[:], producer[:]) 102 pids = append(pids, pid) 103 } 104 return pids 105 } 106 107 func (p *Producers) getCurrentNeedConnectArbiters() []peer.PID { 108 p.mtx.Lock() 109 defer p.mtx.Unlock() 110 pids := make([]peer.PID, 0) 111 for _, producer := range p.producers { 112 var pid peer.PID 113 copy(pid[:], producer) 114 pids = append(pids, pid) 115 } 116 return pids 117 } 118 119 func (p *Producers) GetNextNeedConnectArbiters() []peer.PID { 120 p.mtx.Lock() 121 defer p.mtx.Unlock() 122 pids := make([]peer.PID, 0) 123 for _, producer := range p.nextProducers { 124 var pid peer.PID 125 copy(pid[:], producer[:]) 126 pids = append(pids, pid) 127 } 128 return pids 129 } 130 131 func (p *Producers) UpdateDutyIndex(height uint64) uint32 { 132 p.mtx.Lock() 133 defer p.mtx.Unlock() 134 if len(p.producers) <= 0 { 135 return 0 136 } 137 index := (height + 1 - p.workingHeight) % uint64(len(p.producers)) 138 p.dutyIndex = uint32(index) 139 return uint32(index) 140 } 141 142 func (p *Producers) GetProducers() [][]byte { 143 p.mtx.Lock() 144 defer p.mtx.Unlock() 145 list := make([][]byte, len(p.producers)) 146 copy(list, p.producers) 147 return list 148 } 149 150 func (p *Producers) IsProducers(signer []byte) bool { 151 p.mtx.Lock() 152 defer p.mtx.Unlock() 153 for _, producer := range p.producers { 154 if bytes.Equal(producer, signer) { 155 return true 156 } 157 } 158 return false 159 } 160 161 func (p *Producers) ProducerIndex(signer []byte) int { 162 p.mtx.Lock() 163 defer p.mtx.Unlock() 164 for index, producer := range p.producers { 165 if bytes.Equal(producer, signer) { 166 return index 167 } 168 } 169 return -1 170 } 171 172 func (p *Producers) GetMajorityCount() int { 173 p.mtx.Lock() 174 minSignCount := int(float64(p.totalProducers) * 2 / 3) 175 p.mtx.Unlock() 176 return minSignCount 177 178 } 179 180 func (p *Producers) GetCRMajorityCount() int { 181 return p.GetMajorityCountByTotalSigners(defaultCRCSignerNumber) 182 } 183 184 func (p *Producers) GetMajorityCountByTotalSigners(totalSigner int) int { 185 p.mtx.Lock() 186 minSignCount := int(float64(totalSigner) * 2 / 3) 187 p.mtx.Unlock() 188 return minSignCount 189 } 190 191 func (p *Producers) GetProducersCount() int { 192 p.mtx.Lock() 193 result := len(p.producers) 194 p.mtx.Unlock() 195 return result 196 } 197 198 func (p *Producers) GetNextOnDutyProducer(offset uint32) []byte { 199 p.mtx.Lock() 200 defer p.mtx.Unlock() 201 producers := p.producers 202 if len(producers) == 0 { 203 return nil 204 } 205 index := (p.dutyIndex + offset) % uint32(len(producers)) 206 producer := producers[index] 207 208 return producer 209 } 210 211 func (p *Producers) IsMajorityAgree(count int) bool { 212 return count > p.GetMajorityCount() 213 } 214 215 func (p *Producers) IsMajorityRejected(count int) bool { 216 num := len(p.producers) 217 return count >= num-p.GetMajorityCount() 218 } 219 220 func (p *Producers) HasProducerMajorityCount(num int) bool { 221 return num > p.GetMajorityCount() 222 } 223 224 func (p *Producers) HasArbitersMinorityCount(num int) bool { 225 p.mtx.Lock() 226 count := len(p.producers) 227 p.mtx.Unlock() 228 return num >= count-p.GetMajorityCount() 229 }