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  }