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