github.com/evdatsion/aphelion-dpos-bft@v0.32.1/types/validator_set_test.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "fmt" 6 "math" 7 "sort" 8 "strings" 9 "testing" 10 "testing/quick" 11 12 "github.com/stretchr/testify/assert" 13 14 "github.com/evdatsion/aphelion-dpos-bft/crypto" 15 "github.com/evdatsion/aphelion-dpos-bft/crypto/ed25519" 16 cmn "github.com/evdatsion/aphelion-dpos-bft/libs/common" 17 tmtime "github.com/evdatsion/aphelion-dpos-bft/types/time" 18 ) 19 20 func TestValidatorSetBasic(t *testing.T) { 21 // empty or nil validator lists are allowed, 22 // but attempting to IncrementProposerPriority on them will panic. 23 vset := NewValidatorSet([]*Validator{}) 24 assert.Panics(t, func() { vset.IncrementProposerPriority(1) }) 25 26 vset = NewValidatorSet(nil) 27 assert.Panics(t, func() { vset.IncrementProposerPriority(1) }) 28 29 assert.EqualValues(t, vset, vset.Copy()) 30 assert.False(t, vset.HasAddress([]byte("some val"))) 31 idx, val := vset.GetByAddress([]byte("some val")) 32 assert.Equal(t, -1, idx) 33 assert.Nil(t, val) 34 addr, val := vset.GetByIndex(-100) 35 assert.Nil(t, addr) 36 assert.Nil(t, val) 37 addr, val = vset.GetByIndex(0) 38 assert.Nil(t, addr) 39 assert.Nil(t, val) 40 addr, val = vset.GetByIndex(100) 41 assert.Nil(t, addr) 42 assert.Nil(t, val) 43 assert.Zero(t, vset.Size()) 44 assert.Equal(t, int64(0), vset.TotalVotingPower()) 45 assert.Nil(t, vset.GetProposer()) 46 assert.Nil(t, vset.Hash()) 47 48 // add 49 val = randValidator_(vset.TotalVotingPower()) 50 assert.NoError(t, vset.UpdateWithChangeSet([]*Validator{val})) 51 52 assert.True(t, vset.HasAddress(val.Address)) 53 idx, _ = vset.GetByAddress(val.Address) 54 assert.Equal(t, 0, idx) 55 addr, _ = vset.GetByIndex(0) 56 assert.Equal(t, []byte(val.Address), addr) 57 assert.Equal(t, 1, vset.Size()) 58 assert.Equal(t, val.VotingPower, vset.TotalVotingPower()) 59 assert.NotNil(t, vset.Hash()) 60 assert.NotPanics(t, func() { vset.IncrementProposerPriority(1) }) 61 assert.Equal(t, val.Address, vset.GetProposer().Address) 62 63 // update 64 val = randValidator_(vset.TotalVotingPower()) 65 assert.NoError(t, vset.UpdateWithChangeSet([]*Validator{val})) 66 _, val = vset.GetByAddress(val.Address) 67 val.VotingPower += 100 68 proposerPriority := val.ProposerPriority 69 70 val.ProposerPriority = 0 71 assert.NoError(t, vset.UpdateWithChangeSet([]*Validator{val})) 72 _, val = vset.GetByAddress(val.Address) 73 assert.Equal(t, proposerPriority, val.ProposerPriority) 74 75 } 76 77 func TestCopy(t *testing.T) { 78 vset := randValidatorSet(10) 79 vsetHash := vset.Hash() 80 if len(vsetHash) == 0 { 81 t.Fatalf("ValidatorSet had unexpected zero hash") 82 } 83 84 vsetCopy := vset.Copy() 85 vsetCopyHash := vsetCopy.Hash() 86 87 if !bytes.Equal(vsetHash, vsetCopyHash) { 88 t.Fatalf("ValidatorSet copy had wrong hash. Orig: %X, Copy: %X", vsetHash, vsetCopyHash) 89 } 90 } 91 92 // Test that IncrementProposerPriority requires positive times. 93 func TestIncrementProposerPriorityPositiveTimes(t *testing.T) { 94 vset := NewValidatorSet([]*Validator{ 95 newValidator([]byte("foo"), 1000), 96 newValidator([]byte("bar"), 300), 97 newValidator([]byte("baz"), 330), 98 }) 99 100 assert.Panics(t, func() { vset.IncrementProposerPriority(-1) }) 101 assert.Panics(t, func() { vset.IncrementProposerPriority(0) }) 102 vset.IncrementProposerPriority(1) 103 } 104 105 func BenchmarkValidatorSetCopy(b *testing.B) { 106 b.StopTimer() 107 vset := NewValidatorSet([]*Validator{}) 108 for i := 0; i < 1000; i++ { 109 privKey := ed25519.GenPrivKey() 110 pubKey := privKey.PubKey() 111 val := NewValidator(pubKey, 10) 112 err := vset.UpdateWithChangeSet([]*Validator{val}) 113 if err != nil { 114 panic("Failed to add validator") 115 } 116 } 117 b.StartTimer() 118 119 for i := 0; i < b.N; i++ { 120 vset.Copy() 121 } 122 } 123 124 //------------------------------------------------------------------- 125 126 func TestProposerSelection1(t *testing.T) { 127 vset := NewValidatorSet([]*Validator{ 128 newValidator([]byte("foo"), 1000), 129 newValidator([]byte("bar"), 300), 130 newValidator([]byte("baz"), 330), 131 }) 132 var proposers []string 133 for i := 0; i < 99; i++ { 134 val := vset.GetProposer() 135 proposers = append(proposers, string(val.Address)) 136 vset.IncrementProposerPriority(1) 137 } 138 expected := `foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo foo baz bar foo foo foo baz foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo` 139 if expected != strings.Join(proposers, " ") { 140 t.Errorf("Expected sequence of proposers was\n%v\nbut got \n%v", expected, strings.Join(proposers, " ")) 141 } 142 } 143 144 func TestProposerSelection2(t *testing.T) { 145 addr0 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 146 addr1 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} 147 addr2 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2} 148 149 // when all voting power is same, we go in order of addresses 150 val0, val1, val2 := newValidator(addr0, 100), newValidator(addr1, 100), newValidator(addr2, 100) 151 valList := []*Validator{val0, val1, val2} 152 vals := NewValidatorSet(valList) 153 for i := 0; i < len(valList)*5; i++ { 154 ii := (i) % len(valList) 155 prop := vals.GetProposer() 156 if !bytes.Equal(prop.Address, valList[ii].Address) { 157 t.Fatalf("(%d): Expected %X. Got %X", i, valList[ii].Address, prop.Address) 158 } 159 vals.IncrementProposerPriority(1) 160 } 161 162 // One validator has more than the others, but not enough to propose twice in a row 163 *val2 = *newValidator(addr2, 400) 164 vals = NewValidatorSet(valList) 165 // vals.IncrementProposerPriority(1) 166 prop := vals.GetProposer() 167 if !bytes.Equal(prop.Address, addr2) { 168 t.Fatalf("Expected address with highest voting power to be first proposer. Got %X", prop.Address) 169 } 170 vals.IncrementProposerPriority(1) 171 prop = vals.GetProposer() 172 if !bytes.Equal(prop.Address, addr0) { 173 t.Fatalf("Expected smallest address to be validator. Got %X", prop.Address) 174 } 175 176 // One validator has more than the others, and enough to be proposer twice in a row 177 *val2 = *newValidator(addr2, 401) 178 vals = NewValidatorSet(valList) 179 prop = vals.GetProposer() 180 if !bytes.Equal(prop.Address, addr2) { 181 t.Fatalf("Expected address with highest voting power to be first proposer. Got %X", prop.Address) 182 } 183 vals.IncrementProposerPriority(1) 184 prop = vals.GetProposer() 185 if !bytes.Equal(prop.Address, addr2) { 186 t.Fatalf("Expected address with highest voting power to be second proposer. Got %X", prop.Address) 187 } 188 vals.IncrementProposerPriority(1) 189 prop = vals.GetProposer() 190 if !bytes.Equal(prop.Address, addr0) { 191 t.Fatalf("Expected smallest address to be validator. Got %X", prop.Address) 192 } 193 194 // each validator should be the proposer a proportional number of times 195 val0, val1, val2 = newValidator(addr0, 4), newValidator(addr1, 5), newValidator(addr2, 3) 196 valList = []*Validator{val0, val1, val2} 197 propCount := make([]int, 3) 198 vals = NewValidatorSet(valList) 199 N := 1 200 for i := 0; i < 120*N; i++ { 201 prop := vals.GetProposer() 202 ii := prop.Address[19] 203 propCount[ii]++ 204 vals.IncrementProposerPriority(1) 205 } 206 207 if propCount[0] != 40*N { 208 t.Fatalf("Expected prop count for validator with 4/12 of voting power to be %d/%d. Got %d/%d", 40*N, 120*N, propCount[0], 120*N) 209 } 210 if propCount[1] != 50*N { 211 t.Fatalf("Expected prop count for validator with 5/12 of voting power to be %d/%d. Got %d/%d", 50*N, 120*N, propCount[1], 120*N) 212 } 213 if propCount[2] != 30*N { 214 t.Fatalf("Expected prop count for validator with 3/12 of voting power to be %d/%d. Got %d/%d", 30*N, 120*N, propCount[2], 120*N) 215 } 216 } 217 218 func TestProposerSelection3(t *testing.T) { 219 vset := NewValidatorSet([]*Validator{ 220 newValidator([]byte("a"), 1), 221 newValidator([]byte("b"), 1), 222 newValidator([]byte("c"), 1), 223 newValidator([]byte("d"), 1), 224 }) 225 226 proposerOrder := make([]*Validator, 4) 227 for i := 0; i < 4; i++ { 228 proposerOrder[i] = vset.GetProposer() 229 vset.IncrementProposerPriority(1) 230 } 231 232 // i for the loop 233 // j for the times 234 // we should go in order for ever, despite some IncrementProposerPriority with times > 1 235 var i, j int 236 for ; i < 10000; i++ { 237 got := vset.GetProposer().Address 238 expected := proposerOrder[j%4].Address 239 if !bytes.Equal(got, expected) { 240 t.Fatalf(fmt.Sprintf("vset.Proposer (%X) does not match expected proposer (%X) for (%d, %d)", got, expected, i, j)) 241 } 242 243 // serialize, deserialize, check proposer 244 b := vset.toBytes() 245 vset.fromBytes(b) 246 247 computed := vset.GetProposer() // findGetProposer() 248 if i != 0 { 249 if !bytes.Equal(got, computed.Address) { 250 t.Fatalf(fmt.Sprintf("vset.Proposer (%X) does not match computed proposer (%X) for (%d, %d)", got, computed.Address, i, j)) 251 } 252 } 253 254 // times is usually 1 255 times := 1 256 mod := (cmn.RandInt() % 5) + 1 257 if cmn.RandInt()%mod > 0 { 258 // sometimes its up to 5 259 times = (cmn.RandInt() % 4) + 1 260 } 261 vset.IncrementProposerPriority(times) 262 263 j += times 264 } 265 } 266 267 func newValidator(address []byte, power int64) *Validator { 268 return &Validator{Address: address, VotingPower: power} 269 } 270 271 func randPubKey() crypto.PubKey { 272 var pubKey [32]byte 273 copy(pubKey[:], cmn.RandBytes(32)) 274 return ed25519.PubKeyEd25519(pubKey) 275 } 276 277 func randValidator_(totalVotingPower int64) *Validator { 278 // this modulo limits the ProposerPriority/VotingPower to stay in the 279 // bounds of MaxTotalVotingPower minus the already existing voting power: 280 val := NewValidator(randPubKey(), int64(cmn.RandUint64()%uint64((MaxTotalVotingPower-totalVotingPower)))) 281 val.ProposerPriority = cmn.RandInt64() % (MaxTotalVotingPower - totalVotingPower) 282 return val 283 } 284 285 func randValidatorSet(numValidators int) *ValidatorSet { 286 validators := make([]*Validator, numValidators) 287 totalVotingPower := int64(0) 288 for i := 0; i < numValidators; i++ { 289 validators[i] = randValidator_(totalVotingPower) 290 totalVotingPower += validators[i].VotingPower 291 } 292 return NewValidatorSet(validators) 293 } 294 295 func (valSet *ValidatorSet) toBytes() []byte { 296 bz, err := cdc.MarshalBinaryLengthPrefixed(valSet) 297 if err != nil { 298 panic(err) 299 } 300 return bz 301 } 302 303 func (valSet *ValidatorSet) fromBytes(b []byte) { 304 err := cdc.UnmarshalBinaryLengthPrefixed(b, &valSet) 305 if err != nil { 306 // DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED 307 panic(err) 308 } 309 } 310 311 //------------------------------------------------------------------- 312 313 func TestValidatorSetTotalVotingPowerPanicsOnOverflow(t *testing.T) { 314 // NewValidatorSet calls IncrementProposerPriority which calls TotalVotingPower() 315 // which should panic on overflows: 316 shouldPanic := func() { 317 NewValidatorSet([]*Validator{ 318 {Address: []byte("a"), VotingPower: math.MaxInt64, ProposerPriority: 0}, 319 {Address: []byte("b"), VotingPower: math.MaxInt64, ProposerPriority: 0}, 320 {Address: []byte("c"), VotingPower: math.MaxInt64, ProposerPriority: 0}, 321 }) 322 } 323 324 assert.Panics(t, shouldPanic) 325 } 326 327 func TestAvgProposerPriority(t *testing.T) { 328 // Create Validator set without calling IncrementProposerPriority: 329 tcs := []struct { 330 vs ValidatorSet 331 want int64 332 }{ 333 0: {ValidatorSet{Validators: []*Validator{{ProposerPriority: 0}, {ProposerPriority: 0}, {ProposerPriority: 0}}}, 0}, 334 1: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MaxInt64}, {ProposerPriority: 0}, {ProposerPriority: 0}}}, math.MaxInt64 / 3}, 335 2: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MaxInt64}, {ProposerPriority: 0}}}, math.MaxInt64 / 2}, 336 3: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MaxInt64}, {ProposerPriority: math.MaxInt64}}}, math.MaxInt64}, 337 4: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MinInt64}, {ProposerPriority: math.MinInt64}}}, math.MinInt64}, 338 } 339 for i, tc := range tcs { 340 got := tc.vs.computeAvgProposerPriority() 341 assert.Equal(t, tc.want, got, "test case: %v", i) 342 } 343 } 344 345 func TestAveragingInIncrementProposerPriority(t *testing.T) { 346 // Test that the averaging works as expected inside of IncrementProposerPriority. 347 // Each validator comes with zero voting power which simplifies reasoning about 348 // the expected ProposerPriority. 349 tcs := []struct { 350 vs ValidatorSet 351 times int 352 avg int64 353 }{ 354 0: {ValidatorSet{ 355 Validators: []*Validator{ 356 {Address: []byte("a"), ProposerPriority: 1}, 357 {Address: []byte("b"), ProposerPriority: 2}, 358 {Address: []byte("c"), ProposerPriority: 3}}}, 359 1, 2}, 360 1: {ValidatorSet{ 361 Validators: []*Validator{ 362 {Address: []byte("a"), ProposerPriority: 10}, 363 {Address: []byte("b"), ProposerPriority: -10}, 364 {Address: []byte("c"), ProposerPriority: 1}}}, 365 // this should average twice but the average should be 0 after the first iteration 366 // (voting power is 0 -> no changes) 367 11, 1 / 3}, 368 2: {ValidatorSet{ 369 Validators: []*Validator{ 370 {Address: []byte("a"), ProposerPriority: 100}, 371 {Address: []byte("b"), ProposerPriority: -10}, 372 {Address: []byte("c"), ProposerPriority: 1}}}, 373 1, 91 / 3}, 374 } 375 for i, tc := range tcs { 376 // work on copy to have the old ProposerPriorities: 377 newVset := tc.vs.CopyIncrementProposerPriority(tc.times) 378 for _, val := range tc.vs.Validators { 379 _, updatedVal := newVset.GetByAddress(val.Address) 380 assert.Equal(t, updatedVal.ProposerPriority, val.ProposerPriority-tc.avg, "test case: %v", i) 381 } 382 } 383 } 384 385 func TestAveragingInIncrementProposerPriorityWithVotingPower(t *testing.T) { 386 // Other than TestAveragingInIncrementProposerPriority this is a more complete test showing 387 // how each ProposerPriority changes in relation to the validator's voting power respectively. 388 // average is zero in each round: 389 vp0 := int64(10) 390 vp1 := int64(1) 391 vp2 := int64(1) 392 total := vp0 + vp1 + vp2 393 avg := (vp0 + vp1 + vp2 - total) / 3 394 vals := ValidatorSet{Validators: []*Validator{ 395 {Address: []byte{0}, ProposerPriority: 0, VotingPower: vp0}, 396 {Address: []byte{1}, ProposerPriority: 0, VotingPower: vp1}, 397 {Address: []byte{2}, ProposerPriority: 0, VotingPower: vp2}}} 398 tcs := []struct { 399 vals *ValidatorSet 400 wantProposerPrioritys []int64 401 times int 402 wantProposer *Validator 403 }{ 404 405 0: { 406 vals.Copy(), 407 []int64{ 408 // Acumm+VotingPower-Avg: 409 0 + vp0 - total - avg, // mostest will be subtracted by total voting power (12) 410 0 + vp1, 411 0 + vp2}, 412 1, 413 vals.Validators[0]}, 414 1: { 415 vals.Copy(), 416 []int64{ 417 (0 + vp0 - total) + vp0 - total - avg, // this will be mostest on 2nd iter, too 418 (0 + vp1) + vp1, 419 (0 + vp2) + vp2}, 420 2, 421 vals.Validators[0]}, // increment twice -> expect average to be subtracted twice 422 2: { 423 vals.Copy(), 424 []int64{ 425 0 + 3*(vp0-total) - avg, // still mostest 426 0 + 3*vp1, 427 0 + 3*vp2}, 428 3, 429 vals.Validators[0]}, 430 3: { 431 vals.Copy(), 432 []int64{ 433 0 + 4*(vp0-total), // still mostest 434 0 + 4*vp1, 435 0 + 4*vp2}, 436 4, 437 vals.Validators[0]}, 438 4: { 439 vals.Copy(), 440 []int64{ 441 0 + 4*(vp0-total) + vp0, // 4 iters was mostest 442 0 + 5*vp1 - total, // now this val is mostest for the 1st time (hence -12==totalVotingPower) 443 0 + 5*vp2}, 444 5, 445 vals.Validators[1]}, 446 5: { 447 vals.Copy(), 448 []int64{ 449 0 + 6*vp0 - 5*total, // mostest again 450 0 + 6*vp1 - total, // mostest once up to here 451 0 + 6*vp2}, 452 6, 453 vals.Validators[0]}, 454 6: { 455 vals.Copy(), 456 []int64{ 457 0 + 7*vp0 - 6*total, // in 7 iters this val is mostest 6 times 458 0 + 7*vp1 - total, // in 7 iters this val is mostest 1 time 459 0 + 7*vp2}, 460 7, 461 vals.Validators[0]}, 462 7: { 463 vals.Copy(), 464 []int64{ 465 0 + 8*vp0 - 7*total, // mostest again 466 0 + 8*vp1 - total, 467 0 + 8*vp2}, 468 8, 469 vals.Validators[0]}, 470 8: { 471 vals.Copy(), 472 []int64{ 473 0 + 9*vp0 - 7*total, 474 0 + 9*vp1 - total, 475 0 + 9*vp2 - total}, // mostest 476 9, 477 vals.Validators[2]}, 478 9: { 479 vals.Copy(), 480 []int64{ 481 0 + 10*vp0 - 8*total, // after 10 iters this is mostest again 482 0 + 10*vp1 - total, // after 6 iters this val is "mostest" once and not in between 483 0 + 10*vp2 - total}, // in between 10 iters this val is "mostest" once 484 10, 485 vals.Validators[0]}, 486 10: { 487 vals.Copy(), 488 []int64{ 489 0 + 11*vp0 - 9*total, 490 0 + 11*vp1 - total, // after 6 iters this val is "mostest" once and not in between 491 0 + 11*vp2 - total}, // after 10 iters this val is "mostest" once 492 11, 493 vals.Validators[0]}, 494 } 495 for i, tc := range tcs { 496 tc.vals.IncrementProposerPriority(tc.times) 497 498 assert.Equal(t, tc.wantProposer.Address, tc.vals.GetProposer().Address, 499 "test case: %v", 500 i) 501 502 for valIdx, val := range tc.vals.Validators { 503 assert.Equal(t, 504 tc.wantProposerPrioritys[valIdx], 505 val.ProposerPriority, 506 "test case: %v, validator: %v", 507 i, 508 valIdx) 509 } 510 } 511 } 512 513 func TestSafeAdd(t *testing.T) { 514 f := func(a, b int64) bool { 515 c, overflow := safeAdd(a, b) 516 return overflow || (!overflow && c == a+b) 517 } 518 if err := quick.Check(f, nil); err != nil { 519 t.Error(err) 520 } 521 } 522 523 func TestSafeAddClip(t *testing.T) { 524 assert.EqualValues(t, math.MaxInt64, safeAddClip(math.MaxInt64, 10)) 525 assert.EqualValues(t, math.MaxInt64, safeAddClip(math.MaxInt64, math.MaxInt64)) 526 assert.EqualValues(t, math.MinInt64, safeAddClip(math.MinInt64, -10)) 527 } 528 529 func TestSafeSubClip(t *testing.T) { 530 assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, 10)) 531 assert.EqualValues(t, 0, safeSubClip(math.MinInt64, math.MinInt64)) 532 assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, math.MaxInt64)) 533 assert.EqualValues(t, math.MaxInt64, safeSubClip(math.MaxInt64, -10)) 534 } 535 536 //------------------------------------------------------------------- 537 538 func TestValidatorSetVerifyCommit(t *testing.T) { 539 privKey := ed25519.GenPrivKey() 540 pubKey := privKey.PubKey() 541 v1 := NewValidator(pubKey, 1000) 542 vset := NewValidatorSet([]*Validator{v1}) 543 544 chainID := "mychainID" 545 blockID := BlockID{Hash: []byte("hello")} 546 height := int64(5) 547 vote := &Vote{ 548 ValidatorAddress: v1.Address, 549 ValidatorIndex: 0, 550 Height: height, 551 Round: 0, 552 Timestamp: tmtime.Now(), 553 Type: PrecommitType, 554 BlockID: blockID, 555 } 556 sig, err := privKey.Sign(vote.SignBytes(chainID)) 557 assert.NoError(t, err) 558 vote.Signature = sig 559 commit := NewCommit(blockID, []*CommitSig{vote.CommitSig()}) 560 561 badChainID := "notmychainID" 562 badBlockID := BlockID{Hash: []byte("goodbye")} 563 badHeight := height + 1 564 badCommit := NewCommit(blockID, []*CommitSig{nil}) 565 566 // test some error cases 567 // TODO: test more cases! 568 cases := []struct { 569 chainID string 570 blockID BlockID 571 height int64 572 commit *Commit 573 }{ 574 {badChainID, blockID, height, commit}, 575 {chainID, badBlockID, height, commit}, 576 {chainID, blockID, badHeight, commit}, 577 {chainID, blockID, height, badCommit}, 578 } 579 580 for i, c := range cases { 581 err := vset.VerifyCommit(c.chainID, c.blockID, c.height, c.commit) 582 assert.NotNil(t, err, i) 583 } 584 585 // test a good one 586 err = vset.VerifyCommit(chainID, blockID, height, commit) 587 assert.Nil(t, err) 588 } 589 590 func TestEmptySet(t *testing.T) { 591 592 var valList []*Validator 593 valSet := NewValidatorSet(valList) 594 assert.Panics(t, func() { valSet.IncrementProposerPriority(1) }) 595 assert.Panics(t, func() { valSet.RescalePriorities(100) }) 596 assert.Panics(t, func() { valSet.shiftByAvgProposerPriority() }) 597 assert.Panics(t, func() { assert.Zero(t, computeMaxMinPriorityDiff(valSet)) }) 598 valSet.GetProposer() 599 600 // Add to empty set 601 v1 := newValidator([]byte("v1"), 100) 602 v2 := newValidator([]byte("v2"), 100) 603 valList = []*Validator{v1, v2} 604 assert.NoError(t, valSet.UpdateWithChangeSet(valList)) 605 verifyValidatorSet(t, valSet) 606 607 // Delete all validators from set 608 v1 = newValidator([]byte("v1"), 0) 609 v2 = newValidator([]byte("v2"), 0) 610 delList := []*Validator{v1, v2} 611 assert.Error(t, valSet.UpdateWithChangeSet(delList)) 612 613 // Attempt delete from empty set 614 assert.Error(t, valSet.UpdateWithChangeSet(delList)) 615 616 } 617 618 func TestUpdatesForNewValidatorSet(t *testing.T) { 619 620 v1 := newValidator([]byte("v1"), 100) 621 v2 := newValidator([]byte("v2"), 100) 622 valList := []*Validator{v1, v2} 623 valSet := NewValidatorSet(valList) 624 verifyValidatorSet(t, valSet) 625 626 // Verify duplicates are caught in NewValidatorSet() and it panics 627 v111 := newValidator([]byte("v1"), 100) 628 v112 := newValidator([]byte("v1"), 123) 629 v113 := newValidator([]byte("v1"), 234) 630 valList = []*Validator{v111, v112, v113} 631 assert.Panics(t, func() { NewValidatorSet(valList) }) 632 633 // Verify set including validator with voting power 0 cannot be created 634 v1 = newValidator([]byte("v1"), 0) 635 v2 = newValidator([]byte("v2"), 22) 636 v3 := newValidator([]byte("v3"), 33) 637 valList = []*Validator{v1, v2, v3} 638 assert.Panics(t, func() { NewValidatorSet(valList) }) 639 640 // Verify set including validator with negative voting power cannot be created 641 v1 = newValidator([]byte("v1"), 10) 642 v2 = newValidator([]byte("v2"), -20) 643 v3 = newValidator([]byte("v3"), 30) 644 valList = []*Validator{v1, v2, v3} 645 assert.Panics(t, func() { NewValidatorSet(valList) }) 646 647 } 648 649 type testVal struct { 650 name string 651 power int64 652 } 653 654 func permutation(valList []testVal) []testVal { 655 if len(valList) == 0 { 656 return nil 657 } 658 permList := make([]testVal, len(valList)) 659 perm := cmn.RandPerm(len(valList)) 660 for i, v := range perm { 661 permList[v] = valList[i] 662 } 663 return permList 664 } 665 666 func createNewValidatorList(testValList []testVal) []*Validator { 667 valList := make([]*Validator, 0, len(testValList)) 668 for _, val := range testValList { 669 valList = append(valList, newValidator([]byte(val.name), val.power)) 670 } 671 return valList 672 } 673 674 func createNewValidatorSet(testValList []testVal) *ValidatorSet { 675 return NewValidatorSet(createNewValidatorList(testValList)) 676 } 677 678 func valSetTotalProposerPriority(valSet *ValidatorSet) int64 { 679 sum := int64(0) 680 for _, val := range valSet.Validators { 681 // mind overflow 682 sum = safeAddClip(sum, val.ProposerPriority) 683 } 684 return sum 685 } 686 687 func verifyValidatorSet(t *testing.T, valSet *ValidatorSet) { 688 // verify that the capacity and length of validators is the same 689 assert.Equal(t, len(valSet.Validators), cap(valSet.Validators)) 690 691 // verify that the set's total voting power has been updated 692 tvp := valSet.totalVotingPower 693 valSet.updateTotalVotingPower() 694 expectedTvp := valSet.TotalVotingPower() 695 assert.Equal(t, expectedTvp, tvp, 696 "expected TVP %d. Got %d, valSet=%s", expectedTvp, tvp, valSet) 697 698 // verify that validator priorities are centered 699 valsCount := int64(len(valSet.Validators)) 700 tpp := valSetTotalProposerPriority(valSet) 701 assert.True(t, tpp < valsCount && tpp > -valsCount, 702 "expected total priority in (-%d, %d). Got %d", valsCount, valsCount, tpp) 703 704 // verify that priorities are scaled 705 dist := computeMaxMinPriorityDiff(valSet) 706 assert.True(t, dist <= PriorityWindowSizeFactor*tvp, 707 "expected priority distance < %d. Got %d", PriorityWindowSizeFactor*tvp, dist) 708 } 709 710 func toTestValList(valList []*Validator) []testVal { 711 testList := make([]testVal, len(valList)) 712 for i, val := range valList { 713 testList[i].name = string(val.Address) 714 testList[i].power = val.VotingPower 715 } 716 return testList 717 } 718 719 func testValSet(nVals int, power int64) []testVal { 720 vals := make([]testVal, nVals) 721 for i := 0; i < nVals; i++ { 722 vals[i] = testVal{fmt.Sprintf("v%d", i+1), power} 723 } 724 return vals 725 } 726 727 type valSetErrTestCase struct { 728 startVals []testVal 729 updateVals []testVal 730 } 731 732 func executeValSetErrTestCase(t *testing.T, idx int, tt valSetErrTestCase) { 733 // create a new set and apply updates, keeping copies for the checks 734 valSet := createNewValidatorSet(tt.startVals) 735 valSetCopy := valSet.Copy() 736 valList := createNewValidatorList(tt.updateVals) 737 valListCopy := validatorListCopy(valList) 738 err := valSet.UpdateWithChangeSet(valList) 739 740 // for errors check the validator set has not been changed 741 assert.Error(t, err, "test %d", idx) 742 assert.Equal(t, valSet, valSetCopy, "test %v", idx) 743 744 // check the parameter list has not changed 745 assert.Equal(t, valList, valListCopy, "test %v", idx) 746 } 747 748 func TestValSetUpdatesDuplicateEntries(t *testing.T) { 749 testCases := []valSetErrTestCase{ 750 // Duplicate entries in changes 751 { // first entry is duplicated change 752 testValSet(2, 10), 753 []testVal{{"v1", 11}, {"v1", 22}}, 754 }, 755 { // second entry is duplicated change 756 testValSet(2, 10), 757 []testVal{{"v2", 11}, {"v2", 22}}, 758 }, 759 { // change duplicates are separated by a valid change 760 testValSet(2, 10), 761 []testVal{{"v1", 11}, {"v2", 22}, {"v1", 12}}, 762 }, 763 { // change duplicates are separated by a valid change 764 testValSet(3, 10), 765 []testVal{{"v1", 11}, {"v3", 22}, {"v1", 12}}, 766 }, 767 768 // Duplicate entries in remove 769 { // first entry is duplicated remove 770 testValSet(2, 10), 771 []testVal{{"v1", 0}, {"v1", 0}}, 772 }, 773 { // second entry is duplicated remove 774 testValSet(2, 10), 775 []testVal{{"v2", 0}, {"v2", 0}}, 776 }, 777 { // remove duplicates are separated by a valid remove 778 testValSet(2, 10), 779 []testVal{{"v1", 0}, {"v2", 0}, {"v1", 0}}, 780 }, 781 { // remove duplicates are separated by a valid remove 782 testValSet(3, 10), 783 []testVal{{"v1", 0}, {"v3", 0}, {"v1", 0}}, 784 }, 785 786 { // remove and update same val 787 testValSet(2, 10), 788 []testVal{{"v1", 0}, {"v2", 20}, {"v1", 30}}, 789 }, 790 { // duplicate entries in removes + changes 791 testValSet(2, 10), 792 []testVal{{"v1", 0}, {"v2", 20}, {"v2", 30}, {"v1", 0}}, 793 }, 794 { // duplicate entries in removes + changes 795 testValSet(3, 10), 796 []testVal{{"v1", 0}, {"v3", 5}, {"v2", 20}, {"v2", 30}, {"v1", 0}}, 797 }, 798 } 799 800 for i, tt := range testCases { 801 executeValSetErrTestCase(t, i, tt) 802 } 803 } 804 805 func TestValSetUpdatesOverflows(t *testing.T) { 806 maxVP := MaxTotalVotingPower 807 testCases := []valSetErrTestCase{ 808 { // single update leading to overflow 809 testValSet(2, 10), 810 []testVal{{"v1", math.MaxInt64}}, 811 }, 812 { // single update leading to overflow 813 testValSet(2, 10), 814 []testVal{{"v2", math.MaxInt64}}, 815 }, 816 { // add validator leading to overflow 817 testValSet(1, maxVP), 818 []testVal{{"v2", math.MaxInt64}}, 819 }, 820 { // add validator leading to exceed Max 821 testValSet(1, maxVP-1), 822 []testVal{{"v2", 5}}, 823 }, 824 { // add validator leading to exceed Max 825 testValSet(2, maxVP/3), 826 []testVal{{"v3", maxVP / 2}}, 827 }, 828 { // add validator leading to exceed Max 829 testValSet(1, maxVP), 830 []testVal{{"v2", maxVP}}, 831 }, 832 } 833 834 for i, tt := range testCases { 835 executeValSetErrTestCase(t, i, tt) 836 } 837 } 838 839 func TestValSetUpdatesOtherErrors(t *testing.T) { 840 testCases := []valSetErrTestCase{ 841 { // update with negative voting power 842 testValSet(2, 10), 843 []testVal{{"v1", -123}}, 844 }, 845 { // update with negative voting power 846 testValSet(2, 10), 847 []testVal{{"v2", -123}}, 848 }, 849 { // remove non-existing validator 850 testValSet(2, 10), 851 []testVal{{"v3", 0}}, 852 }, 853 { // delete all validators 854 []testVal{{"v1", 10}, {"v2", 20}, {"v3", 30}}, 855 []testVal{{"v1", 0}, {"v2", 0}, {"v3", 0}}, 856 }, 857 } 858 859 for i, tt := range testCases { 860 executeValSetErrTestCase(t, i, tt) 861 } 862 } 863 864 func TestValSetUpdatesBasicTestsExecute(t *testing.T) { 865 valSetUpdatesBasicTests := []struct { 866 startVals []testVal 867 updateVals []testVal 868 expectedVals []testVal 869 }{ 870 { // no changes 871 testValSet(2, 10), 872 []testVal{}, 873 testValSet(2, 10), 874 }, 875 { // voting power changes 876 testValSet(2, 10), 877 []testVal{{"v1", 11}, {"v2", 22}}, 878 []testVal{{"v1", 11}, {"v2", 22}}, 879 }, 880 { // add new validators 881 []testVal{{"v1", 10}, {"v2", 20}}, 882 []testVal{{"v3", 30}, {"v4", 40}}, 883 []testVal{{"v1", 10}, {"v2", 20}, {"v3", 30}, {"v4", 40}}, 884 }, 885 { // add new validator to middle 886 []testVal{{"v1", 10}, {"v3", 20}}, 887 []testVal{{"v2", 30}}, 888 []testVal{{"v1", 10}, {"v2", 30}, {"v3", 20}}, 889 }, 890 { // add new validator to beginning 891 []testVal{{"v2", 10}, {"v3", 20}}, 892 []testVal{{"v1", 30}}, 893 []testVal{{"v1", 30}, {"v2", 10}, {"v3", 20}}, 894 }, 895 { // delete validators 896 []testVal{{"v1", 10}, {"v2", 20}, {"v3", 30}}, 897 []testVal{{"v2", 0}}, 898 []testVal{{"v1", 10}, {"v3", 30}}, 899 }, 900 } 901 902 for i, tt := range valSetUpdatesBasicTests { 903 // create a new set and apply updates, keeping copies for the checks 904 valSet := createNewValidatorSet(tt.startVals) 905 valList := createNewValidatorList(tt.updateVals) 906 err := valSet.UpdateWithChangeSet(valList) 907 assert.NoError(t, err, "test %d", i) 908 909 valListCopy := validatorListCopy(valSet.Validators) 910 // check that the voting power in the set's validators is not changing if the voting power 911 // is changed in the list of validators previously passed as parameter to UpdateWithChangeSet. 912 // this is to make sure copies of the validators are made by UpdateWithChangeSet. 913 if len(valList) > 0 { 914 valList[0].VotingPower++ 915 assert.Equal(t, toTestValList(valListCopy), toTestValList(valSet.Validators), "test %v", i) 916 917 } 918 919 // check the final validator list is as expected and the set is properly scaled and centered. 920 assert.Equal(t, tt.expectedVals, toTestValList(valSet.Validators), "test %v", i) 921 verifyValidatorSet(t, valSet) 922 } 923 } 924 925 // Test that different permutations of an update give the same result. 926 func TestValSetUpdatesOrderIndependenceTestsExecute(t *testing.T) { 927 // startVals - initial validators to create the set with 928 // updateVals - a sequence of updates to be applied to the set. 929 // updateVals is shuffled a number of times during testing to check for same resulting validator set. 930 valSetUpdatesOrderTests := []struct { 931 startVals []testVal 932 updateVals []testVal 933 }{ 934 0: { // order of changes should not matter, the final validator sets should be the same 935 []testVal{{"v1", 10}, {"v2", 10}, {"v3", 30}, {"v4", 40}}, 936 []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}, {"v4", 44}}}, 937 938 1: { // order of additions should not matter 939 []testVal{{"v1", 10}, {"v2", 20}}, 940 []testVal{{"v3", 30}, {"v4", 40}, {"v5", 50}, {"v6", 60}}}, 941 942 2: { // order of removals should not matter 943 []testVal{{"v1", 10}, {"v2", 20}, {"v3", 30}, {"v4", 40}}, 944 []testVal{{"v1", 0}, {"v3", 0}, {"v4", 0}}}, 945 946 3: { // order of mixed operations should not matter 947 []testVal{{"v1", 10}, {"v2", 20}, {"v3", 30}, {"v4", 40}}, 948 []testVal{{"v1", 0}, {"v3", 0}, {"v2", 22}, {"v5", 50}, {"v4", 44}}}, 949 } 950 951 for i, tt := range valSetUpdatesOrderTests { 952 // create a new set and apply updates 953 valSet := createNewValidatorSet(tt.startVals) 954 valSetCopy := valSet.Copy() 955 valList := createNewValidatorList(tt.updateVals) 956 assert.NoError(t, valSetCopy.UpdateWithChangeSet(valList)) 957 958 // save the result as expected for next updates 959 valSetExp := valSetCopy.Copy() 960 961 // perform at most 20 permutations on the updates and call UpdateWithChangeSet() 962 n := len(tt.updateVals) 963 maxNumPerms := cmn.MinInt(20, n*n) 964 for j := 0; j < maxNumPerms; j++ { 965 // create a copy of original set and apply a random permutation of updates 966 valSetCopy := valSet.Copy() 967 valList := createNewValidatorList(permutation(tt.updateVals)) 968 969 // check there was no error and the set is properly scaled and centered. 970 assert.NoError(t, valSetCopy.UpdateWithChangeSet(valList), 971 "test %v failed for permutation %v", i, valList) 972 verifyValidatorSet(t, valSetCopy) 973 974 // verify the resulting test is same as the expected 975 assert.Equal(t, valSetCopy, valSetExp, 976 "test %v failed for permutation %v", i, valList) 977 } 978 } 979 } 980 981 // This tests the private function validator_set.go:applyUpdates() function, used only for additions and changes. 982 // Should perform a proper merge of updatedVals and startVals 983 func TestValSetApplyUpdatesTestsExecute(t *testing.T) { 984 valSetUpdatesBasicTests := []struct { 985 startVals []testVal 986 updateVals []testVal 987 expectedVals []testVal 988 }{ 989 // additions 990 0: { // prepend 991 []testVal{{"v4", 44}, {"v5", 55}}, 992 []testVal{{"v1", 11}}, 993 []testVal{{"v1", 11}, {"v4", 44}, {"v5", 55}}}, 994 1: { // append 995 []testVal{{"v4", 44}, {"v5", 55}}, 996 []testVal{{"v6", 66}}, 997 []testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}}}, 998 2: { // insert 999 []testVal{{"v4", 44}, {"v6", 66}}, 1000 []testVal{{"v5", 55}}, 1001 []testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}}}, 1002 3: { // insert multi 1003 []testVal{{"v4", 44}, {"v6", 66}, {"v9", 99}}, 1004 []testVal{{"v5", 55}, {"v7", 77}, {"v8", 88}}, 1005 []testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}, {"v7", 77}, {"v8", 88}, {"v9", 99}}}, 1006 // changes 1007 4: { // head 1008 []testVal{{"v1", 111}, {"v2", 22}}, 1009 []testVal{{"v1", 11}}, 1010 []testVal{{"v1", 11}, {"v2", 22}}}, 1011 5: { // tail 1012 []testVal{{"v1", 11}, {"v2", 222}}, 1013 []testVal{{"v2", 22}}, 1014 []testVal{{"v1", 11}, {"v2", 22}}}, 1015 6: { // middle 1016 []testVal{{"v1", 11}, {"v2", 222}, {"v3", 33}}, 1017 []testVal{{"v2", 22}}, 1018 []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}}}, 1019 7: { // multi 1020 []testVal{{"v1", 111}, {"v2", 222}, {"v3", 333}}, 1021 []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}}, 1022 []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}}}, 1023 // additions and changes 1024 8: { 1025 []testVal{{"v1", 111}, {"v2", 22}}, 1026 []testVal{{"v1", 11}, {"v3", 33}, {"v4", 44}}, 1027 []testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}, {"v4", 44}}}, 1028 } 1029 1030 for i, tt := range valSetUpdatesBasicTests { 1031 // create a new validator set with the start values 1032 valSet := createNewValidatorSet(tt.startVals) 1033 1034 // applyUpdates() with the update values 1035 valList := createNewValidatorList(tt.updateVals) 1036 valSet.applyUpdates(valList) 1037 1038 // check the new list of validators for proper merge 1039 assert.Equal(t, toTestValList(valSet.Validators), tt.expectedVals, "test %v", i) 1040 } 1041 } 1042 1043 type testVSetCfg struct { 1044 startVals []testVal 1045 deletedVals []testVal 1046 updatedVals []testVal 1047 addedVals []testVal 1048 expectedVals []testVal 1049 } 1050 1051 func randTestVSetCfg(t *testing.T, nBase, nAddMax int) testVSetCfg { 1052 if nBase <= 0 || nAddMax < 0 { 1053 panic(fmt.Sprintf("bad parameters %v %v", nBase, nAddMax)) 1054 } 1055 1056 const maxPower = 1000 1057 var nOld, nDel, nChanged, nAdd int 1058 1059 nOld = int(cmn.RandUint()%uint(nBase)) + 1 1060 if nBase-nOld > 0 { 1061 nDel = int(cmn.RandUint() % uint(nBase-nOld)) 1062 } 1063 nChanged = nBase - nOld - nDel 1064 1065 if nAddMax > 0 { 1066 nAdd = cmn.RandInt()%nAddMax + 1 1067 } 1068 1069 cfg := testVSetCfg{} 1070 1071 cfg.startVals = make([]testVal, nBase) 1072 cfg.deletedVals = make([]testVal, nDel) 1073 cfg.addedVals = make([]testVal, nAdd) 1074 cfg.updatedVals = make([]testVal, nChanged) 1075 cfg.expectedVals = make([]testVal, nBase-nDel+nAdd) 1076 1077 for i := 0; i < nBase; i++ { 1078 cfg.startVals[i] = testVal{fmt.Sprintf("v%d", i), int64(cmn.RandUint()%maxPower + 1)} 1079 if i < nOld { 1080 cfg.expectedVals[i] = cfg.startVals[i] 1081 } 1082 if i >= nOld && i < nOld+nChanged { 1083 cfg.updatedVals[i-nOld] = testVal{fmt.Sprintf("v%d", i), int64(cmn.RandUint()%maxPower + 1)} 1084 cfg.expectedVals[i] = cfg.updatedVals[i-nOld] 1085 } 1086 if i >= nOld+nChanged { 1087 cfg.deletedVals[i-nOld-nChanged] = testVal{fmt.Sprintf("v%d", i), 0} 1088 } 1089 } 1090 1091 for i := nBase; i < nBase+nAdd; i++ { 1092 cfg.addedVals[i-nBase] = testVal{fmt.Sprintf("v%d", i), int64(cmn.RandUint()%maxPower + 1)} 1093 cfg.expectedVals[i-nDel] = cfg.addedVals[i-nBase] 1094 } 1095 1096 sort.Sort(testValsByAddress(cfg.startVals)) 1097 sort.Sort(testValsByAddress(cfg.deletedVals)) 1098 sort.Sort(testValsByAddress(cfg.updatedVals)) 1099 sort.Sort(testValsByAddress(cfg.addedVals)) 1100 sort.Sort(testValsByAddress(cfg.expectedVals)) 1101 1102 return cfg 1103 1104 } 1105 1106 func applyChangesToValSet(t *testing.T, valSet *ValidatorSet, valsLists ...[]testVal) { 1107 changes := make([]testVal, 0) 1108 for _, valsList := range valsLists { 1109 changes = append(changes, valsList...) 1110 } 1111 valList := createNewValidatorList(changes) 1112 err := valSet.UpdateWithChangeSet(valList) 1113 assert.NoError(t, err) 1114 } 1115 1116 func TestValSetUpdatePriorityOrderTests(t *testing.T) { 1117 const nMaxElections = 5000 1118 1119 testCases := []testVSetCfg{ 1120 0: { // remove high power validator, keep old equal lower power validators 1121 startVals: []testVal{{"v1", 1}, {"v2", 1}, {"v3", 1000}}, 1122 deletedVals: []testVal{{"v3", 0}}, 1123 updatedVals: []testVal{}, 1124 addedVals: []testVal{}, 1125 expectedVals: []testVal{{"v1", 1}, {"v2", 1}}, 1126 }, 1127 1: { // remove high power validator, keep old different power validators 1128 startVals: []testVal{{"v1", 1}, {"v2", 10}, {"v3", 1000}}, 1129 deletedVals: []testVal{{"v3", 0}}, 1130 updatedVals: []testVal{}, 1131 addedVals: []testVal{}, 1132 expectedVals: []testVal{{"v1", 1}, {"v2", 10}}, 1133 }, 1134 2: { // remove high power validator, add new low power validators, keep old lower power 1135 startVals: []testVal{{"v1", 1}, {"v2", 2}, {"v3", 1000}}, 1136 deletedVals: []testVal{{"v3", 0}}, 1137 updatedVals: []testVal{{"v2", 1}}, 1138 addedVals: []testVal{{"v4", 40}, {"v5", 50}}, 1139 expectedVals: []testVal{{"v1", 1}, {"v2", 1}, {"v4", 40}, {"v5", 50}}, 1140 }, 1141 1142 // generate a configuration with 100 validators, 1143 // randomly select validators for updates and deletes, and 1144 // generate 10 new validators to be added 1145 3: randTestVSetCfg(t, 100, 10), 1146 1147 4: randTestVSetCfg(t, 1000, 100), 1148 1149 5: randTestVSetCfg(t, 10, 100), 1150 1151 6: randTestVSetCfg(t, 100, 1000), 1152 1153 7: randTestVSetCfg(t, 1000, 1000), 1154 1155 8: randTestVSetCfg(t, 10000, 1000), 1156 1157 9: randTestVSetCfg(t, 1000, 10000), 1158 } 1159 1160 for _, cfg := range testCases { 1161 1162 // create a new validator set 1163 valSet := createNewValidatorSet(cfg.startVals) 1164 verifyValidatorSet(t, valSet) 1165 1166 // run election up to nMaxElections times, apply changes and verify that the priority order is correct 1167 verifyValSetUpdatePriorityOrder(t, valSet, cfg, nMaxElections) 1168 } 1169 } 1170 1171 func verifyValSetUpdatePriorityOrder(t *testing.T, valSet *ValidatorSet, cfg testVSetCfg, nMaxElections int) { 1172 1173 // Run election up to nMaxElections times, sort validators by priorities 1174 valSet.IncrementProposerPriority(cmn.RandInt()%nMaxElections + 1) 1175 origValsPriSorted := validatorListCopy(valSet.Validators) 1176 sort.Sort(validatorsByPriority(origValsPriSorted)) 1177 1178 // apply the changes, get the updated validators, sort by priorities 1179 applyChangesToValSet(t, valSet, cfg.addedVals, cfg.updatedVals, cfg.deletedVals) 1180 updatedValsPriSorted := validatorListCopy(valSet.Validators) 1181 sort.Sort(validatorsByPriority(updatedValsPriSorted)) 1182 1183 // basic checks 1184 assert.Equal(t, toTestValList(valSet.Validators), cfg.expectedVals) 1185 verifyValidatorSet(t, valSet) 1186 1187 // verify that the added validators have the smallest priority: 1188 // - they should be at the beginning of valListNewPriority since it is sorted by priority 1189 if len(cfg.addedVals) > 0 { 1190 addedValsPriSlice := updatedValsPriSorted[:len(cfg.addedVals)] 1191 sort.Sort(ValidatorsByAddress(addedValsPriSlice)) 1192 assert.Equal(t, cfg.addedVals, toTestValList(addedValsPriSlice)) 1193 1194 // - and should all have the same priority 1195 expectedPri := addedValsPriSlice[0].ProposerPriority 1196 for _, val := range addedValsPriSlice[1:] { 1197 assert.Equal(t, expectedPri, val.ProposerPriority) 1198 } 1199 } 1200 } 1201 1202 //--------------------- 1203 // Sort validators by priority and address 1204 type validatorsByPriority []*Validator 1205 1206 func (valz validatorsByPriority) Len() int { 1207 return len(valz) 1208 } 1209 1210 func (valz validatorsByPriority) Less(i, j int) bool { 1211 if valz[i].ProposerPriority < valz[j].ProposerPriority { 1212 return true 1213 } 1214 if valz[i].ProposerPriority > valz[j].ProposerPriority { 1215 return false 1216 } 1217 return bytes.Compare(valz[i].Address, valz[j].Address) < 0 1218 } 1219 1220 func (valz validatorsByPriority) Swap(i, j int) { 1221 it := valz[i] 1222 valz[i] = valz[j] 1223 valz[j] = it 1224 } 1225 1226 //------------------------------------- 1227 // Sort testVal-s by address. 1228 type testValsByAddress []testVal 1229 1230 func (tvals testValsByAddress) Len() int { 1231 return len(tvals) 1232 } 1233 1234 func (tvals testValsByAddress) Less(i, j int) bool { 1235 return bytes.Compare([]byte(tvals[i].name), []byte(tvals[j].name)) == -1 1236 } 1237 1238 func (tvals testValsByAddress) Swap(i, j int) { 1239 it := tvals[i] 1240 tvals[i] = tvals[j] 1241 tvals[j] = it 1242 } 1243 1244 //------------------------------------- 1245 // Benchmark tests 1246 // 1247 func BenchmarkUpdates(b *testing.B) { 1248 const ( 1249 n = 100 1250 m = 2000 1251 ) 1252 // Init with n validators 1253 vs := make([]*Validator, n) 1254 for j := 0; j < n; j++ { 1255 vs[j] = newValidator([]byte(fmt.Sprintf("v%d", j)), 100) 1256 } 1257 valSet := NewValidatorSet(vs) 1258 l := len(valSet.Validators) 1259 1260 // Make m new validators 1261 newValList := make([]*Validator, m) 1262 for j := 0; j < m; j++ { 1263 newValList[j] = newValidator([]byte(fmt.Sprintf("v%d", j+l)), 1000) 1264 } 1265 b.ResetTimer() 1266 1267 for i := 0; i < b.N; i++ { 1268 // Add m validators to valSetCopy 1269 valSetCopy := valSet.Copy() 1270 assert.NoError(b, valSetCopy.UpdateWithChangeSet(newValList)) 1271 } 1272 }