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 }