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