github.com/okex/exchain@v1.8.0/libs/tendermint/types/block_test.go (about) 1 package types 2 3 import ( 4 stdbytes "bytes" 5 // it is ok to use math/rand here: we do not need a cryptographically secure random 6 // number generator here and we can run the tests a bit faster 7 "crypto/rand" 8 "encoding/hex" 9 "fmt" 10 "io" 11 "math" 12 "os" 13 "reflect" 14 "testing" 15 "time" 16 17 "github.com/stretchr/testify/assert" 18 "github.com/stretchr/testify/require" 19 20 "github.com/okex/exchain/libs/tendermint/crypto" 21 "github.com/okex/exchain/libs/tendermint/crypto/merkle" 22 "github.com/okex/exchain/libs/tendermint/crypto/tmhash" 23 "github.com/okex/exchain/libs/tendermint/libs/bits" 24 "github.com/okex/exchain/libs/tendermint/libs/bytes" 25 tmrand "github.com/okex/exchain/libs/tendermint/libs/rand" 26 tmtime "github.com/okex/exchain/libs/tendermint/types/time" 27 "github.com/okex/exchain/libs/tendermint/version" 28 ) 29 30 func TestMain(m *testing.M) { 31 RegisterMockEvidences(cdc) 32 33 code := m.Run() 34 os.Exit(code) 35 } 36 37 func TestBlockAddEvidence(t *testing.T) { 38 txs := []Tx{Tx("foo"), Tx("bar")} 39 lastID := makeBlockIDRandom() 40 h := int64(3) 41 42 voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 43 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 44 require.NoError(t, err) 45 46 ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address) 47 evList := []Evidence{ev} 48 49 block := MakeBlock(h, txs, commit, evList) 50 require.NotNil(t, block) 51 require.Equal(t, 1, len(block.Evidence.Evidence)) 52 require.NotNil(t, block.EvidenceHash) 53 } 54 55 func TestBlockValidateBasic(t *testing.T) { 56 require.Error(t, (*Block)(nil).ValidateBasic()) 57 58 txs := []Tx{Tx("foo"), Tx("bar")} 59 lastID := makeBlockIDRandom() 60 h := int64(3) 61 62 voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 63 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 64 require.NoError(t, err) 65 66 ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address) 67 evList := []Evidence{ev} 68 69 testCases := []struct { 70 testName string 71 malleateBlock func(*Block) 72 expErr bool 73 }{ 74 {"Make Block", func(blk *Block) {}, false}, 75 {"Make Block w/ proposer Addr", func(blk *Block) { blk.ProposerAddress = valSet.GetProposer().Address }, false}, 76 {"Negative Height", func(blk *Block) { blk.Height = -1 }, true}, 77 {"Remove 1/2 the commits", func(blk *Block) { 78 blk.LastCommit.Signatures = commit.Signatures[:commit.Size()/2] 79 blk.LastCommit.hash = nil // clear hash or change wont be noticed 80 }, true}, 81 {"Remove LastCommitHash", func(blk *Block) { blk.LastCommitHash = []byte("something else") }, true}, 82 {"Tampered Data", func(blk *Block) { 83 blk.Data.Txs[0] = Tx("something else") 84 blk.Data.hash = nil // clear hash or change wont be noticed 85 }, true}, 86 {"Tampered DataHash", func(blk *Block) { 87 blk.DataHash = tmrand.Bytes(len(blk.DataHash)) 88 }, true}, 89 {"Tampered EvidenceHash", func(blk *Block) { 90 blk.EvidenceHash = []byte("something else") 91 }, true}, 92 } 93 for i, tc := range testCases { 94 tc := tc 95 i := i 96 t.Run(tc.testName, func(t *testing.T) { 97 block := MakeBlock(h, txs, commit, evList) 98 block.ProposerAddress = valSet.GetProposer().Address 99 tc.malleateBlock(block) 100 err = block.ValidateBasic() 101 assert.Equal(t, tc.expErr, err != nil, "#%d: %v", i, err) 102 }) 103 } 104 } 105 106 func TestBlockHash(t *testing.T) { 107 assert.Nil(t, (*Block)(nil).Hash()) 108 assert.Nil(t, MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).Hash()) 109 } 110 111 func TestBlockMakePartSet(t *testing.T) { 112 assert.Nil(t, (*Block)(nil).MakePartSet(2)) 113 114 partSet := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).MakePartSet(1024) 115 assert.NotNil(t, partSet) 116 assert.Equal(t, 1, partSet.Total()) 117 } 118 119 func TestBlock_MakePartSetByExInfo(t *testing.T) { 120 assert.Nil(t, (*Block)(nil).MakePartSetByExInfo(nil)) 121 block := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil) 122 assert.NotNil(t, block.MakePartSetByExInfo(nil)) 123 124 partSet := block.MakePartSetByExInfo(&BlockExInfo{BlockPartSize: 1024}) 125 assert.NotNil(t, partSet) 126 assert.Equal(t, 1, partSet.Total()) 127 128 partSet = block.MakePartSetByExInfo(&BlockExInfo{BlockPartSize: 1024, BlockCompressType: 2, BlockCompressFlag: 0}) 129 assert.NotNil(t, partSet) 130 assert.Equal(t, 1, partSet.Total()) 131 } 132 133 func TestBlockMakePartSetWithEvidence(t *testing.T) { 134 assert.Nil(t, (*Block)(nil).MakePartSet(2)) 135 136 lastID := makeBlockIDRandom() 137 h := int64(3) 138 139 voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 140 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 141 require.NoError(t, err) 142 143 ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address) 144 evList := []Evidence{ev} 145 146 partSet := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList).MakePartSet(512) 147 assert.NotNil(t, partSet) 148 assert.Equal(t, 3, partSet.Total()) 149 } 150 151 func TestBlockHashesTo(t *testing.T) { 152 assert.False(t, (*Block)(nil).HashesTo(nil)) 153 154 lastID := makeBlockIDRandom() 155 h := int64(3) 156 voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 157 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 158 require.NoError(t, err) 159 160 ev := NewMockEvidence(h, time.Now(), 0, valSet.Validators[0].Address) 161 evList := []Evidence{ev} 162 163 block := MakeBlock(h, []Tx{Tx("Hello World")}, commit, evList) 164 block.ValidatorsHash = valSet.Hash(block.Height) 165 assert.False(t, block.HashesTo([]byte{})) 166 assert.False(t, block.HashesTo([]byte("something else"))) 167 assert.True(t, block.HashesTo(block.Hash())) 168 } 169 170 func TestBlockSize(t *testing.T) { 171 size := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil).Size() 172 if size <= 0 { 173 t.Fatal("Size of the block is zero or negative") 174 } 175 } 176 177 func TestBlockString(t *testing.T) { 178 assert.Equal(t, "nil-Block", (*Block)(nil).String()) 179 assert.Equal(t, "nil-Block", (*Block)(nil).StringIndented("")) 180 assert.Equal(t, "nil-Block", (*Block)(nil).StringShort()) 181 182 block := MakeBlock(int64(3), []Tx{Tx("Hello World")}, nil, nil) 183 assert.NotEqual(t, "nil-Block", block.String()) 184 assert.NotEqual(t, "nil-Block", block.StringIndented("")) 185 assert.NotEqual(t, "nil-Block", block.StringShort()) 186 } 187 188 func makeBlockIDRandom() BlockID { 189 var ( 190 blockHash = make([]byte, tmhash.Size) 191 partSetHash = make([]byte, tmhash.Size) 192 ) 193 rand.Read(blockHash) //nolint: gosec 194 rand.Read(partSetHash) //nolint: gosec 195 return BlockID{blockHash, PartSetHeader{123, partSetHash}} 196 } 197 198 func makeBlockID(hash []byte, partSetSize int, partSetHash []byte) BlockID { 199 var ( 200 h = make([]byte, tmhash.Size) 201 psH = make([]byte, tmhash.Size) 202 ) 203 copy(h, hash) 204 copy(psH, partSetHash) 205 return BlockID{ 206 Hash: h, 207 PartsHeader: PartSetHeader{ 208 Total: partSetSize, 209 Hash: psH, 210 }, 211 } 212 } 213 214 var nilBytes []byte 215 216 func TestNilHeaderHashDoesntCrash(t *testing.T) { 217 assert.Equal(t, []byte((*Header)(nil).Hash()), nilBytes) 218 assert.Equal(t, []byte((new(Header)).Hash()), nilBytes) 219 } 220 221 func TestNilDataHashDoesntCrash(t *testing.T) { 222 assert.Equal(t, []byte((*Data)(nil).Hash(0)), nilBytes) 223 assert.Equal(t, []byte(new(Data).Hash(0)), nilBytes) 224 } 225 226 func TestCommit(t *testing.T) { 227 lastID := makeBlockIDRandom() 228 h := int64(3) 229 voteSet, _, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 230 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 231 require.NoError(t, err) 232 233 assert.Equal(t, h-1, commit.Height) 234 assert.Equal(t, 1, commit.Round) 235 assert.Equal(t, PrecommitType, SignedMsgType(commit.Type())) 236 if commit.Size() <= 0 { 237 t.Fatalf("commit %v has a zero or negative size: %d", commit, commit.Size()) 238 } 239 240 require.NotNil(t, commit.BitArray()) 241 assert.Equal(t, bits.NewBitArray(10).Size(), commit.BitArray().Size()) 242 243 assert.Equal(t, voteSet.GetByIndex(0), commit.GetByIndex(0)) 244 assert.True(t, commit.IsCommit()) 245 } 246 247 func TestCommitValidateBasic(t *testing.T) { 248 testCases := []struct { 249 testName string 250 malleateCommit func(*Commit) 251 expectErr bool 252 }{ 253 {"Random Commit", func(com *Commit) {}, false}, 254 {"Incorrect signature", func(com *Commit) { com.Signatures[0].Signature = []byte{0} }, false}, 255 {"Incorrect height", func(com *Commit) { com.Height = int64(-100) }, true}, 256 {"Incorrect round", func(com *Commit) { com.Round = -100 }, true}, 257 } 258 for _, tc := range testCases { 259 tc := tc 260 t.Run(tc.testName, func(t *testing.T) { 261 com := randCommit(time.Now()) 262 tc.malleateCommit(com) 263 assert.Equal(t, tc.expectErr, com.ValidateBasic() != nil, "Validate Basic had an unexpected result") 264 }) 265 } 266 } 267 268 func TestHeaderHash(t *testing.T) { 269 testCases := []struct { 270 desc string 271 header *Header 272 expectHash bytes.HexBytes 273 }{ 274 {"Generates expected hash", &Header{ 275 Version: version.Consensus{Block: 1, App: 2}, 276 ChainID: "chainId", 277 Height: 3, 278 Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC), 279 LastBlockID: makeBlockID(make([]byte, tmhash.Size), 6, make([]byte, tmhash.Size)), 280 LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), 281 DataHash: tmhash.Sum([]byte("data_hash")), 282 ValidatorsHash: tmhash.Sum([]byte("validators_hash")), 283 NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), 284 ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 285 AppHash: tmhash.Sum([]byte("app_hash")), 286 LastResultsHash: tmhash.Sum([]byte("last_results_hash")), 287 EvidenceHash: tmhash.Sum([]byte("evidence_hash")), 288 ProposerAddress: crypto.AddressHash([]byte("proposer_address")), 289 }, hexBytesFromString("ABDC78921B18A47EE6BEF5E31637BADB0F3E587E3C0F4DB2D1E93E9FF0533862")}, 290 {"nil header yields nil", nil, nil}, 291 {"nil ValidatorsHash yields nil", &Header{ 292 Version: version.Consensus{Block: 1, App: 2}, 293 ChainID: "chainId", 294 Height: 3, 295 Time: time.Date(2019, 10, 13, 16, 14, 44, 0, time.UTC), 296 LastBlockID: makeBlockID(make([]byte, tmhash.Size), 6, make([]byte, tmhash.Size)), 297 LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), 298 DataHash: tmhash.Sum([]byte("data_hash")), 299 ValidatorsHash: nil, 300 NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), 301 ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 302 AppHash: tmhash.Sum([]byte("app_hash")), 303 LastResultsHash: tmhash.Sum([]byte("last_results_hash")), 304 EvidenceHash: tmhash.Sum([]byte("evidence_hash")), 305 ProposerAddress: crypto.AddressHash([]byte("proposer_address")), 306 }, nil}, 307 } 308 for _, tc := range testCases { 309 tc := tc 310 t.Run(tc.desc, func(t *testing.T) { 311 assert.Equal(t, tc.expectHash, tc.header.Hash()) 312 313 // We also make sure that all fields are hashed in struct order, and that all 314 // fields in the test struct are non-zero. 315 if tc.header != nil && tc.expectHash != nil { 316 byteSlices := [][]byte{} 317 s := reflect.ValueOf(*tc.header) 318 for i := 0; i < s.NumField(); i++ { 319 f := s.Field(i) 320 assert.False(t, f.IsZero(), "Found zero-valued field %v", 321 s.Type().Field(i).Name) 322 byteSlices = append(byteSlices, cdcEncode(f.Interface())) 323 } 324 assert.Equal(t, 325 bytes.HexBytes(merkle.SimpleHashFromByteSlices(byteSlices)), tc.header.Hash()) 326 } 327 }) 328 } 329 } 330 331 func TestMaxHeaderBytes(t *testing.T) { 332 // Construct a UTF-8 string of MaxChainIDLen length using the supplementary 333 // characters. 334 // Each supplementary character takes 4 bytes. 335 // http://www.i18nguy.com/unicode/supplementary-test.html 336 maxChainID := "" 337 for i := 0; i < MaxChainIDLen; i++ { 338 maxChainID += "𠜎" 339 } 340 341 // time is varint encoded so need to pick the max. 342 // year int, month Month, day, hour, min, sec, nsec int, loc *Location 343 timestamp := time.Date(math.MaxInt64, 0, 0, 0, 0, 0, math.MaxInt64, time.UTC) 344 345 h := Header{ 346 Version: version.Consensus{Block: math.MaxInt64, App: math.MaxInt64}, 347 ChainID: maxChainID, 348 Height: math.MaxInt64, 349 Time: timestamp, 350 LastBlockID: makeBlockID(make([]byte, tmhash.Size), math.MaxInt64, make([]byte, tmhash.Size)), 351 LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), 352 DataHash: tmhash.Sum([]byte("data_hash")), 353 ValidatorsHash: tmhash.Sum([]byte("validators_hash")), 354 NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), 355 ConsensusHash: tmhash.Sum([]byte("consensus_hash")), 356 AppHash: tmhash.Sum([]byte("app_hash")), 357 LastResultsHash: tmhash.Sum([]byte("last_results_hash")), 358 EvidenceHash: tmhash.Sum([]byte("evidence_hash")), 359 ProposerAddress: crypto.AddressHash([]byte("proposer_address")), 360 } 361 362 bz, err := cdc.MarshalBinaryLengthPrefixed(h) 363 require.NoError(t, err) 364 365 assert.EqualValues(t, MaxHeaderBytes, int64(len(bz))) 366 } 367 368 func randCommit(now time.Time) *Commit { 369 lastID := makeBlockIDRandom() 370 h := int64(3) 371 voteSet, _, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 372 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, now) 373 if err != nil { 374 panic(err) 375 } 376 return commit 377 } 378 379 func hexBytesFromString(s string) bytes.HexBytes { 380 b, err := hex.DecodeString(s) 381 if err != nil { 382 panic(err) 383 } 384 return bytes.HexBytes(b) 385 } 386 387 func TestBlockMaxDataBytes(t *testing.T) { 388 testCases := []struct { 389 maxBytes int64 390 valsCount int 391 evidenceCount int 392 panics bool 393 result int64 394 }{ 395 0: {-10, 1, 0, true, 0}, 396 1: {10, 1, 0, true, 0}, 397 2: {865, 1, 0, true, 0}, 398 3: {866, 1, 0, false, 0}, 399 4: {867, 1, 0, false, 1}, 400 } 401 402 for i, tc := range testCases { 403 tc := tc 404 if tc.panics { 405 assert.Panics(t, func() { 406 MaxDataBytes(tc.maxBytes, tc.valsCount, tc.evidenceCount) 407 }, "#%v", i) 408 } else { 409 assert.Equal(t, 410 tc.result, 411 MaxDataBytes(tc.maxBytes, tc.valsCount, tc.evidenceCount), 412 "#%v", i) 413 } 414 } 415 } 416 417 func TestBlockMaxDataBytesUnknownEvidence(t *testing.T) { 418 testCases := []struct { 419 maxBytes int64 420 valsCount int 421 panics bool 422 result int64 423 }{ 424 0: {-10, 1, true, 0}, 425 1: {10, 1, true, 0}, 426 2: {961, 1, true, 0}, 427 3: {962, 1, false, 0}, 428 4: {963, 1, false, 1}, 429 } 430 431 for i, tc := range testCases { 432 tc := tc 433 if tc.panics { 434 assert.Panics(t, func() { 435 MaxDataBytesUnknownEvidence(tc.maxBytes, tc.valsCount) 436 }, "#%v", i) 437 } else { 438 assert.Equal(t, 439 tc.result, 440 MaxDataBytesUnknownEvidence(tc.maxBytes, tc.valsCount), 441 "#%v", i) 442 } 443 } 444 } 445 446 func TestCommitToVoteSet(t *testing.T) { 447 lastID := makeBlockIDRandom() 448 h := int64(3) 449 450 voteSet, valSet, vals := randVoteSet(h-1, 1, PrecommitType, 10, 1) 451 commit, err := MakeCommit(lastID, h-1, 1, voteSet, vals, time.Now()) 452 assert.NoError(t, err) 453 454 chainID := voteSet.ChainID() 455 voteSet2 := CommitToVoteSet(chainID, commit, valSet) 456 457 for i := 0; i < len(vals); i++ { 458 vote1 := voteSet.GetByIndex(i) 459 vote2 := voteSet2.GetByIndex(i) 460 vote3 := commit.GetVote(i) 461 462 vote1bz := cdc.MustMarshalBinaryBare(vote1) 463 vote2bz := cdc.MustMarshalBinaryBare(vote2) 464 vote3bz := cdc.MustMarshalBinaryBare(vote3) 465 assert.Equal(t, vote1bz, vote2bz) 466 assert.Equal(t, vote1bz, vote3bz) 467 } 468 } 469 470 func TestCommitToVoteSetWithVotesForNilBlock(t *testing.T) { 471 blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash")) 472 473 const ( 474 height = int64(3) 475 round = 0 476 ) 477 478 type commitVoteTest struct { 479 blockIDs []BlockID 480 numVotes []int // must sum to numValidators 481 numValidators int 482 valid bool 483 } 484 485 testCases := []commitVoteTest{ 486 {[]BlockID{blockID, {}}, []int{67, 33}, 100, true}, 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 LastBlockID: commit.BlockID, 536 LastCommitHash: commit.Hash(), 537 DataHash: commit.Hash(), 538 ValidatorsHash: commit.Hash(), 539 NextValidatorsHash: commit.Hash(), 540 ConsensusHash: commit.Hash(), 541 AppHash: commit.Hash(), 542 LastResultsHash: commit.Hash(), 543 EvidenceHash: commit.Hash(), 544 ProposerAddress: crypto.AddressHash([]byte("proposer_address")), 545 } 546 547 validSignedHeader := SignedHeader{Header: &h, Commit: commit} 548 validSignedHeader.Commit.BlockID.Hash = validSignedHeader.Hash() 549 invalidSignedHeader := SignedHeader{} 550 551 testCases := []struct { 552 testName string 553 shHeader *Header 554 shCommit *Commit 555 expectErr bool 556 }{ 557 {"Valid Signed Header", validSignedHeader.Header, validSignedHeader.Commit, false}, 558 {"Invalid Signed Header", invalidSignedHeader.Header, validSignedHeader.Commit, true}, 559 {"Invalid Signed Header", validSignedHeader.Header, invalidSignedHeader.Commit, true}, 560 } 561 562 for _, tc := range testCases { 563 tc := tc 564 t.Run(tc.testName, func(t *testing.T) { 565 sh := SignedHeader{ 566 Header: tc.shHeader, 567 Commit: tc.shCommit, 568 } 569 assert.Equal( 570 t, 571 tc.expectErr, 572 sh.ValidateBasic(validSignedHeader.Header.ChainID) != nil, 573 "Validate Basic had an unexpected result", 574 ) 575 }) 576 } 577 } 578 579 func TestBlockIDValidateBasic(t *testing.T) { 580 validBlockID := BlockID{ 581 Hash: bytes.HexBytes{}, 582 PartsHeader: PartSetHeader{ 583 Total: 1, 584 Hash: bytes.HexBytes{}, 585 }, 586 } 587 588 invalidBlockID := BlockID{ 589 Hash: []byte{0}, 590 PartsHeader: PartSetHeader{ 591 Total: -1, 592 Hash: bytes.HexBytes{}, 593 }, 594 } 595 596 testCases := []struct { 597 testName string 598 blockIDHash bytes.HexBytes 599 blockIDPartsHeader PartSetHeader 600 expectErr bool 601 }{ 602 {"Valid BlockID", validBlockID.Hash, validBlockID.PartsHeader, false}, 603 {"Invalid BlockID", invalidBlockID.Hash, validBlockID.PartsHeader, true}, 604 {"Invalid BlockID", validBlockID.Hash, invalidBlockID.PartsHeader, true}, 605 } 606 607 for _, tc := range testCases { 608 tc := tc 609 t.Run(tc.testName, func(t *testing.T) { 610 blockID := BlockID{ 611 Hash: tc.blockIDHash, 612 PartsHeader: tc.blockIDPartsHeader, 613 } 614 assert.Equal(t, tc.expectErr, blockID.ValidateBasic() != nil, "Validate Basic had an unexpected result") 615 }) 616 } 617 } 618 619 func makeRandHeader() Header { 620 chainID := "test" 621 t := time.Now() 622 height := tmrand.Int63() 623 randBytes := tmrand.Bytes(tmhash.Size) 624 randAddress := tmrand.Bytes(crypto.AddressSize) 625 h := Header{ 626 Version: version.Consensus{Block: 1, App: 1}, 627 ChainID: chainID, 628 Height: height, 629 Time: t, 630 LastBlockID: BlockID{}, 631 LastCommitHash: randBytes, 632 DataHash: randBytes, 633 ValidatorsHash: randBytes, 634 NextValidatorsHash: randBytes, 635 ConsensusHash: randBytes, 636 AppHash: randBytes, 637 638 LastResultsHash: randBytes, 639 640 EvidenceHash: randBytes, 641 ProposerAddress: randAddress, 642 } 643 644 return h 645 } 646 647 func TestHeaderProto(t *testing.T) { 648 h1 := makeRandHeader() 649 tc := []struct { 650 msg string 651 h1 *Header 652 expPass bool 653 }{ 654 {"success", &h1, true}, 655 {"failure empty Header", &Header{}, false}, 656 } 657 658 for _, tt := range tc { 659 tt := tt 660 t.Run(tt.msg, func(t *testing.T) { 661 pb := tt.h1.ToProto() 662 h, err := HeaderFromProto(pb) 663 if tt.expPass { 664 require.NoError(t, err, tt.msg) 665 require.Equal(t, tt.h1, &h, tt.msg) 666 } else { 667 require.Error(t, err, tt.msg) 668 } 669 670 }) 671 } 672 } 673 674 func TestBlockIDProtoBuf(t *testing.T) { 675 blockID := makeBlockID([]byte("hash"), 2, []byte("part_set_hash")) 676 testCases := []struct { 677 msg string 678 bid1 *BlockID 679 expPass bool 680 }{ 681 {"success", &blockID, true}, 682 {"success empty", &BlockID{}, true}, 683 {"failure BlockID nil", nil, false}, 684 } 685 for _, tc := range testCases { 686 protoBlockID := tc.bid1.ToProto() 687 688 bi, err := BlockIDFromProto(&protoBlockID) 689 if tc.expPass { 690 require.NoError(t, err) 691 require.Equal(t, tc.bid1, bi, tc.msg) 692 } else { 693 require.NotEqual(t, tc.bid1, bi, tc.msg) 694 } 695 } 696 } 697 698 func TestSignedHeaderProtoBuf(t *testing.T) { 699 commit := randCommit(time.Now()) 700 h := makeRandHeader() 701 702 sh := SignedHeader{Header: &h, Commit: commit} 703 704 testCases := []struct { 705 msg string 706 sh1 *SignedHeader 707 expPass bool 708 }{ 709 {"empty SignedHeader 2", &SignedHeader{}, true}, 710 {"success", &sh, true}, 711 {"failure nil", nil, false}, 712 } 713 for _, tc := range testCases { 714 protoSignedHeader := tc.sh1.ToProto() 715 716 sh, err := SignedHeaderFromProto(protoSignedHeader) 717 718 if tc.expPass { 719 require.NoError(t, err, tc.msg) 720 require.Equal(t, tc.sh1, sh, tc.msg) 721 } else { 722 require.Error(t, err, tc.msg) 723 } 724 } 725 } 726 727 func TestCommitProtoBuf(t *testing.T) { 728 commit := randCommit(time.Now()) 729 730 testCases := []struct { 731 msg string 732 c1 *Commit 733 expPass bool 734 }{ 735 {"success", commit, true}, 736 // Empty value sets signatures to nil, signatures should not be nillable 737 {"empty commit", &Commit{Signatures: []CommitSig{}}, true}, 738 {"fail Commit nil", nil, false}, 739 } 740 for _, tc := range testCases { 741 tc := tc 742 protoCommit := tc.c1.ToProto() 743 744 c, err := CommitFromProto(protoCommit) 745 746 if tc.expPass { 747 require.NoError(t, err, tc.msg) 748 require.Equal(t, tc.c1, c, tc.msg) 749 } else { 750 require.Error(t, err, tc.msg) 751 } 752 } 753 } 754 755 var blockIDTestCases = []BlockID{ 756 {}, 757 {Hash: []byte{}}, 758 {[]byte("hashhashhashhashhashhash"), PartSetHeader{}}, 759 {[]byte("hashhashhashhashhashhash"), PartSetHeader{Total: 1, Hash: []byte("part_set_hash")}}, 760 } 761 762 func TestBlockIDAmino(t *testing.T) { 763 for _, tc := range blockIDTestCases { 764 bz, err := cdc.MarshalBinaryBare(tc) 765 require.NoError(t, err) 766 767 var tc2 BlockID 768 err = cdc.UnmarshalBinaryBare(bz, &tc2) 769 require.NoError(t, err) 770 771 var tc3 BlockID 772 err = tc3.UnmarshalFromAmino(cdc, bz) 773 require.NoError(t, err) 774 775 require.EqualValues(t, tc2, tc3) 776 require.EqualValues(t, len(bz), tc.AminoSize(cdc)) 777 } 778 } 779 780 var headerAminoTestCases = []Header{ 781 {}, 782 {Version: version.Consensus{Block: 1, App: 1}}, 783 {ChainID: "ChainID"}, 784 {Height: 1}, 785 {Height: math.MaxInt64}, 786 {Height: math.MinInt64}, 787 {Time: time.Now()}, 788 {LastBlockID: BlockID{[]byte("Hash"), PartSetHeader{1, []byte("Hash")}}}, 789 {LastCommitHash: []byte("LastCommitHash")}, 790 {DataHash: []byte("DataHash")}, 791 {ValidatorsHash: []byte("ValidatorsHash")}, 792 {NextValidatorsHash: []byte("NextValidatorsHash")}, 793 {ConsensusHash: []byte("ConsensusHash")}, 794 {AppHash: []byte("AppHash")}, 795 {LastResultsHash: []byte("LastResultsHash")}, 796 {EvidenceHash: []byte("EvidenceHash")}, 797 {ProposerAddress: []byte("ProposerAddress")}, 798 } 799 800 func TestHeaderAmino(t *testing.T) { 801 for _, header := range headerAminoTestCases { 802 expectData, err := cdc.MarshalBinaryBare(header) 803 require.NoError(t, err) 804 805 require.Equal(t, len(expectData), header.AminoSize(cdc)) 806 807 var expectValue Header 808 err = cdc.UnmarshalBinaryBare(expectData, &expectValue) 809 require.NoError(t, err) 810 811 var actualValue Header 812 err = actualValue.UnmarshalFromAmino(cdc, expectData) 813 require.NoError(t, err) 814 815 require.EqualValues(t, expectValue, actualValue) 816 } 817 } 818 819 func BenchmarkHeaderAminoUnmarshal(b *testing.B) { 820 testData := make([][]byte, len(headerAminoTestCases)) 821 for i, header := range headerAminoTestCases { 822 data, err := cdc.MarshalBinaryBare(header) 823 require.NoError(b, err) 824 testData[i] = data 825 } 826 b.ResetTimer() 827 b.Run("amino", func(b *testing.B) { 828 b.ReportAllocs() 829 for i := 0; i < b.N; i++ { 830 for _, data := range testData { 831 var header Header 832 err := cdc.UnmarshalBinaryBare(data, &header) 833 if err != nil { 834 b.Fatal(err) 835 } 836 } 837 } 838 }) 839 b.Run("unmarshaller", func(b *testing.B) { 840 b.ReportAllocs() 841 for i := 0; i < b.N; i++ { 842 for _, data := range testData { 843 var header Header 844 err := header.UnmarshalFromAmino(cdc, data) 845 if err != nil { 846 b.Fatal(err) 847 } 848 } 849 } 850 }) 851 } 852 853 func TestDataAmino(t *testing.T) { 854 var testCases = []Data{ 855 {}, 856 {Txs: []Tx{}}, 857 {Txs: []Tx{{}}}, 858 {Txs: []Tx{nil}}, 859 {Txs: []Tx{{}, []byte("tx1"), []byte("tx2"), nil}}, 860 {hash: []byte("hash")}, 861 } 862 863 for _, d := range testCases { 864 expectData, err := cdc.MarshalBinaryBare(d) 865 require.NoError(t, err) 866 867 require.Equal(t, len(expectData), d.AminoSize(cdc)) 868 869 var expectValue Data 870 err = cdc.UnmarshalBinaryBare(expectData, &expectValue) 871 require.NoError(t, err) 872 873 var actualValue Data 874 err = actualValue.UnmarshalFromAmino(cdc, expectData) 875 require.NoError(t, err) 876 877 require.EqualValues(t, expectValue, actualValue) 878 } 879 } 880 881 var commitSigAminoTestCases = []CommitSig{ 882 {}, 883 {125, []byte("ValidatorAddress"), time.Now(), []byte("Signature")}, 884 {math.MaxUint8, []byte(""), time.Now(), []byte("")}, 885 } 886 887 func TestCommitSigAmino(t *testing.T) { 888 for _, cs := range commitSigAminoTestCases { 889 expectData, err := cdc.MarshalBinaryBare(cs) 890 require.NoError(t, err) 891 892 require.Equal(t, len(expectData), cs.AminoSize(cdc)) 893 894 var expectValue CommitSig 895 err = cdc.UnmarshalBinaryBare(expectData, &expectValue) 896 require.NoError(t, err) 897 898 var actualValue CommitSig 899 err = actualValue.UnmarshalFromAmino(cdc, expectData) 900 901 require.NoError(t, err) 902 903 require.EqualValues(t, expectValue, actualValue) 904 } 905 } 906 907 var commitAminoTestCases = []Commit{ 908 {}, 909 { 910 Height: 123456, 911 Round: 10, 912 BlockID: BlockID{Hash: []byte("hash"), PartsHeader: PartSetHeader{Total: 123, Hash: []byte("hash")}}, 913 Signatures: commitSigAminoTestCases, 914 }, 915 { 916 Height: math.MaxInt64, 917 Round: math.MaxInt, 918 Signatures: []CommitSig{}, 919 }, 920 { 921 Height: math.MinInt64, 922 Round: math.MinInt, 923 }, 924 } 925 926 func TestCommitAmino(t *testing.T) { 927 for _, commit := range commitAminoTestCases { 928 expectData, err := cdc.MarshalBinaryBare(commit) 929 require.NoError(t, err) 930 931 require.Equal(t, len(expectData), commit.AminoSize(cdc)) 932 933 var expectValue Commit 934 err = cdc.UnmarshalBinaryBare(expectData, &expectValue) 935 require.NoError(t, err) 936 937 var actualValue Commit 938 err = actualValue.UnmarshalFromAmino(cdc, expectData) 939 require.NoError(t, err) 940 941 require.EqualValues(t, expectValue, actualValue) 942 } 943 } 944 945 func TestEvidenceDataAmino(t *testing.T) { 946 evidenceDataAminoTestCases := []EvidenceData{ 947 {}, 948 {[]Evidence{}, []byte("hash")}, 949 {Evidence: []Evidence{nil, nil}}, 950 { 951 Evidence: []Evidence{ 952 nil, 953 &DuplicateVoteEvidence{VoteA: nil}, 954 MockRandomEvidence{}, 955 MockEvidence{}, 956 }, 957 }, 958 } 959 for _, evi := range evidenceDataAminoTestCases { 960 expectData, err := cdc.MarshalBinaryBare(evi) 961 require.NoError(t, err) 962 963 require.Equal(t, len(expectData), evi.AminoSize(cdc)) 964 965 var expectValue EvidenceData 966 err = cdc.UnmarshalBinaryBare(expectData, &expectValue) 967 require.NoError(t, err) 968 969 var actualValue EvidenceData 970 err = actualValue.UnmarshalFromAmino(cdc, expectData) 971 require.NoError(t, err) 972 973 require.EqualValues(t, expectValue, actualValue) 974 } 975 } 976 977 var blockAminoTestCases = []Block{ 978 {}, 979 { 980 Header: Header{LastBlockID: BlockID{[]byte("Hash"), PartSetHeader{1, []byte("Hash")}}}, 981 Data: Data{Txs: []Tx{{}, []byte("tx1"), []byte("tx2"), nil}}, 982 Evidence: EvidenceData{ 983 Evidence: []Evidence{ 984 &DuplicateVoteEvidence{VoteA: &Vote{ 985 0, 12345, 123, 986 BlockID{[]byte("hash"), PartSetHeader{8, []byte("hash")}}, 987 time.Now(), 988 []byte("ValidatorAddress"), 989 23, 990 []byte("Signature"), false, 991 }}, 992 }, 993 }, 994 LastCommit: &Commit{ 995 Height: 123456, 996 Round: 10, 997 BlockID: BlockID{Hash: []byte("hash"), PartsHeader: PartSetHeader{Total: 123, Hash: []byte("hash")}}, 998 Signatures: commitSigAminoTestCases, 999 }, 1000 }, 1001 { 1002 LastCommit: &Commit{}, 1003 }, 1004 } 1005 1006 func TestBlockAmino(t *testing.T) { 1007 for _, block := range blockAminoTestCases { 1008 expectData, err := cdc.MarshalBinaryBare(block) 1009 require.NoError(t, err) 1010 1011 require.Equal(t, len(expectData), block.AminoSize(cdc)) 1012 1013 var expectValue Block 1014 err = cdc.UnmarshalBinaryBare(expectData, &expectValue) 1015 require.NoError(t, err) 1016 1017 var actualValue Block 1018 err = actualValue.UnmarshalFromAmino(cdc, expectData) 1019 require.NoError(t, err) 1020 1021 require.EqualValues(t, expectValue, actualValue) 1022 } 1023 } 1024 1025 func BenchmarkBlockAminoUnmarshal(b *testing.B) { 1026 testData := make([][]byte, len(blockAminoTestCases)) 1027 for i, block := range blockAminoTestCases { 1028 data, err := cdc.MarshalBinaryBare(block) 1029 require.NoError(b, err) 1030 testData[i] = data 1031 } 1032 b.ResetTimer() 1033 b.Run("amino", func(b *testing.B) { 1034 b.ReportAllocs() 1035 for i := 0; i < b.N; i++ { 1036 for _, d := range testData { 1037 var block Block 1038 err := cdc.UnmarshalBinaryBare(d, &block) 1039 if err != nil { 1040 b.Fatal(err) 1041 } 1042 } 1043 } 1044 }) 1045 b.Run("unmarshaller", func(b *testing.B) { 1046 b.ReportAllocs() 1047 for i := 0; i < b.N; i++ { 1048 for _, d := range testData { 1049 var block Block 1050 err := block.UnmarshalFromAmino(cdc, d) 1051 if err != nil { 1052 b.Fatal(err) 1053 } 1054 } 1055 } 1056 }) 1057 } 1058 1059 func Test_compressBlock(t *testing.T) { 1060 bzShort := []byte("short bz value") 1061 bzLarge := make([]byte, BlockCompressThreshold+1) 1062 type args struct { 1063 bz []byte 1064 oldBlockComressType int 1065 before func() 1066 } 1067 tests := []struct { 1068 name string 1069 args args 1070 want []byte 1071 ret func(got []byte) bool 1072 }{ 1073 {"block compress type zero", args{bz: bzShort, oldBlockComressType: BlockCompressType, before: func() {}}, bzShort, func([]byte) bool { return true }}, 1074 {"block compress with short length", args{bz: bzShort, oldBlockComressType: BlockCompressType, before: func() { BlockCompressType = 1 }}, bzShort, func([]byte) bool { return true }}, 1075 {"block compress with large length", args{bz: bzLarge, oldBlockComressType: BlockCompressType, before: func() { BlockCompressType = 1 }}, nil, func(got []byte) bool { return len(got) < len(bzLarge) }}, 1076 {"block compress with unknown compress type", args{bz: bzLarge, oldBlockComressType: BlockCompressType, before: func() { BlockCompressType = 9 }}, nil, func(got []byte) bool { return len(got) > len(bzLarge) }}, 1077 } 1078 for _, tt := range tests { 1079 t.Run(tt.name, func(t *testing.T) { 1080 tt.args.before() 1081 got := compressBlock(tt.args.bz, BlockCompressType, 0) 1082 assert.NotNil(t, got) 1083 assert.True(t, tt.ret(got)) 1084 BlockCompressType = tt.args.oldBlockComressType 1085 }) 1086 } 1087 } 1088 1089 func TestUncompressBlockFromReader(t *testing.T) { 1090 unCompressedContent, _ := cdc.MarshalBinaryBare([]byte("this is unCompressed content")) 1091 unCompressedReader := stdbytes.NewReader(unCompressedContent) 1092 1093 compressedBytes := make([]byte, BlockCompressThreshold+1) 1094 content, _ := cdc.MarshalBinaryBare(compressedBytes) 1095 oldCompressType := BlockCompressType 1096 BlockCompressType = 1 1097 compressedContent := compressBlock(content, BlockCompressType, 0) 1098 compressedReader := stdbytes.NewReader(compressedContent) 1099 1100 type args struct { 1101 pbpReader io.Reader 1102 } 1103 tests := []struct { 1104 name string 1105 args args 1106 want []byte 1107 wantErr assert.ErrorAssertionFunc 1108 }{ 1109 {"uncompressed from not compressed reader", args{pbpReader: unCompressedReader}, unCompressedContent, assert.NoError}, 1110 {"uncompressed from compressed reader", args{pbpReader: compressedReader}, content, assert.NoError}, 1111 } 1112 for _, tt := range tests { 1113 t.Run(tt.name, func(t *testing.T) { 1114 got, err := UncompressBlockFromReader(tt.args.pbpReader) 1115 if !tt.wantErr(t, err, fmt.Sprintf("UncompressBlockFromReader(%v)", tt.args.pbpReader)) { 1116 return 1117 } 1118 gotBytes := make([]byte, BlockCompressThreshold+BlockCompressThreshold) 1119 n, _ := got.Read(gotBytes) 1120 assert.Equalf(t, tt.want, gotBytes[:n], "UncompressBlockFromReader(%v)", tt.args.pbpReader) 1121 }) 1122 } 1123 BlockCompressType = oldCompressType 1124 } 1125 1126 func TestUncompressBlockFromBytes(t *testing.T) { 1127 unCompressedContent, _ := cdc.MarshalBinaryBare([]byte("this is unCompressed content")) 1128 1129 compressedBytes := make([]byte, BlockCompressThreshold+1) 1130 content, _ := cdc.MarshalBinaryBare(compressedBytes) 1131 BlockCompressType = 1 1132 compressedContent := compressBlock(content, BlockCompressType, 0) 1133 1134 type args struct { 1135 payload []byte 1136 } 1137 tests := []struct { 1138 name string 1139 args args 1140 wantRes []byte 1141 wantCompressType int 1142 wantErr assert.ErrorAssertionFunc 1143 }{ 1144 {"uncompressed from not compressed bytes", args{payload: unCompressedContent}, unCompressedContent, 0, assert.NoError}, 1145 {"uncompressed from compressed bytes", args{payload: compressedContent}, content, 1, assert.NoError}, 1146 } 1147 for _, tt := range tests { 1148 t.Run(tt.name, func(t *testing.T) { 1149 gotRes, gotCompressSign, err := UncompressBlockFromBytes(tt.args.payload) 1150 if !tt.wantErr(t, err, fmt.Sprintf("UncompressBlockFromBytes(%v)", tt.args.payload)) { 1151 return 1152 } 1153 gotCompressType := gotCompressSign / CompressDividing 1154 assert.Equalf(t, tt.wantRes, gotRes, "UncompressBlockFromBytes(%v)", tt.args.payload) 1155 assert.Equalf(t, tt.wantCompressType, gotCompressType, "UncompressBlockFromBytes(%v)", tt.args.payload) 1156 }) 1157 } 1158 }