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