github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/types/block_test.go (about) 1 package types 2 3 import ( 4 // it is ok to use math/rand here: we do not need a cryptographically secure random 5 // number generator here and we can run the tests a bit faster 6 "crypto/rand" 7 "encoding/hex" 8 "math" 9 "os" 10 "reflect" 11 "testing" 12 "time" 13 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 17 "github.com/tendermint/tendermint/crypto" 18 "github.com/tendermint/tendermint/crypto/merkle" 19 "github.com/tendermint/tendermint/crypto/tmhash" 20 "github.com/tendermint/tendermint/libs/bits" 21 "github.com/tendermint/tendermint/libs/bytes" 22 tmrand "github.com/tendermint/tendermint/libs/rand" 23 tmtime "github.com/tendermint/tendermint/types/time" 24 "github.com/tendermint/tendermint/version" 25 ) 26 27 func TestMain(m *testing.M) { 28 RegisterMockEvidences(cdc) 29 30 code := m.Run() 31 os.Exit(code) 32 } 33 34 func TestBlockAddEvidence(t *testing.T) { 35 txs := []Tx{Tx("foo"), Tx("bar")} 36 lastID := makeBlockIDRandom() 37 h := int64(3) 38 39 voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 40 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 41 require.NoError(t, err) 42 43 ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address) 44 evList := []Evidence{ev} 45 46 block := MakeBlock(h, txs, commit, evList) 47 require.NotNil(t, block) 48 require.Equal(t, 1, len(block.Evidence.Evidence)) 49 require.NotNil(t, block.EvidenceHash) 50 } 51 52 func TestBlockValidateBasic(t *testing.T) { 53 require.Error(t, (*Block)(nil).ValidateBasic()) 54 55 txs := []Tx{Tx("foo"), Tx("bar")} 56 lastID := makeBlockIDRandom() 57 h := int64(3) 58 59 voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 60 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 61 require.NoError(t, err) 62 63 ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address) 64 evList := []Evidence{ev} 65 66 testCases := []struct { 67 testName string 68 malleateBlock func(*Block) 69 expErr bool 70 }{ 71 {"Make Block", func(blk *Block) {}, false}, 72 {"Make Block w/ proposer Addr", func(blk *Block) { blk.ProposerAddress = valSet.GetProposer().Address }, false}, 73 {"Negative Height", func(blk *Block) { blk.Height = -1 }, true}, 74 {"Increase NumTxs", func(blk *Block) { blk.NumTxs++ }, true}, 75 {"Remove 1/2 the commits", func(blk *Block) { 76 blk.LastCommit.Precommits = commit.Precommits[:commit.Size()/2] 77 blk.LastCommit.hash = nil // clear hash or change wont be noticed 78 }, true}, 79 {"Remove LastCommitHash", func(blk *Block) { blk.LastCommitHash = []byte("something else") }, true}, 80 {"Tampered Data", func(blk *Block) { 81 blk.Data.Txs[0] = Tx("something else") 82 blk.Data.hash = nil // clear hash or change wont be noticed 83 }, true}, 84 {"Tampered DataHash", func(blk *Block) { 85 blk.DataHash = tmrand.Bytes(len(blk.DataHash)) 86 }, true}, 87 {"Tampered EvidenceHash", func(blk *Block) { 88 blk.EvidenceHash = []byte("something else") 89 }, true}, 90 } 91 for i, tc := range testCases { 92 tc := tc 93 i := i 94 t.Run(tc.testName, func(t *testing.T) { 95 block := MakeBlock(h, txs, commit, evList) 96 block.ProposerAddress = valSet.GetProposer().Address 97 tc.malleateBlock(block) 98 err = block.ValidateBasic() 99 assert.Equal(t, tc.expErr, err != nil, "#%d: %v", i, err) 100 }) 101 } 102 } 103 104 func TestBlockHash(t *testing.T) { 105 assert.Nil(t, (*Block)(nil).Hash()) 106 assert.Nil(t, MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).Hash()) 107 } 108 109 func TestBlockMakePartSet(t *testing.T) { 110 assert.Nil(t, (*Block)(nil).MakePartSet(2)) 111 112 partSet := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).MakePartSet(1024) 113 assert.NotNil(t, partSet) 114 assert.Equal(t, 1, partSet.Total()) 115 } 116 117 func TestBlockMakePartSetWithEvidence(t *testing.T) { 118 assert.Nil(t, (*Block)(nil).MakePartSet(2)) 119 120 lastID := makeBlockIDRandom() 121 h := int64(3) 122 123 voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 124 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 125 require.NoError(t, err) 126 127 ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address) 128 evList := []Evidence{ev} 129 130 partSet := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(1024) 131 assert.NotNil(t, partSet) 132 assert.Equal(t, 3, partSet.Total()) 133 } 134 135 func TestBlockHashesTo(t *testing.T) { 136 assert.False(t, (*Block)(nil).HashesTo(nil)) 137 138 lastID := makeBlockIDRandom() 139 h := int64(3) 140 voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 141 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 142 require.NoError(t, err) 143 144 ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address) 145 evList := []Evidence{ev} 146 147 block := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList) 148 block.ValidatorsHash = valSet.Hash() 149 assert.False(t, block.HashesTo([]byte{})) 150 assert.False(t, block.HashesTo([]byte("something else"))) 151 assert.True(t, block.HashesTo(block.Hash())) 152 } 153 154 func TestBlockSize(t *testing.T) { 155 size := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).Size() 156 if size <= 0 { 157 t.Fatal("Size of the block is zero or negative") 158 } 159 } 160 161 func TestBlockString(t *testing.T) { 162 assert.Equal(t, "nil-Block", (*Block)(nil).String()) 163 assert.Equal(t, "nil-Block", (*Block)(nil).StringIndented("")) 164 assert.Equal(t, "nil-Block", (*Block)(nil).StringShort()) 165 166 block := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil) 167 assert.NotEqual(t, "nil-Block", block.String()) 168 assert.NotEqual(t, "nil-Block", block.StringIndented("")) 169 assert.NotEqual(t, "nil-Block", block.StringShort()) 170 } 171 172 func makeBlockIDRandom() BlockID { 173 var ( 174 blockHash = make([]byte, tmhash.Size) 175 partSetHash = make([]byte, tmhash.Size) 176 ) 177 rand.Read(blockHash) //nolint: gosec 178 rand.Read(partSetHash) //nolint: gosec 179 return BlockID{blockHash, PartSetHeader{123, partSetHash}} 180 } 181 182 func makeBlockID(hash []byte, partSetSize int, partSetHash []byte) BlockID { 183 var ( 184 h = make([]byte, tmhash.Size) 185 psH = make([]byte, tmhash.Size) 186 ) 187 copy(h, hash) 188 copy(psH, partSetHash) 189 return BlockID{ 190 Hash: h, 191 PartsHeader: PartSetHeader{ 192 Total: partSetSize, 193 Hash: psH, 194 }, 195 } 196 } 197 198 var nilBytes []byte 199 200 func TestNilHeaderHashDoesntCrash(t *testing.T) { 201 assert.Equal(t, []byte((*Header)(nil).Hash()), nilBytes) 202 assert.Equal(t, []byte((new(Header)).Hash()), nilBytes) 203 } 204 205 func TestNilDataHashDoesntCrash(t *testing.T) { 206 assert.Equal(t, []byte((*Data)(nil).Hash()), nilBytes) 207 assert.Equal(t, []byte(new(Data).Hash()), nilBytes) 208 } 209 210 func TestCommit(t *testing.T) { 211 lastID := makeBlockIDRandom() 212 h := int64(3) 213 voteSet, _, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 214 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 215 require.NoError(t, err) 216 217 assert.Equal(t, h-1, commit.Height()) 218 assert.Equal(t, 1, commit.Round()) 219 assert.Equal(t, PrecommitType, SignedMsgType(commit.Type())) 220 if commit.Size() <= 0 { 221 t.Fatalf("commit %v has a zero or negative size: %d", commit, commit.Size()) 222 } 223 224 require.NotNil(t, commit.BitArray()) 225 assert.Equal(t, bits.NewBitArray(10).Size(), commit.BitArray().Size()) 226 227 assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0)) 228 assert.True(t, commit.IsCommit()) 229 } 230 231 func TestCommitValidateBasic(t *testing.T) { 232 testCases := []struct { 233 testName string 234 malleateCommit func(*Commit) 235 expectErr bool 236 }{ 237 {"Random Commit", func(com *Commit) {}, false}, 238 {"Nil precommit", func(com *Commit) { com.Precommits[0] = nil }, false}, 239 {"Incorrect signature", func(com *Commit) { com.Precommits[0].Signature = []byte{0} }, false}, 240 {"Incorrect type", func(com *Commit) { com.Precommits[0].Type = PrevoteType }, true}, 241 {"Incorrect height", func(com *Commit) { com.Precommits[0].Height = int64(100) }, true}, 242 {"Incorrect round", func(com *Commit) { com.Precommits[0].Round = 100 }, true}, 243 } 244 for _, tc := range testCases { 245 tc := tc 246 t.Run(tc.testName, func(t *testing.T) { 247 com := randCommit(time.Now()) 248 tc.malleateCommit(com) 249 assert.Equal(t, tc.expectErr, com.ValidateBasic() != nil, "Validate Basic had an unexpected result") 250 }) 251 } 252 } 253 254 func TestHeaderHash(t *testing.T) { 255 testCases := []struct { 256 desc string 257 header *Header 258 expectHash bytes.HexBytes 259 }{ 260 {"Generates expected hash", &Header{ 261 Version: version.Consensus{Block: 1, App: 2}, 262 ChainID: "chainId", 263 Height: 3, 264 Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC), 265 NumTxs: 4, 266 TotalTxs: 5, 267 LastBlockID: makeBlockID(make([]byte, tmhash.Size), 6, make([]byte, tmhash.Size)), 268 LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), 269 DataHash: tmhash.Sum([]byte("data_hash")), 270 ValidatorsHash: tmhash.Sum([]byte("validators_hash")), 271 NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), 272 ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 273 AppHash: tmhash.Sum([]byte("app_hash")), 274 LastResultsHash: tmhash.Sum([]byte("last_results_hash")), 275 EvidenceHash: tmhash.Sum([]byte("evidence_hash")), 276 ProposerAddress: crypto.AddressHash([]byte("proposer_address")), 277 }, hexBytesFromString("A37A7A69D89D3A66D599B0914A53F959EFE490EE9B449C95852F6FB331D58D07")}, 278 {"nil header yields nil", nil, nil}, 279 {"nil ValidatorsHash yields nil", &Header{ 280 Version: version.Consensus{Block: 1, App: 2}, 281 ChainID: "chainId", 282 Height: 3, 283 Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC), 284 NumTxs: 4, 285 TotalTxs: 5, 286 LastBlockID: makeBlockID(make([]byte, tmhash.Size), 6, make([]byte, tmhash.Size)), 287 LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), 288 DataHash: tmhash.Sum([]byte("data_hash")), 289 ValidatorsHash: nil, 290 NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), 291 ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 292 AppHash: tmhash.Sum([]byte("app_hash")), 293 LastResultsHash: tmhash.Sum([]byte("last_results_hash")), 294 EvidenceHash: tmhash.Sum([]byte("evidence_hash")), 295 ProposerAddress: crypto.AddressHash([]byte("proposer_address")), 296 }, nil}, 297 } 298 for _, tc := range testCases { 299 tc := tc 300 t.Run(tc.desc, func(t *testing.T) { 301 assert.Equal(t, tc.expectHash, tc.header.Hash()) 302 303 // We also make sure that all fields are hashed in struct order, and that all 304 // fields in the test struct are non-zero. 305 if tc.header != nil && tc.expectHash != nil { 306 byteSlices := [][]byte{} 307 s := reflect.ValueOf(*tc.header) 308 for i := 0; i < s.NumField(); i++ { 309 f := s.Field(i) 310 assert.False(t, f.IsZero(), "Found zero-valued field %v", 311 s.Type().Field(i).Name) 312 byteSlices = append(byteSlices, cdcEncode(f.Interface())) 313 } 314 assert.Equal(t, 315 bytes.HexBytes(merkle.SimpleHashFromByteSlices(byteSlices)), tc.header.Hash()) 316 } 317 }) 318 } 319 } 320 321 func TestMaxHeaderBytes(t *testing.T) { 322 // Construct a UTF-8 string of MaxChainIDLen length using the supplementary 323 // characters. 324 // Each supplementary character takes 4 bytes. 325 // http://www.i18nguy.com/unicode/supplementary-test.html 326 maxChainID := "" 327 for i := 0; i < MaxChainIDLen; i++ { 328 maxChainID += "𠜎" 329 } 330 331 // time is varint encoded so need to pick the max. 332 // year int, month Month, day, hour, min, sec, nsec int, loc *Location 333 timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) 334 335 h := Header{ 336 Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64}, 337 ChainID: maxChainID, 338 Height: math.MaxInt64, 339 Time: timestamp, 340 NumTxs: math.MaxInt64, 341 TotalTxs: math.MaxInt64, 342 LastBlockID: makeBlockID(make([]byte, tmhash.Size), math.MaxInt64, make([]byte, tmhash.Size)), 343 LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), 344 DataHash: tmhash.Sum([]byte("data_hash")), 345 ValidatorsHash: tmhash.Sum([]byte("validators_hash")), 346 NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), 347 ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 348 AppHash: tmhash.Sum([]byte("app_hash")), 349 LastResultsHash: tmhash.Sum([]byte("last_results_hash")), 350 EvidenceHash: tmhash.Sum([]byte("evidence_hash")), 351 ProposerAddress: crypto.AddressHash([]byte("proposer_address")), 352 } 353 354 bz, err := cdc.MarshalBinaryLengthPrefixed(h) 355 require.NoError(t, err) 356 357 assert.EqualValues(t, MaxHeaderBytes, int64(len(bz))) 358 } 359 360 func randCommit(now time.Time) *Commit { 361 lastID := makeBlockIDRandom() 362 h := int64(3) 363 voteSet, _, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 364 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, now) 365 if err != nil { 366 panic(err) 367 } 368 commit.memoizeHeightRound() 369 return commit 370 } 371 372 func hexBytesFromString(s string) bytes.HexBytes { 373 b, err := hex.DecodeString(s) 374 if err != nil { 375 panic(err) 376 } 377 return bytes.HexBytes(b) 378 } 379 380 func TestBlockMaxDataBytes(t *testing.T) { 381 testCases := []struct { 382 maxBytes int64 383 valsCount int 384 evidenceCount int 385 panics bool 386 result int64 387 }{ 388 0: {-10, 1, 0, true, 0}, 389 1: {10, 1, 0, true, 0}, 390 2: {886, 1, 0, true, 0}, 391 3: {887, 1, 0, false, 0}, 392 4: {888, 1, 0, false, 1}, 393 } 394 395 for i, tc := range testCases { 396 tc := tc 397 if tc.panics { 398 assert.Panics(t, func() { 399 MaxDataBytes(tc.maxBytes, tc.valsCount, tc.evidenceCount) 400 }, "#%v", i) 401 } else { 402 assert.Equal(t, 403 tc.result, 404 MaxDataBytes(tc.maxBytes, tc.valsCount, tc.evidenceCount), 405 "#%v", i) 406 } 407 } 408 } 409 410 func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) { 411 testCases := []struct { 412 maxBytes int64 413 valsCount int 414 panics bool 415 result int64 416 }{ 417 0: {-10, 1, true, 0}, 418 1: {10, 1, true, 0}, 419 2: {984, 1, true, 0}, 420 3: {985, 1, false, 0}, 421 4: {986, 1, false, 1}, 422 } 423 424 for i, tc := range testCases { 425 tc := tc 426 if tc.panics { 427 assert.Panics(t, func() { 428 MaxDataBytesUnknownEvidence(tc.maxBytes, tc.valsCount) 429 }, "#%v", i) 430 } else { 431 assert.Equal(t, 432 tc.result, 433 MaxDataBytesUnknownEvidence(tc.maxBytes, tc.valsCount), 434 "#%v", i) 435 } 436 } 437 } 438 439 func TestCommitToVoteSet(t *testing.T) { 440 lastID := makeBlockIDRandom() 441 h := int64(3) 442 443 voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 444 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 445 assert.NoError(t, err) 446 447 chainID := voteSet.ChainID() 448 voteSet2 := CommitToVoteSet(chainID, commit, valSet) 449 450 for i := 0; i < len(vals); i++ { 451 vote1 := voteSet.GetByIndex(i) 452 vote2 := voteSet2.GetByIndex(i) 453 vote3 := commit.GetVote(i) 454 455 vote1bz := cdc.MustMarshalBinaryBare(vote1) 456 vote2bz := cdc.MustMarshalBinaryBare(vote2) 457 vote3bz := cdc.MustMarshalBinaryBare(vote3) 458 assert.Equal(t, vote1bz, vote2bz) 459 assert.Equal(t, vote1bz, vote3bz) 460 } 461 } 462 463 func TestCommitToVoteSetWithVotesForNilBlock(t *testing.T) { 464 blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash")) 465 blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash")) 466 blockID3 := makeBlockID([]byte("blockhash3"), 10000, []byte("partshash")) 467 468 const ( 469 height = int64(3) 470 round = 0 471 ) 472 473 type commitVoteTest struct { 474 blockIDs []BlockID 475 numVotes []int // must sum to numValidators 476 numValidators int 477 valid bool 478 } 479 480 testCases := []commitVoteTest{ 481 {[]BlockID{blockID, blockID2, blockID3}, []int{8, 1, 1}, 10, true}, 482 {[]BlockID{blockID, blockID2, blockID3}, []int{67, 20, 13}, 100, true}, 483 {[]BlockID{blockID, blockID2, blockID3}, []int{1, 1, 1}, 3, false}, 484 {[]BlockID{blockID, blockID2, blockID3}, []int{3, 1, 1}, 5, false}, 485 {[]BlockID{blockID, {}}, []int{67, 33}, 100, true}, 486 {[]BlockID{blockID, blockID2, {}}, []int{10, 5, 5}, 20, false}, 487 } 488 489 for _, tc := range testCases { 490 voteSet, valSet, vals := randVoteSet(height-1, round, PrecommitType, tc.numValidators, 1) 491 492 vi := 0 493 for n := range tc.blockIDs { 494 for i := 0; i < tc.numVotes[n]; i++ { 495 pubKey, err := vals[vi].GetPubKey() 496 require.NoError(t, err) 497 vote := &Vote{ 498 ValidatorAddress: pubKey.Address(), 499 ValidatorIndex: vi, 500 Height: height - 1, 501 Round: round, 502 Type: PrecommitType, 503 BlockID: tc.blockIDs[n], 504 Timestamp: tmtime.Now(), 505 } 506 507 added, err := signAddVote(vals[vi], vote, voteSet) 508 assert.NoError(t, err) 509 assert.True(t, added) 510 511 vi++ 512 } 513 } 514 515 if tc.valid { 516 commit := voteSet.MakeCommit() // panics without > 2/3 valid votes 517 assert.NotNil(t, commit) 518 err := valSet.VerifyCommit(voteSet.ChainID(), blockID, height-1, commit) 519 assert.Nil(t, err) 520 } else { 521 assert.Panics(t, func() { voteSet.MakeCommit() }) 522 } 523 } 524 } 525 526 func TestSignedHeaderValidateBasic(t *testing.T) { 527 commit := randCommit(time.Now()) 528 chainID := "𠜎" 529 timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) 530 h := Header{ 531 Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64}, 532 ChainID: chainID, 533 Height: commit.Height(), 534 Time: timestamp, 535 NumTxs: math.MaxInt64, 536 TotalTxs: math.MaxInt64, 537 LastBlockID: commit.BlockID, 538 LastCommitHash: commit.Hash(), 539 DataHash: commit.Hash(), 540 ValidatorsHash: commit.Hash(), 541 NextValidatorsHash: commit.Hash(), 542 ConsensusHash: commit.Hash(), 543 AppHash: commit.Hash(), 544 LastResultsHash: commit.Hash(), 545 EvidenceHash: commit.Hash(), 546 ProposerAddress: crypto.AddressHash([]byte("proposer_address")), 547 } 548 549 validSignedHeader := SignedHeader{Header: &h, Commit: commit} 550 validSignedHeader.Commit.BlockID.Hash = validSignedHeader.Hash() 551 invalidSignedHeader := SignedHeader{} 552 553 testCases := []struct { 554 testName string 555 shHeader *Header 556 shCommit *Commit 557 expectErr bool 558 }{ 559 {"Valid Signed Header", validSignedHeader.Header, validSignedHeader.Commit, false}, 560 {"Invalid Signed Header", invalidSignedHeader.Header, validSignedHeader.Commit, true}, 561 {"Invalid Signed Header", validSignedHeader.Header, invalidSignedHeader.Commit, true}, 562 } 563 564 for _, tc := range testCases { 565 tc := tc 566 t.Run(tc.testName, func(t *testing.T) { 567 sh := SignedHeader{ 568 Header: tc.shHeader, 569 Commit: tc.shCommit, 570 } 571 assert.Equal( 572 t, 573 tc.expectErr, 574 sh.ValidateBasic(validSignedHeader.Header.ChainID) != nil, 575 "Validate Basic had an unexpected result", 576 ) 577 }) 578 } 579 } 580 581 func TestBlockIDValidateBasic(t *testing.T) { 582 validBlockID := BlockID{ 583 Hash: bytes.HexBytes{}, 584 PartsHeader: PartSetHeader{ 585 Total: 1, 586 Hash: bytes.HexBytes{}, 587 }, 588 } 589 590 invalidBlockID := BlockID{ 591 Hash: []byte{0}, 592 PartsHeader: PartSetHeader{ 593 Total: -1, 594 Hash: bytes.HexBytes{}, 595 }, 596 } 597 598 testCases := []struct { 599 testName string 600 blockIDHash bytes.HexBytes 601 blockIDPartsHeader PartSetHeader 602 expectErr bool 603 }{ 604 {"Valid BlockID", validBlockID.Hash, validBlockID.PartsHeader, false}, 605 {"Invalid BlockID", invalidBlockID.Hash, validBlockID.PartsHeader, true}, 606 {"Invalid BlockID", validBlockID.Hash, invalidBlockID.PartsHeader, true}, 607 } 608 609 for _, tc := range testCases { 610 tc := tc 611 t.Run(tc.testName, func(t *testing.T) { 612 blockID := BlockID{ 613 Hash: tc.blockIDHash, 614 PartsHeader: tc.blockIDPartsHeader, 615 } 616 assert.Equal(t, tc.expectErr, blockID.ValidateBasic() != nil, "Validate Basic had an unexpected result") 617 }) 618 } 619 } 620 621 func makeRandHeader() Header { 622 chainID := "test" 623 t := time.Now() 624 height := tmrand.Int63() 625 randBytes := tmrand.Bytes(tmhash.Size) 626 randAddress := tmrand.Bytes(crypto.AddressSize) 627 h := Header{ 628 Version: version.Consensus{Block: 1, App: 1}, 629 ChainID: chainID, 630 Height: height, 631 Time: t, 632 LastBlockID: BlockID{}, 633 LastCommitHash: randBytes, 634 DataHash: randBytes, 635 ValidatorsHash: randBytes, 636 NextValidatorsHash: randBytes, 637 ConsensusHash: randBytes, 638 AppHash: randBytes, 639 640 LastResultsHash: randBytes, 641 642 EvidenceHash: randBytes, 643 ProposerAddress: randAddress, 644 } 645 646 return h 647 } 648 649 func TestHeaderProto(t *testing.T) { 650 h1 := makeRandHeader() 651 tc := []struct { 652 msg string 653 h1 *Header 654 expPass bool 655 }{ 656 {"success", &h1, true}, 657 {"failure empty Header", &Header{}, false}, 658 } 659 660 for _, tt := range tc { 661 tt := tt 662 t.Run(tt.msg, func(t *testing.T) { 663 pb := tt.h1.ToProto() 664 h, err := HeaderFromProto(pb) 665 if tt.expPass { 666 require.NoError(t, err, tt.msg) 667 require.Equal(t, tt.h1, &h, tt.msg) 668 } else { 669 require.Error(t, err, tt.msg) 670 } 671 672 }) 673 } 674 } 675 676 func TestBlockIDProtoBuf(t *testing.T) { 677 blockID := makeBlockID([]byte("hash"), 2, []byte("part_set_hash")) 678 testCases := []struct { 679 msg string 680 bid1 *BlockID 681 expPass bool 682 }{ 683 {"success", &blockID, true}, 684 {"success empty", &BlockID{}, true}, 685 {"failure BlockID nil", nil, false}, 686 } 687 for _, tc := range testCases { 688 protoBlockID := tc.bid1.ToProto() 689 690 bi, err := BlockIDFromProto(&protoBlockID) 691 if tc.expPass { 692 require.NoError(t, err) 693 require.Equal(t, tc.bid1, bi, tc.msg) 694 } else { 695 require.NotEqual(t, tc.bid1, bi, tc.msg) 696 } 697 } 698 } 699 700 func TestSignedHeaderProtoBuf(t *testing.T) { 701 commit := randCommit(time.Now()) 702 h := makeRandHeader() 703 704 sh := SignedHeader{Header: &h, Commit: commit} 705 706 testCases := []struct { 707 msg string 708 sh1 *SignedHeader 709 expPass bool 710 }{ 711 {"empty SignedHeader 2", &SignedHeader{}, true}, 712 {"success", &sh, true}, 713 {"failure nil", nil, false}, 714 } 715 for _, tc := range testCases { 716 protoSignedHeader := tc.sh1.ToProto() 717 718 sh, err := SignedHeaderFromProto(protoSignedHeader) 719 720 if tc.expPass { 721 require.NoError(t, err, tc.msg) 722 require.Equal(t, tc.sh1, sh, tc.msg) 723 } else { 724 require.Error(t, err, tc.msg) 725 } 726 } 727 } 728 729 func TestCommitProtoBuf(t *testing.T) { 730 commit := randCommit(time.Now()) 731 732 testCases := []struct { 733 msg string 734 c1 *Commit 735 expPass bool 736 }{ 737 {"success", commit, true}, 738 // Empty value sets signatures to nil, signatures should not be nillable 739 {"empty commit", &Commit{Precommits: []*CommitSig{}}, true}, 740 {"fail Commit nil", nil, false}, 741 } 742 for _, tc := range testCases { 743 tc := tc 744 protoCommit := tc.c1.ToProto() 745 746 c, err := CommitFromProto(protoCommit) 747 748 if tc.expPass { 749 require.NoError(t, err, tc.msg) 750 require.Equal(t, tc.c1, c, tc.msg) 751 } else { 752 require.Error(t, err, tc.msg) 753 } 754 } 755 }