github.com/nnlgsakib/mind-dpos@v0.0.0-20230606105614-f3c8ca06f808/consensus/alien/signer_queue.go (about)

     1  // Copyright 2018 The gttc Authors
     2  // This file is part of the gttc library.
     3  //
     4  // The gttc 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 gttc 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 gttc library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package alien implements the delegated-proof-of-stake consensus engine.
    18  
    19  package alien
    20  
    21  import (
    22  	"bytes"
    23  	"math/big"
    24  	"sort"
    25  
    26  	"github.com/TTCECO/gttc/common"
    27  )
    28  
    29  type TallyItem struct {
    30  	addr  common.Address
    31  	stake *big.Int
    32  }
    33  type TallySlice []TallyItem
    34  
    35  func (s TallySlice) Len() int      { return len(s) }
    36  func (s TallySlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
    37  func (s TallySlice) Less(i, j int) bool {
    38  	//we need sort reverse, so ...
    39  	isLess := s[i].stake.Cmp(s[j].stake)
    40  	if isLess > 0 {
    41  		return true
    42  
    43  	} else if isLess < 0 {
    44  		return false
    45  	}
    46  	// if the stake equal
    47  	return bytes.Compare(s[i].addr.Bytes(), s[j].addr.Bytes()) > 0
    48  }
    49  
    50  type SignerItem struct {
    51  	addr common.Address
    52  	hash common.Hash
    53  }
    54  type SignerSlice []SignerItem
    55  
    56  func (s SignerSlice) Len() int      { return len(s) }
    57  func (s SignerSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
    58  func (s SignerSlice) Less(i, j int) bool {
    59  	return bytes.Compare(s[i].hash.Bytes(), s[j].hash.Bytes()) > 0
    60  }
    61  
    62  // verify the SignerQueue base on block hash
    63  func (s *Snapshot) verifySignerQueue(signerQueue []common.Address) error {
    64  
    65  	if len(signerQueue) > int(s.config.MaxSignerCount) {
    66  		return errInvalidSignerQueue
    67  	}
    68  	sq, err := s.createSignerQueue()
    69  	if err != nil {
    70  		return err
    71  	}
    72  	if len(sq) == 0 || len(sq) != len(signerQueue) {
    73  		return errInvalidSignerQueue
    74  	}
    75  	for i, signer := range signerQueue {
    76  		if signer != sq[i] {
    77  			return errInvalidSignerQueue
    78  		}
    79  	}
    80  
    81  	return nil
    82  }
    83  
    84  func (s *Snapshot) buildTallySlice() TallySlice {
    85  	var tallySlice TallySlice
    86  	for address, stake := range s.Tally {
    87  		if !candidateNeedPD || s.isCandidate(address) {
    88  			if _, ok := s.Punished[address]; ok {
    89  				var creditWeight uint64
    90  				if s.Punished[address] > defaultFullCredit-minCalSignerQueueCredit {
    91  					creditWeight = minCalSignerQueueCredit
    92  				} else {
    93  					creditWeight = defaultFullCredit - s.Punished[address]
    94  				}
    95  				tallySlice = append(tallySlice, TallyItem{address, new(big.Int).Mul(stake, big.NewInt(int64(creditWeight)))})
    96  			} else {
    97  				tallySlice = append(tallySlice, TallyItem{address, new(big.Int).Mul(stake, big.NewInt(defaultFullCredit))})
    98  			}
    99  		}
   100  	}
   101  	return tallySlice
   102  }
   103  
   104  func (s *Snapshot) createSignerQueue() ([]common.Address, error) {
   105  
   106  	if (s.Number+1)%s.config.MaxSignerCount != 0 || s.Hash != s.HistoryHash[len(s.HistoryHash)-1] {
   107  		return nil, errCreateSignerQueueNotAllowed
   108  	}
   109  
   110  	var signerSlice SignerSlice
   111  	var topStakeAddress []common.Address
   112  
   113  	if (s.Number+1)%(s.config.MaxSignerCount*s.LCRS) == 0 {
   114  		// before recalculate the signers, clear the candidate is not in snap.Candidates
   115  
   116  		// only recalculate signers from to tally per 10 loop,
   117  		// other loop end just reset the order of signers by block hash (nearly random)
   118  		tallySlice := s.buildTallySlice()
   119  		sort.Sort(TallySlice(tallySlice))
   120  		queueLength := int(s.config.MaxSignerCount)
   121  		if queueLength > len(tallySlice) {
   122  			queueLength = len(tallySlice)
   123  		}
   124  
   125  		if queueLength == defaultOfficialMaxSignerCount && len(tallySlice) > defaultOfficialThirdLevelCount {
   126  			for i, tallyItem := range tallySlice[:defaultOfficialFirstLevelCount] {
   127  				signerSlice = append(signerSlice, SignerItem{tallyItem.addr, s.HistoryHash[len(s.HistoryHash)-1-i]})
   128  			}
   129  			var signerSecondLevelSlice, signerThirdLevelSlice, signerLastLevelSlice SignerSlice
   130  			// 60%
   131  			for i, tallyItem := range tallySlice[defaultOfficialFirstLevelCount:defaultOfficialSecondLevelCount] {
   132  				signerSecondLevelSlice = append(signerSecondLevelSlice, SignerItem{tallyItem.addr, s.HistoryHash[len(s.HistoryHash)-1-i]})
   133  			}
   134  			sort.Sort(SignerSlice(signerSecondLevelSlice))
   135  			signerSlice = append(signerSlice, signerSecondLevelSlice[:6]...)
   136  			// 40%
   137  			for i, tallyItem := range tallySlice[defaultOfficialSecondLevelCount:defaultOfficialThirdLevelCount] {
   138  				signerThirdLevelSlice = append(signerThirdLevelSlice, SignerItem{tallyItem.addr, s.HistoryHash[len(s.HistoryHash)-1-i]})
   139  			}
   140  			sort.Sort(SignerSlice(signerThirdLevelSlice))
   141  			signerSlice = append(signerSlice, signerThirdLevelSlice[:4]...)
   142  			// choose 1 from last
   143  			maxValidCount := defaultOfficialMaxValidCount
   144  			if maxValidCount > len(tallySlice) {
   145  				maxValidCount = len(tallySlice)
   146  			}
   147  			for i, tallyItem := range tallySlice[defaultOfficialThirdLevelCount:maxValidCount] {
   148  				signerLastLevelSlice = append(signerLastLevelSlice, SignerItem{tallyItem.addr, s.HistoryHash[len(s.HistoryHash)-1-i]})
   149  			}
   150  			sort.Sort(SignerSlice(signerLastLevelSlice))
   151  			signerSlice = append(signerSlice, signerLastLevelSlice[0])
   152  
   153  		} else {
   154  			for i, tallyItem := range tallySlice[:queueLength] {
   155  				signerSlice = append(signerSlice, SignerItem{tallyItem.addr, s.HistoryHash[len(s.HistoryHash)-1-i]})
   156  			}
   157  
   158  		}
   159  
   160  	} else {
   161  		for i, signer := range s.Signers {
   162  			signerSlice = append(signerSlice, SignerItem{*signer, s.HistoryHash[len(s.HistoryHash)-1-i]})
   163  		}
   164  	}
   165  
   166  	sort.Sort(SignerSlice(signerSlice))
   167  	// Set the top candidates in random order base on block hash
   168  	if len(signerSlice) == 0 {
   169  		return nil, errSignerQueueEmpty
   170  	}
   171  	for i := 0; i < int(s.config.MaxSignerCount); i++ {
   172  		topStakeAddress = append(topStakeAddress, signerSlice[i%len(signerSlice)].addr)
   173  	}
   174  
   175  	return topStakeAddress, nil
   176  
   177  }