github.com/nnlgsakib/mind-dpos@v0.0.0-20230606105614-f3c8ca06f808/consensus/alien/signer_queue_test.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 "testing" 25 26 "github.com/TTCECO/gttc/common" 27 "github.com/TTCECO/gttc/params" 28 ) 29 30 // Tests that voting is evaluated correctly for various simple and complex scenarios. 31 func TestQueue(t *testing.T) { 32 // Define the various voting scenarios to test 33 tests := []struct { 34 addrNames []string // accounts used in this case 35 signers []string 36 number uint64 37 maxSignerCount uint64 38 historyHash []string 39 tally map[string]uint64 40 punished map[string]uint64 41 result []string // the result of current snapshot 42 }{ 43 { 44 /* Case 0: 45 * new loop signer queue is create at blocknumber 2, 46 * the new signerQueue is selected by tally, and random order depends on history hash 47 * step 1: the top 3(maxSignerCount) is selected order by tally -> A, B, C 48 * step 2: the top 3 signer is map to historyHash A->c, B->b, C->a 49 * step 3: the result order is set by historyHash decrease -> A, B, C 50 */ 51 addrNames: []string{"A", "B", "C", "D"}, 52 signers: []string{"A", "B", "C", "D"}, 53 number: 2, 54 maxSignerCount: 3, 55 historyHash: []string{"a", "b", "c"}, 56 tally: map[string]uint64{"D": 5, "A": 30, "B": 20, "C": 10}, 57 punished: map[string]uint64{}, 58 result: []string{"A", "B", "C"}, 59 }, 60 { 61 /* Case 1: 62 * follow test case 0. the tally is same but history hash is x,b,c 63 * step 1: the top 3(maxSignerCount) is selected order by tally -> A, B, C 64 * step 2: the top 3 signer is map to historyHash A->c, B->b, C->x 65 * step 3: the result order is set by historyHash decrease -> C, A, B 66 * 67 */ 68 addrNames: []string{"A", "B", "C"}, 69 signers: []string{"A", "B", "C"}, 70 number: 2, 71 maxSignerCount: 3, 72 historyHash: []string{"x", "b", "c"}, 73 tally: map[string]uint64{"A": 30, "B": 20, "C": 10}, 74 punished: map[string]uint64{}, 75 result: []string{"C", "A", "B"}, 76 }, 77 { 78 /* Case 2: 79 * fllow test case 0. the tally is same but history hash is a,x,c 80 * step 1: the top 3(maxSignerCount) is selected order by tally -> A, B, C 81 * step 2: the top 3 signer is map to historyHash A->c, B->x, C->a 82 * step 3: the result order is set by historyHash decrease -> B, A, C 83 * 84 */ 85 addrNames: []string{"A", "B", "C"}, 86 signers: []string{"A", "B", "C"}, 87 number: 2, 88 maxSignerCount: 3, 89 historyHash: []string{"a", "x", "c"}, 90 tally: map[string]uint64{"A": 30, "B": 20, "C": 10}, 91 punished: map[string]uint64{}, 92 result: []string{"B", "A", "C"}, 93 }, 94 { 95 /* Case 3: 96 * fllow test case 0. the tally is changed and history hash is a,b,c 97 * step 1: the top 3(maxSignerCount) is selected order by tally -> B, A, C 98 * step 2: the top 3 signer is map to historyHash B->c, A->b, C->a 99 * step 3: the result order is set by historyHash decrease -> B, A, C 100 * 101 */ 102 addrNames: []string{"A", "B", "C"}, 103 signers: []string{"A", "B", "C"}, 104 number: 2, 105 maxSignerCount: 3, 106 historyHash: []string{"a", "b", "c"}, 107 tally: map[string]uint64{"A": 30, "B": 40, "C": 10}, 108 punished: map[string]uint64{}, 109 result: []string{"B", "A", "C"}, 110 }, 111 { 112 /* Case 4: 113 * fllow test case 0. the tally is changed and history hash is x,b,c 114 * step 1: the top 3(maxSignerCount) is selected order by tally -> B, A, C 115 * step 2: the top 3 signer is map to historyHash B->c, A->b, C->x 116 * step 3: the result order is set by historyHash decrease -> C, B, A 117 * 118 */ 119 addrNames: []string{"A", "B", "C"}, 120 signers: []string{"A", "B", "C"}, 121 number: 2, 122 maxSignerCount: 3, 123 historyHash: []string{"x", "b", "c"}, 124 tally: map[string]uint64{"A": 30, "B": 40, "C": 10}, 125 punished: map[string]uint64{}, 126 result: []string{"C", "B", "A"}, 127 }, 128 { 129 /* Case 5: 130 * fllow test case 0. the tally is changed and history hash is a,b,c 131 * step 1: the top 3(maxSignerCount) is selected order by tally -> but same t ally 132 * step 2: order by address (NOT A, B, C , address is [20]byte) desc, different by each test. 133 * step 3: the top 3 signer is map to historyHash 134 * step 4: the result order is set by historyHash decrease 135 * The result will be checked if order by address desc if result if empty 136 */ 137 addrNames: []string{"A", "B", "C"}, 138 signers: []string{"A", "B", "C"}, 139 number: 2, 140 maxSignerCount: 3, 141 historyHash: []string{"a", "b", "c"}, 142 tally: map[string]uint64{"A": 30, "B": 30, "C": 30}, 143 punished: map[string]uint64{}, 144 result: []string{}, // If tally(punished include) is same, then result order by their address 145 }, 146 { 147 /* Case 6: 148 * fllow test case 0. the tally is changed and history hash is x,b,c 149 * step 1: the top 3(maxSignerCount) is selected order by tally -> same tally 150 * step 2: consider the punished for each account, result order -> A, B, C 151 * step 3: the top 3 signer is map to historyHash A->c, B->b, C->x 152 * step 4: the result order is set by historyHash decrease -> C, A, B 153 * 154 */ 155 addrNames: []string{"A", "B", "C"}, 156 signers: []string{"A", "B", "C"}, 157 number: 2, 158 maxSignerCount: 3, 159 historyHash: []string{"x", "b", "c"}, 160 tally: map[string]uint64{"A": 300, "B": 300, "C": 300}, 161 punished: map[string]uint64{"A": 500, "B": 600, "C": 800}, 162 result: []string{"C", "A", "B"}, 163 }, 164 } 165 166 // Run through the scenarios and test them 167 for i, tt := range tests { 168 candidateNeedPD = false 169 // Create the account pool and generate the initial set of all address in addrNames 170 accounts := newTesterAccountPool() 171 addrNames := make([]common.Address, len(tt.addrNames)) 172 for j, signer := range tt.addrNames { 173 addrNames[j] = accounts.address(signer) 174 } 175 for j := 0; j < len(addrNames); j++ { 176 for k := j + 1; k < len(addrNames); k++ { 177 if bytes.Compare(addrNames[j][:], addrNames[k][:]) > 0 { 178 addrNames[j], addrNames[k] = addrNames[k], addrNames[j] 179 } 180 } 181 } 182 183 snap := &Snapshot{ 184 config: ¶ms.AlienConfig{MaxSignerCount: tt.maxSignerCount}, 185 Number: tt.number, 186 LCRS: 1, 187 Tally: make(map[common.Address]*big.Int), 188 Punished: make(map[common.Address]uint64), 189 } 190 191 snap.Hash.SetString(tt.historyHash[len(tt.historyHash)-1]) 192 for _, hash := range tt.historyHash { 193 var hh common.Hash 194 hh.SetString(hash) 195 snap.HistoryHash = append(snap.HistoryHash, hh) 196 } 197 198 for signer, tally := range tt.tally { 199 snap.Tally[accounts.address(signer)] = big.NewInt(int64(tally)) 200 } 201 202 for signer, punish := range tt.punished { 203 snap.Punished[accounts.address(signer)] = punish 204 } 205 206 signerQueue, err := snap.createSignerQueue() 207 if err != nil { 208 t.Errorf("test %d: create signer queue fail , err = %s", i, err) 209 continue 210 } 211 if len(tt.result) == 0 { 212 for j, signer := range signerQueue { 213 if j >= 1 && signerQueue[j-1].Str() < signerQueue[j].Str() { 214 t.Errorf("test %d: result is not correct, signerQueue(%d) %s larger than signerQueue(%d) %s ", i, j, signer.Hex(), j-1, signerQueue[j-1].Hex()) 215 } 216 } 217 } else { 218 if len(signerQueue) != len(tt.result) { 219 t.Errorf("test %d: length of result is not correct. len(signerQueue) is %d, but len(tt.result) is %d", i, len(signerQueue), len(tt.result)) 220 continue 221 } 222 for j, signer := range signerQueue { 223 if signer.Hex() != accounts.address(tt.result[j]).Hex() { 224 t.Errorf("test %d: result is not correct signerQueue(%d) is %s, but result(%d) is %s", i, j, signer.Hex(), j, accounts.address(tt.result[j]).Hex()) 225 } 226 } 227 } 228 229 } 230 }