github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/types/vote_set_test.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 "github.com/stretchr/testify/require" 9 10 "github.com/tendermint/tendermint/crypto" 11 tmrand "github.com/tendermint/tendermint/libs/rand" 12 tmtime "github.com/tendermint/tendermint/types/time" 13 ) 14 15 // NOTE: privValidators are in order 16 func randVoteSet( 17 height int64, 18 round int, 19 signedMsgType SignedMsgType, 20 numValidators int, 21 votingPower int64, 22 ) (*VoteSet, *ValidatorSet, []PrivValidator) { 23 valSet, privValidators := RandValidatorSet(numValidators, votingPower) 24 return NewVoteSet("test_chain_id", height, round, signedMsgType, valSet), valSet, privValidators 25 } 26 27 // Convenience: Return new vote with different validator address/index 28 func withValidator(vote *Vote, addr []byte, idx int) *Vote { 29 vote = vote.Copy() 30 vote.ValidatorAddress = addr 31 vote.ValidatorIndex = idx 32 return vote 33 } 34 35 // Convenience: Return new vote with different height 36 func withHeight(vote *Vote, height int64) *Vote { 37 vote = vote.Copy() 38 vote.Height = height 39 return vote 40 } 41 42 // Convenience: Return new vote with different round 43 func withRound(vote *Vote, round int) *Vote { 44 vote = vote.Copy() 45 vote.Round = round 46 return vote 47 } 48 49 // Convenience: Return new vote with different type 50 func withType(vote *Vote, signedMsgType byte) *Vote { 51 vote = vote.Copy() 52 vote.Type = SignedMsgType(signedMsgType) 53 return vote 54 } 55 56 // Convenience: Return new vote with different blockHash 57 func withBlockHash(vote *Vote, blockHash []byte) *Vote { 58 vote = vote.Copy() 59 vote.BlockID.Hash = blockHash 60 return vote 61 } 62 63 // Convenience: Return new vote with different blockParts 64 func withBlockPartsHeader(vote *Vote, blockPartsHeader PartSetHeader) *Vote { 65 vote = vote.Copy() 66 vote.BlockID.PartsHeader = blockPartsHeader 67 return vote 68 } 69 70 func TestAddVote(t *testing.T) { 71 height, round := int64(1), 0 72 voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 10, 1) 73 val0 := privValidators[0] 74 75 // t.Logf(">> %v", voteSet) 76 77 val0p, err := val0.GetPubKey() 78 require.NoError(t, err) 79 val0Addr := val0p.Address() 80 81 if voteSet.GetByAddress(val0Addr) != nil { 82 t.Errorf("expected GetByAddress(val0.Address) to be nil") 83 } 84 if voteSet.BitArray().GetIndex(0) { 85 t.Errorf("expected BitArray.GetIndex(0) to be false") 86 } 87 blockID, ok := voteSet.TwoThirdsMajority() 88 if ok || !blockID.IsZero() { 89 t.Errorf("there should be no 2/3 majority") 90 } 91 92 vote := &Vote{ 93 ValidatorAddress: val0Addr, 94 ValidatorIndex: 0, // since privValidators are in order 95 Height: height, 96 Round: round, 97 Type: PrevoteType, 98 Timestamp: tmtime.Now(), 99 BlockID: BlockID{nil, PartSetHeader{}}, 100 } 101 _, err = signAddVote(val0, vote, voteSet) 102 if err != nil { 103 t.Error(err) 104 } 105 106 if voteSet.GetByAddress(val0Addr) == nil { 107 t.Errorf("expected GetByAddress(val0.Address) to be present") 108 } 109 if !voteSet.BitArray().GetIndex(0) { 110 t.Errorf("expected BitArray.GetIndex(0) to be true") 111 } 112 blockID, ok = voteSet.TwoThirdsMajority() 113 if ok || !blockID.IsZero() { 114 t.Errorf("there should be no 2/3 majority") 115 } 116 } 117 118 func Test2_3Majority(t *testing.T) { 119 height, round := int64(1), 0 120 voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 10, 1) 121 122 voteProto := &Vote{ 123 ValidatorAddress: nil, // NOTE: must fill in 124 ValidatorIndex: -1, // NOTE: must fill in 125 Height: height, 126 Round: round, 127 Type: PrevoteType, 128 Timestamp: tmtime.Now(), 129 BlockID: BlockID{nil, PartSetHeader{}}, 130 } 131 // 6 out of 10 voted for nil. 132 for i := 0; i < 6; i++ { 133 pubKey, err := privValidators[i].GetPubKey() 134 require.NoError(t, err) 135 addr := pubKey.Address() 136 vote := withValidator(voteProto, addr, i) 137 _, err = signAddVote(privValidators[i], vote, voteSet) 138 if err != nil { 139 t.Error(err) 140 } 141 } 142 blockID, ok := voteSet.TwoThirdsMajority() 143 if ok || !blockID.IsZero() { 144 t.Errorf("there should be no 2/3 majority") 145 } 146 147 // 7th validator voted for some blockhash 148 { 149 pubKey, err := privValidators[6].GetPubKey() 150 require.NoError(t, err) 151 addr := pubKey.Address() 152 vote := withValidator(voteProto, addr, 6) 153 _, err = signAddVote(privValidators[6], withBlockHash(vote, tmrand.Bytes(32)), voteSet) 154 if err != nil { 155 t.Error(err) 156 } 157 blockID, ok = voteSet.TwoThirdsMajority() 158 if ok || !blockID.IsZero() { 159 t.Errorf("there should be no 2/3 majority") 160 } 161 } 162 163 // 8th validator voted for nil. 164 { 165 pubKey, err := privValidators[7].GetPubKey() 166 require.NoError(t, err) 167 addr := pubKey.Address() 168 vote := withValidator(voteProto, addr, 7) 169 _, err = signAddVote(privValidators[7], vote, voteSet) 170 if err != nil { 171 t.Error(err) 172 } 173 blockID, ok = voteSet.TwoThirdsMajority() 174 if !ok || !blockID.IsZero() { 175 t.Errorf("there should be 2/3 majority for nil") 176 } 177 } 178 } 179 180 func Test2_3MajorityRedux(t *testing.T) { 181 height, round := int64(1), 0 182 voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 100, 1) 183 184 blockHash := crypto.CRandBytes(32) 185 blockPartsTotal := 123 186 blockPartsHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)} 187 188 voteProto := &Vote{ 189 ValidatorAddress: nil, // NOTE: must fill in 190 ValidatorIndex: -1, // NOTE: must fill in 191 Height: height, 192 Round: round, 193 Timestamp: tmtime.Now(), 194 Type: PrevoteType, 195 BlockID: BlockID{blockHash, blockPartsHeader}, 196 } 197 198 // 66 out of 100 voted for nil. 199 for i := 0; i < 66; i++ { 200 pubKey, err := privValidators[i].GetPubKey() 201 require.NoError(t, err) 202 addr := pubKey.Address() 203 vote := withValidator(voteProto, addr, i) 204 _, err = signAddVote(privValidators[i], vote, voteSet) 205 if err != nil { 206 t.Error(err) 207 } 208 } 209 blockID, ok := voteSet.TwoThirdsMajority() 210 if ok || !blockID.IsZero() { 211 t.Errorf("there should be no 2/3 majority") 212 } 213 214 // 67th validator voted for nil 215 { 216 pubKey, err := privValidators[66].GetPubKey() 217 require.NoError(t, err) 218 adrr := pubKey.Address() 219 vote := withValidator(voteProto, adrr, 66) 220 _, err = signAddVote(privValidators[66], withBlockHash(vote, nil), voteSet) 221 if err != nil { 222 t.Error(err) 223 } 224 blockID, ok = voteSet.TwoThirdsMajority() 225 if ok || !blockID.IsZero() { 226 t.Errorf("there should be no 2/3 majority: last vote added was nil") 227 } 228 } 229 230 // 68th validator voted for a different BlockParts PartSetHeader 231 { 232 pubKey, err := privValidators[67].GetPubKey() 233 require.NoError(t, err) 234 addr := pubKey.Address() 235 vote := withValidator(voteProto, addr, 67) 236 blockPartsHeader := PartSetHeader{blockPartsTotal, crypto.CRandBytes(32)} 237 _, err = signAddVote(privValidators[67], withBlockPartsHeader(vote, blockPartsHeader), voteSet) 238 if err != nil { 239 t.Error(err) 240 } 241 blockID, ok = voteSet.TwoThirdsMajority() 242 if ok || !blockID.IsZero() { 243 t.Errorf("there should be no 2/3 majority: last vote added had different PartSetHeader Hash") 244 } 245 } 246 247 // 69th validator voted for different BlockParts Total 248 { 249 pubKey, err := privValidators[68].GetPubKey() 250 require.NoError(t, err) 251 addr := pubKey.Address() 252 vote := withValidator(voteProto, addr, 68) 253 blockPartsHeader := PartSetHeader{blockPartsTotal + 1, blockPartsHeader.Hash} 254 _, err = signAddVote(privValidators[68], withBlockPartsHeader(vote, blockPartsHeader), voteSet) 255 if err != nil { 256 t.Error(err) 257 } 258 blockID, ok = voteSet.TwoThirdsMajority() 259 if ok || !blockID.IsZero() { 260 t.Errorf("there should be no 2/3 majority: last vote added had different PartSetHeader Total") 261 } 262 } 263 264 // 70th validator voted for different BlockHash 265 { 266 pubKey, err := privValidators[69].GetPubKey() 267 require.NoError(t, err) 268 addr := pubKey.Address() 269 vote := withValidator(voteProto, addr, 69) 270 _, err = signAddVote(privValidators[69], withBlockHash(vote, tmrand.Bytes(32)), voteSet) 271 if err != nil { 272 t.Error(err) 273 } 274 blockID, ok = voteSet.TwoThirdsMajority() 275 if ok || !blockID.IsZero() { 276 t.Errorf("there should be no 2/3 majority: last vote added had different BlockHash") 277 } 278 } 279 280 // 71st validator voted for the right BlockHash & BlockPartsHeader 281 { 282 pubKey, err := privValidators[70].GetPubKey() 283 require.NoError(t, err) 284 addr := pubKey.Address() 285 vote := withValidator(voteProto, addr, 70) 286 _, err = signAddVote(privValidators[70], vote, voteSet) 287 if err != nil { 288 t.Error(err) 289 } 290 blockID, ok = voteSet.TwoThirdsMajority() 291 if !ok || !blockID.Equals(BlockID{blockHash, blockPartsHeader}) { 292 t.Errorf("there should be 2/3 majority") 293 } 294 } 295 } 296 297 func TestBadVotes(t *testing.T) { 298 height, round := int64(1), 0 299 voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 10, 1) 300 301 voteProto := &Vote{ 302 ValidatorAddress: nil, 303 ValidatorIndex: -1, 304 Height: height, 305 Round: round, 306 Timestamp: tmtime.Now(), 307 Type: PrevoteType, 308 BlockID: BlockID{nil, PartSetHeader{}}, 309 } 310 311 // val0 votes for nil. 312 { 313 pubKey, err := privValidators[0].GetPubKey() 314 require.NoError(t, err) 315 addr := pubKey.Address() 316 vote := withValidator(voteProto, addr, 0) 317 added, err := signAddVote(privValidators[0], vote, voteSet) 318 if !added || err != nil { 319 t.Errorf("expected VoteSet.Add to succeed") 320 } 321 } 322 323 // val0 votes again for some block. 324 { 325 pubKey, err := privValidators[0].GetPubKey() 326 require.NoError(t, err) 327 addr := pubKey.Address() 328 vote := withValidator(voteProto, addr, 0) 329 added, err := signAddVote(privValidators[0], withBlockHash(vote, tmrand.Bytes(32)), voteSet) 330 if added || err == nil { 331 t.Errorf("expected VoteSet.Add to fail, conflicting vote.") 332 } 333 } 334 335 // val1 votes on another height 336 { 337 pubKey, err := privValidators[1].GetPubKey() 338 require.NoError(t, err) 339 addr := pubKey.Address() 340 vote := withValidator(voteProto, addr, 1) 341 added, err := signAddVote(privValidators[1], withHeight(vote, height+1), voteSet) 342 if added || err == nil { 343 t.Errorf("expected VoteSet.Add to fail, wrong height") 344 } 345 } 346 347 // val2 votes on another round 348 { 349 pubKey, err := privValidators[2].GetPubKey() 350 require.NoError(t, err) 351 addr := pubKey.Address() 352 vote := withValidator(voteProto, addr, 2) 353 added, err := signAddVote(privValidators[2], withRound(vote, round+1), voteSet) 354 if added || err == nil { 355 t.Errorf("expected VoteSet.Add to fail, wrong round") 356 } 357 } 358 359 // val3 votes of another type. 360 { 361 pubKey, err := privValidators[3].GetPubKey() 362 require.NoError(t, err) 363 addr := pubKey.Address() 364 vote := withValidator(voteProto, addr, 3) 365 added, err := signAddVote(privValidators[3], withType(vote, byte(PrecommitType)), voteSet) 366 if added || err == nil { 367 t.Errorf("expected VoteSet.Add to fail, wrong type") 368 } 369 } 370 } 371 372 func TestConflicts(t *testing.T) { 373 height, round := int64(1), 0 374 voteSet, _, privValidators := randVoteSet(height, round, PrevoteType, 4, 1) 375 blockHash1 := tmrand.Bytes(32) 376 blockHash2 := tmrand.Bytes(32) 377 378 voteProto := &Vote{ 379 ValidatorAddress: nil, 380 ValidatorIndex: -1, 381 Height: height, 382 Round: round, 383 Timestamp: tmtime.Now(), 384 Type: PrevoteType, 385 BlockID: BlockID{nil, PartSetHeader{}}, 386 } 387 388 val0, err := privValidators[0].GetPubKey() 389 require.NoError(t, err) 390 val0Addr := val0.Address() 391 392 // val0 votes for nil. 393 { 394 vote := withValidator(voteProto, val0Addr, 0) 395 added, err := signAddVote(privValidators[0], vote, voteSet) 396 if !added || err != nil { 397 t.Errorf("expected VoteSet.Add to succeed") 398 } 399 } 400 401 // val0 votes again for blockHash1. 402 { 403 vote := withValidator(voteProto, val0Addr, 0) 404 added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash1), voteSet) 405 if added { 406 t.Errorf("expected VoteSet.Add to fail, conflicting vote.") 407 } 408 if err == nil { 409 t.Errorf("expected VoteSet.Add to return error, conflicting vote.") 410 } 411 } 412 413 // start tracking blockHash1 414 voteSet.SetPeerMaj23("peerA", BlockID{blockHash1, PartSetHeader{}}) 415 416 // val0 votes again for blockHash1. 417 { 418 vote := withValidator(voteProto, val0Addr, 0) 419 added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash1), voteSet) 420 if !added { 421 t.Errorf("expected VoteSet.Add to succeed, called SetPeerMaj23().") 422 } 423 if err == nil { 424 t.Errorf("expected VoteSet.Add to return error, conflicting vote.") 425 } 426 } 427 428 // attempt tracking blockHash2, should fail because already set for peerA. 429 voteSet.SetPeerMaj23("peerA", BlockID{blockHash2, PartSetHeader{}}) 430 431 // val0 votes again for blockHash1. 432 { 433 vote := withValidator(voteProto, val0Addr, 0) 434 added, err := signAddVote(privValidators[0], withBlockHash(vote, blockHash2), voteSet) 435 if added { 436 t.Errorf("expected VoteSet.Add to fail, duplicate SetPeerMaj23() from peerA") 437 } 438 if err == nil { 439 t.Errorf("expected VoteSet.Add to return error, conflicting vote.") 440 } 441 } 442 443 // val1 votes for blockHash1. 444 { 445 pv, err := privValidators[1].GetPubKey() 446 assert.NoError(t, err) 447 addr := pv.Address() 448 vote := withValidator(voteProto, addr, 1) 449 added, err := signAddVote(privValidators[1], withBlockHash(vote, blockHash1), voteSet) 450 if !added || err != nil { 451 t.Errorf("expected VoteSet.Add to succeed") 452 } 453 } 454 455 // check 456 if voteSet.HasTwoThirdsMajority() { 457 t.Errorf("we shouldn't have 2/3 majority yet") 458 } 459 if voteSet.HasTwoThirdsAny() { 460 t.Errorf("we shouldn't have 2/3 if any votes yet") 461 } 462 463 // val2 votes for blockHash2. 464 { 465 pv, err := privValidators[2].GetPubKey() 466 assert.NoError(t, err) 467 addr := pv.Address() 468 vote := withValidator(voteProto, addr, 2) 469 added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash2), voteSet) 470 if !added || err != nil { 471 t.Errorf("expected VoteSet.Add to succeed") 472 } 473 } 474 475 // check 476 if voteSet.HasTwoThirdsMajority() { 477 t.Errorf("we shouldn't have 2/3 majority yet") 478 } 479 if !voteSet.HasTwoThirdsAny() { 480 t.Errorf("we should have 2/3 if any votes") 481 } 482 483 // now attempt tracking blockHash1 484 voteSet.SetPeerMaj23("peerB", BlockID{blockHash1, PartSetHeader{}}) 485 486 // val2 votes for blockHash1. 487 { 488 pv, err := privValidators[2].GetPubKey() 489 assert.NoError(t, err) 490 addr := pv.Address() 491 vote := withValidator(voteProto, addr, 2) 492 added, err := signAddVote(privValidators[2], withBlockHash(vote, blockHash1), voteSet) 493 if !added { 494 t.Errorf("expected VoteSet.Add to succeed") 495 } 496 if err == nil { 497 t.Errorf("expected VoteSet.Add to return error, conflicting vote") 498 } 499 } 500 501 // check 502 if !voteSet.HasTwoThirdsMajority() { 503 t.Errorf("we should have 2/3 majority for blockHash1") 504 } 505 blockIDMaj23, _ := voteSet.TwoThirdsMajority() 506 if !bytes.Equal(blockIDMaj23.Hash, blockHash1) { 507 t.Errorf("got the wrong 2/3 majority blockhash") 508 } 509 if !voteSet.HasTwoThirdsAny() { 510 t.Errorf("we should have 2/3 if any votes") 511 } 512 513 } 514 515 func TestMakeCommit(t *testing.T) { 516 height, round := int64(1), 0 517 voteSet, _, privValidators := randVoteSet(height, round, PrecommitType, 10, 1) 518 blockHash, blockPartsHeader := crypto.CRandBytes(32), PartSetHeader{123, crypto.CRandBytes(32)} 519 520 voteProto := &Vote{ 521 ValidatorAddress: nil, 522 ValidatorIndex: -1, 523 Height: height, 524 Round: round, 525 Timestamp: tmtime.Now(), 526 Type: PrecommitType, 527 BlockID: BlockID{blockHash, blockPartsHeader}, 528 } 529 530 // 6 out of 10 voted for some block. 531 for i := 0; i < 6; i++ { 532 pv, err := privValidators[i].GetPubKey() 533 assert.NoError(t, err) 534 addr := pv.Address() 535 vote := withValidator(voteProto, addr, i) 536 _, err = signAddVote(privValidators[i], vote, voteSet) 537 if err != nil { 538 t.Error(err) 539 } 540 } 541 542 // MakeCommit should fail. 543 assert.Panics(t, func() { voteSet.MakeCommit() }, "Doesn't have +2/3 majority") 544 545 // 7th voted for some other block. 546 { 547 pv, err := privValidators[6].GetPubKey() 548 assert.NoError(t, err) 549 addr := pv.Address() 550 vote := withValidator(voteProto, addr, 6) 551 vote = withBlockHash(vote, tmrand.Bytes(32)) 552 vote = withBlockPartsHeader(vote, PartSetHeader{123, tmrand.Bytes(32)}) 553 554 _, err = signAddVote(privValidators[6], vote, voteSet) 555 if err != nil { 556 t.Error(err) 557 } 558 } 559 560 // The 8th voted like everyone else. 561 { 562 pv, err := privValidators[7].GetPubKey() 563 assert.NoError(t, err) 564 addr := pv.Address() 565 vote := withValidator(voteProto, addr, 7) 566 _, err = signAddVote(privValidators[7], vote, voteSet) 567 if err != nil { 568 t.Error(err) 569 } 570 } 571 572 // The 9th voted for nil. 573 { 574 pv, err := privValidators[8].GetPubKey() 575 assert.NoError(t, err) 576 addr := pv.Address() 577 vote := withValidator(voteProto, addr, 8) 578 vote.BlockID = BlockID{} 579 580 _, err = signAddVote(privValidators[8], vote, voteSet) 581 if err != nil { 582 t.Error(err) 583 } 584 } 585 586 commit := voteSet.MakeCommit() 587 588 // Commit should have 10 elements 589 if len(commit.Precommits) != 10 { 590 t.Errorf("expected commit to include %d elems, got %d", 10, len(commit.Precommits)) 591 } 592 593 // Ensure that Commit is good. 594 if err := commit.ValidateBasic(); err != nil { 595 t.Errorf("error in Commit.ValidateBasic(): %v", err) 596 } 597 }