github.com/klaytn/klaytn@v1.10.2/consensus/istanbul/validator/weighted_test.go (about) 1 // Copyright 2019 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn 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 klaytn 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 klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package validator 18 19 import ( 20 "reflect" 21 "strings" 22 "testing" 23 24 "github.com/klaytn/klaytn/blockchain" 25 "github.com/klaytn/klaytn/common" 26 "github.com/klaytn/klaytn/consensus/istanbul" 27 "github.com/klaytn/klaytn/crypto" 28 "github.com/stretchr/testify/assert" 29 ) 30 31 func TestNewWeightedCouncil(t *testing.T) { 32 const ValCnt = 100 33 var validators []istanbul.Validator 34 var rewardAddrs []common.Address 35 var votingPowers []uint64 36 37 // Create 100 validators with random addresses 38 b := []byte{} 39 for i := 0; i < ValCnt; i++ { 40 key, _ := crypto.GenerateKey() 41 addr := crypto.PubkeyToAddress(key.PublicKey) 42 val := New(addr) 43 validators = append(validators, val) 44 b = append(b, val.Address().Bytes()...) 45 46 rewardKey, _ := crypto.GenerateKey() 47 rewardAddr := crypto.PubkeyToAddress(rewardKey.PublicKey) 48 rewardAddrs = append(rewardAddrs, rewardAddr) 49 50 votingPowers = append(votingPowers, uint64(1)) 51 } 52 53 // Create ValidatorSet 54 valSet := NewWeightedCouncil(ExtractValidators(b), nil, rewardAddrs, votingPowers, nil, istanbul.WeightedRandom, 21, 0, 0, nil) 55 if valSet == nil { 56 t.Errorf("the validator byte array cannot be parsed") 57 t.FailNow() 58 } 59 60 // Check validators sorting: should be in ascending order 61 for i := 0; i < ValCnt-1; i++ { 62 val := valSet.GetByIndex(uint64(i)) 63 nextVal := valSet.GetByIndex(uint64(i + 1)) 64 if strings.Compare(val.String(), nextVal.String()) >= 0 { 65 t.Errorf("validator set is not sorted in descending order") 66 } 67 } 68 } 69 70 func TestNormalWeightedCouncil(t *testing.T) { 71 b1 := common.Hex2Bytes(testAddress) 72 b2 := common.Hex2Bytes(testAddress2) 73 addr1 := common.BytesToAddress(b1) 74 addr2 := common.BytesToAddress(b2) 75 76 rewardKey1, _ := crypto.GenerateKey() 77 rewardAddr1 := crypto.PubkeyToAddress(rewardKey1.PublicKey) 78 79 rewardKey2, _ := crypto.GenerateKey() 80 rewardAddr2 := crypto.PubkeyToAddress(rewardKey2.PublicKey) 81 82 votingPower1 := uint64(1) 83 votingPower2 := uint64(2) 84 85 weight1 := uint64(1) 86 weight2 := uint64(2) 87 88 val1 := newWeightedValidator(addr1, rewardAddr1, votingPower1, weight1) 89 val2 := newWeightedValidator(addr2, rewardAddr2, votingPower2, weight2) 90 91 valSet := NewWeightedCouncil([]common.Address{addr1, addr2}, nil, []common.Address{rewardAddr1, rewardAddr2}, []uint64{votingPower1, votingPower2}, []uint64{weight1, weight2}, istanbul.WeightedRandom, 21, 0, 0, nil) 92 if valSet == nil { 93 t.Errorf("the format of validator set is invalid") 94 t.FailNow() 95 } 96 97 // check size 98 if size := valSet.Size(); size != 2 { 99 t.Errorf("the size of validator set is wrong: have %v, want 2", size) 100 } 101 102 // test get by index 103 if val := valSet.GetByIndex(uint64(0)); !reflect.DeepEqual(val, val1) { 104 t.Errorf("validator mismatch:") 105 t.Errorf(" Address(): %v, %v", val.Address(), val1.Address()) 106 t.Errorf(" String(): %v, %v", val.String(), val1.String()) 107 t.Errorf(" RewardAddresS(): %v, %v", val.RewardAddress(), val1.RewardAddress()) 108 t.Errorf(" VotingPower(): %v, %v", val.VotingPower(), val1.VotingPower()) 109 t.Errorf(" Weight(): %v, %v", val.Weight(), val1.Weight()) 110 } 111 112 // test get by invalid index 113 if val := valSet.GetByIndex(uint64(2)); val != nil { 114 t.Errorf("validator mismatch: have %v, want nil", val) 115 } 116 117 // test get by address 118 if _, val := valSet.GetByAddress(addr2); !reflect.DeepEqual(val, val2) { 119 t.Errorf("validator mismatch: have %v, want %v", val, val2) 120 } 121 122 // test get by invalid address 123 invalidAddr := common.HexToAddress("0x9535b2e7faaba5288511d89341d94a38063a349b") 124 if _, val := valSet.GetByAddress(invalidAddr); val != nil { 125 t.Errorf("validator mismatch: have %v, want nil", val) 126 } 127 128 // test get proposer 129 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) { 130 t.Errorf("proposer mismatch: have %v, want %v", val, val1) 131 } 132 133 // test calculate proposer 134 lastProposer := addr1 135 valSet.CalcProposer(lastProposer, uint64(0)) 136 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) { 137 t.Errorf("proposer mismatch: have %v, want %v", val, val1) 138 } 139 140 valSet.CalcProposer(lastProposer, uint64(1)) 141 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) { 142 t.Errorf("proposer mismatch: have %v, want %v", val, val2) 143 } 144 145 valSet.CalcProposer(lastProposer, uint64(2)) 146 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) { 147 t.Errorf("proposer mismatch: have %v, want %v", val, val1) 148 } 149 150 valSet.CalcProposer(lastProposer, uint64(5)) 151 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) { 152 t.Errorf("proposer mismatch: have %v, want %v", val, val2) 153 } 154 155 // test empty last proposer 156 lastProposer = common.Address{} 157 valSet.CalcProposer(lastProposer, uint64(3)) 158 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) { 159 t.Errorf("proposer mismatch: have %v, want %v", val, val2) 160 } 161 } 162 163 func TestEmptyWeightedCouncil(t *testing.T) { 164 valSet := NewWeightedCouncil(ExtractValidators([]byte{}), nil, nil, nil, nil, istanbul.WeightedRandom, 0, 0, 0, &blockchain.BlockChain{}) 165 if valSet == nil { 166 t.Errorf("validator set should not be nil") 167 } 168 } 169 170 func TestNewWeightedCouncil_InvalidPolicy(t *testing.T) { 171 // Invalid proposer policy 172 valSet := NewWeightedCouncil(ExtractValidators([]byte{}), nil, nil, nil, nil, istanbul.Sticky, 0, 0, 0, &blockchain.BlockChain{}) 173 assert.Equal(t, (*weightedCouncil)(nil), valSet) 174 175 valSet = NewWeightedCouncil(ExtractValidators([]byte{}), nil, nil, nil, nil, istanbul.RoundRobin, 0, 0, 0, &blockchain.BlockChain{}) 176 assert.Equal(t, (*weightedCouncil)(nil), valSet) 177 } 178 179 func TestNewWeightedCouncil_IncompleteParams(t *testing.T) { 180 const ValCnt = 3 181 var validators []istanbul.Validator 182 var rewardAddrs []common.Address 183 var votingPowers []uint64 184 var weights []uint64 185 186 // Create 3 validators with random addresses 187 b := []byte{} 188 for i := 0; i < ValCnt; i++ { 189 key, _ := crypto.GenerateKey() 190 addr := crypto.PubkeyToAddress(key.PublicKey) 191 val := New(addr) 192 validators = append(validators, val) 193 b = append(b, val.Address().Bytes()...) 194 195 rewardKey, _ := crypto.GenerateKey() 196 rewardAddr := crypto.PubkeyToAddress(rewardKey.PublicKey) 197 rewardAddrs = append(rewardAddrs, rewardAddr) 198 199 votingPowers = append(votingPowers, uint64(1)) 200 weights = append(weights, uint64(1)) 201 } 202 203 // No validator address 204 valSet := NewWeightedCouncil(ExtractValidators([]byte{}), nil, rewardAddrs, votingPowers, weights, istanbul.WeightedRandom, 0, 0, 0, &blockchain.BlockChain{}) 205 assert.Equal(t, (*weightedCouncil)(nil), valSet) 206 207 // Incomplete rewardAddrs 208 incompleteRewardAddrs := make([]common.Address, 1) 209 valSet = NewWeightedCouncil(ExtractValidators(b), nil, incompleteRewardAddrs, nil, nil, istanbul.WeightedRandom, 0, 0, 0, &blockchain.BlockChain{}) 210 assert.Equal(t, (*weightedCouncil)(nil), valSet) 211 212 // Incomplete rewardAddrs 213 incompleteVotingPowers := make([]uint64, 1) 214 valSet = NewWeightedCouncil(ExtractValidators(b), nil, nil, incompleteVotingPowers, nil, istanbul.WeightedRandom, 0, 0, 0, &blockchain.BlockChain{}) 215 assert.Equal(t, (*weightedCouncil)(nil), valSet) 216 217 // Incomplete rewardAddrs 218 incompleteWeights := make([]uint64, 1) 219 valSet = NewWeightedCouncil(ExtractValidators(b), nil, nil, nil, incompleteWeights, istanbul.WeightedRandom, 0, 0, 0, &blockchain.BlockChain{}) 220 assert.Equal(t, (*weightedCouncil)(nil), valSet) 221 }