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