github.com/klaytn/klaytn@v1.12.1/consensus/istanbul/validator/default_test.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2017 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from quorum/consensus/istanbul/validator/default_test.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package validator 22 23 import ( 24 "fmt" 25 "math/big" 26 "reflect" 27 "strings" 28 "testing" 29 30 "github.com/klaytn/klaytn/common" 31 "github.com/klaytn/klaytn/consensus/istanbul" 32 "github.com/klaytn/klaytn/crypto" 33 "github.com/klaytn/klaytn/fork" 34 "github.com/klaytn/klaytn/params" 35 "github.com/stretchr/testify/assert" 36 ) 37 38 var ( 39 testAddress = "136807B12327a8AfF9831F09617dA1B9D398cda2" 40 testAddress2 = "4dd324F9821485caE941640B32c3Bcf1fA6E93E6" 41 testAddress3 = "62E47d858bf8513fc401886B94E33e7DCec2Bfb7" 42 testAddress4 = "8aD8F547fa00f58A8c4fb3B671Ee5f1A75bA028a" 43 testAddress5 = "dd197E88fd97aF3877023cf20d69543fc72e6298" 44 ) 45 46 func TestNewValidatorSet(t *testing.T) { 47 var validators []istanbul.Validator 48 const ValCnt = 100 49 50 // Create 100 validators with random addresses 51 b := []byte{} 52 for i := 0; i < ValCnt; i++ { 53 key, _ := crypto.GenerateKey() 54 addr := crypto.PubkeyToAddress(key.PublicKey) 55 val := New(addr) 56 validators = append(validators, val) 57 b = append(b, val.Address().Bytes()...) 58 } 59 60 // Create ValidatorSet 61 valSet := NewSet(ExtractValidators(b), istanbul.RoundRobin) 62 if valSet == nil { 63 t.Errorf("the validator byte array cannot be parsed") 64 t.FailNow() 65 } 66 67 // Check validators sorting: should be in ascending order 68 for i := 0; i < ValCnt-1; i++ { 69 val := valSet.GetByIndex(uint64(i)) 70 nextVal := valSet.GetByIndex(uint64(i + 1)) 71 if strings.Compare(val.String(), nextVal.String()) >= 0 { 72 t.Errorf("validator set is not sorted in descending order") 73 } 74 } 75 } 76 77 func TestNormalValSet(t *testing.T) { 78 b1 := common.Hex2Bytes(testAddress) 79 b2 := common.Hex2Bytes(testAddress2) 80 addr1 := common.BytesToAddress(b1) 81 addr2 := common.BytesToAddress(b2) 82 val1 := New(addr1) 83 val2 := New(addr2) 84 85 valSet := newDefaultSet([]common.Address{addr1, addr2}, istanbul.RoundRobin) 86 if valSet == nil { 87 t.Errorf("the format of validator set is invalid") 88 t.FailNow() 89 } 90 91 // check size 92 if size := valSet.Size(); size != 2 { 93 t.Errorf("the size of validator set is wrong: have %v, want 2", size) 94 } 95 // test get by index 96 if val := valSet.GetByIndex(uint64(0)); !reflect.DeepEqual(val, val1) { 97 t.Errorf("validator mismatch: have %v, want %v", val, val1) 98 } 99 // test get by invalid index 100 if val := valSet.GetByIndex(uint64(2)); val != nil { 101 t.Errorf("validator mismatch: have %v, want nil", val) 102 } 103 // test get by address 104 if _, val := valSet.GetByAddress(addr2); !reflect.DeepEqual(val, val2) { 105 t.Errorf("validator mismatch: have %v, want %v", val, val2) 106 } 107 // test get by invalid address 108 invalidAddr := common.HexToAddress("0x9535b2e7faaba5288511d89341d94a38063a349b") 109 if _, val := valSet.GetByAddress(invalidAddr); val != nil { 110 t.Errorf("validator mismatch: have %v, want nil", val) 111 } 112 // test get proposer 113 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) { 114 t.Errorf("proposer mismatch: have %v, want %v", val, val1) 115 } 116 // test calculate proposer 117 lastProposer := addr1 118 valSet.CalcProposer(lastProposer, uint64(0)) 119 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) { 120 t.Errorf("proposer mismatch: have %v, want %v", val, val2) 121 } 122 valSet.CalcProposer(lastProposer, uint64(3)) 123 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) { 124 t.Errorf("proposer mismatch: have %v, want %v", val, val1) 125 } 126 // test empty last proposer 127 lastProposer = common.Address{} 128 valSet.CalcProposer(lastProposer, uint64(3)) 129 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) { 130 t.Errorf("proposer mismatch: have %v, want %v", val, val2) 131 } 132 } 133 134 func TestEmptyValSet(t *testing.T) { 135 valSet := NewSet(ExtractValidators([]byte{}), istanbul.RoundRobin) 136 if valSet == nil { 137 t.Errorf("validator set should not be nil") 138 } 139 } 140 141 func TestAddAndRemoveValidator(t *testing.T) { 142 valSet := NewSet(ExtractValidators([]byte{}), istanbul.RoundRobin) 143 if !valSet.AddValidator(common.StringToAddress(string(rune(2)))) { 144 t.Error("the validator should be added") 145 } 146 if valSet.AddValidator(common.StringToAddress(string(rune(2)))) { 147 t.Error("the existing validator should not be added") 148 } 149 valSet.AddValidator(common.StringToAddress(string(rune(1)))) 150 valSet.AddValidator(common.StringToAddress(string(rune(0)))) 151 if len(valSet.List()) != 3 { 152 t.Error("the size of validator set should be 3") 153 } 154 155 for i, v := range valSet.List() { 156 expected := common.StringToAddress(string(rune(i))) 157 if v.Address() != expected { 158 t.Errorf("the order of validators is wrong: have %v, want %v", v.Address().Hex(), expected.Hex()) 159 } 160 } 161 162 if !valSet.RemoveValidator(common.StringToAddress(string(rune(2)))) { 163 t.Error("the validator should be removed") 164 } 165 if valSet.RemoveValidator(common.StringToAddress(string(rune(2)))) { 166 t.Error("the non-existing validator should not be removed") 167 } 168 if len(valSet.List()) != 2 { 169 t.Error("the size of validator set should be 2") 170 } 171 valSet.RemoveValidator(common.StringToAddress(string(rune(1)))) 172 if len(valSet.List()) != 1 { 173 t.Error("the size of validator set should be 1") 174 } 175 valSet.RemoveValidator(common.StringToAddress(string(rune(0)))) 176 if len(valSet.List()) != 0 { 177 t.Error("the size of validator set should be 0") 178 } 179 } 180 181 func TestStickyProposer(t *testing.T) { 182 b1 := common.Hex2Bytes(testAddress) 183 b2 := common.Hex2Bytes(testAddress2) 184 addr1 := common.BytesToAddress(b1) 185 addr2 := common.BytesToAddress(b2) 186 val1 := New(addr1) 187 val2 := New(addr2) 188 189 valSet := newDefaultSet([]common.Address{addr1, addr2}, istanbul.Sticky) 190 191 // test get proposer 192 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) { 193 t.Errorf("proposer mismatch: have %v, want %v", val, val1) 194 } 195 // test calculate proposer 196 lastProposer := addr1 197 valSet.CalcProposer(lastProposer, uint64(0)) 198 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) { 199 t.Errorf("proposer mismatch: have %v, want %v", val, val1) 200 } 201 202 valSet.CalcProposer(lastProposer, uint64(1)) 203 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) { 204 t.Errorf("proposer mismatch: have %v, want %v", val, val2) 205 } 206 // test empty last proposer 207 lastProposer = common.Address{} 208 valSet.CalcProposer(lastProposer, uint64(3)) 209 if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) { 210 t.Errorf("proposer mismatch: have %v, want %v", val, val2) 211 } 212 } 213 214 func TestDefaultSet_SubList(t *testing.T) { 215 fork.SetHardForkBlockNumberConfig(¶ms.ChainConfig{}) 216 defer fork.ClearHardForkBlockNumberConfig() 217 218 b1 := common.Hex2Bytes(testAddress) 219 b2 := common.Hex2Bytes(testAddress2) 220 b3 := common.Hex2Bytes(testAddress3) 221 b4 := common.Hex2Bytes(testAddress4) 222 b5 := common.Hex2Bytes(testAddress5) 223 addr1 := common.BytesToAddress(b1) 224 addr2 := common.BytesToAddress(b2) 225 addr3 := common.BytesToAddress(b3) 226 addr4 := common.BytesToAddress(b4) 227 addr5 := common.BytesToAddress(b5) 228 testAddresses := []common.Address{addr1, addr2, addr3, addr4, addr5} 229 230 valSet := NewSet(testAddresses, istanbul.RoundRobin) 231 if valSet == nil { 232 t.Errorf("the format of validator set is invalid") 233 t.FailNow() 234 } 235 valSet.SetSubGroupSize(3) 236 237 hash := istanbul.RLPHash("This is a test hash") 238 view := &istanbul.View{ 239 Sequence: new(big.Int).SetInt64(1), 240 Round: new(big.Int).SetInt64(0), 241 } 242 243 lenAddress := len(testAddresses) 244 for i := 0; i < lenAddress*2; i++ { 245 currentProposer := valSet.GetProposer() 246 assert.Equal(t, testAddresses[i%lenAddress], currentProposer.Address()) 247 248 committee := valSet.SubList(hash, view) 249 250 assert.Equal(t, testAddresses[i%lenAddress].String(), committee[0].String()) 251 assert.Equal(t, testAddresses[(i+1)%lenAddress].String(), committee[1].String()) 252 253 valSet.CalcProposer(currentProposer.Address(), view.Round.Uint64()) 254 } 255 } 256 257 func TestDefaultSet_Copy(t *testing.T) { 258 b1 := common.Hex2Bytes(testAddress) 259 b2 := common.Hex2Bytes(testAddress2) 260 b3 := common.Hex2Bytes(testAddress3) 261 b4 := common.Hex2Bytes(testAddress4) 262 b5 := common.Hex2Bytes(testAddress5) 263 addr1 := common.BytesToAddress(b1) 264 addr2 := common.BytesToAddress(b2) 265 addr3 := common.BytesToAddress(b3) 266 addr4 := common.BytesToAddress(b4) 267 addr5 := common.BytesToAddress(b5) 268 testAddresses := []common.Address{addr1, addr2, addr3, addr4, addr5} 269 270 valSet := NewSet(testAddresses, istanbul.RoundRobin) 271 copiedValSet := valSet.Copy() 272 273 assert.NotEqual(t, fmt.Sprintf("%p", &valSet), fmt.Sprintf("%p", &copiedValSet)) 274 275 assert.Equal(t, valSet.List(), copiedValSet.List()) 276 assert.NotEqual(t, fmt.Sprintf("%p", valSet.List()), fmt.Sprintf("%p", copiedValSet.List())) 277 278 for i := uint64(0); i < valSet.Size(); i++ { 279 assert.Equal(t, valSet.List()[i], copiedValSet.List()[i]) 280 assert.NotEqual(t, fmt.Sprintf("%p", valSet.List()[i]), fmt.Sprintf("%p", copiedValSet.List())[i]) 281 } 282 283 assert.Equal(t, valSet.GetProposer(), copiedValSet.GetProposer()) 284 assert.NotEqual(t, fmt.Sprintf("%p", valSet.GetProposer()), fmt.Sprintf("%p", copiedValSet.GetProposer())) 285 286 assert.Equal(t, valSet.Policy(), copiedValSet.Policy()) 287 assert.Equal(t, valSet.SubGroupSize(), copiedValSet.SubGroupSize()) 288 assert.Equal(t, valSet.TotalVotingPower(), copiedValSet.TotalVotingPower()) 289 }