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  }