github.com/fiagdao/tendermint@v0.32.11-0.20220824195748-2087fcc480c1/types/evidence_test.go (about)

     1  package types
     2  
     3  import (
     4  	"math"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/tendermint/tendermint/crypto/secp256k1"
    12  	"github.com/tendermint/tendermint/crypto/tmhash"
    13  )
    14  
    15  type voteData struct {
    16  	vote1 *Vote
    17  	vote2 *Vote
    18  	valid bool
    19  }
    20  
    21  func makeVote(
    22  	t *testing.T, val PrivValidator, chainID string, valIndex int, height int64, round, step int, blockID BlockID,
    23  ) *Vote {
    24  	pubKey, err := val.GetPubKey()
    25  	require.NoError(t, err)
    26  	v := &Vote{
    27  		ValidatorAddress: pubKey.Address(),
    28  		ValidatorIndex:   valIndex,
    29  		Height:           height,
    30  		Round:            round,
    31  		Type:             SignedMsgType(step),
    32  		BlockID:          blockID,
    33  	}
    34  	err = val.SignVote(chainID, v)
    35  	if err != nil {
    36  		panic(err)
    37  	}
    38  	return v
    39  }
    40  
    41  func TestEvidence(t *testing.T) {
    42  	val := NewMockPV()
    43  	val2 := NewMockPV()
    44  
    45  	blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
    46  	blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
    47  	blockID3 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash"))
    48  	blockID4 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash2"))
    49  
    50  	const chainID = "mychain"
    51  
    52  	vote1 := makeVote(t, val, chainID, 0, 10, 2, 1, blockID)
    53  	badVote := makeVote(t, val, chainID, 0, 10, 2, 1, blockID)
    54  	err := val2.SignVote(chainID, badVote)
    55  	assert.NoError(t, err)
    56  
    57  	cases := []voteData{
    58  		{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2), true}, // different block ids
    59  		{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID3), true},
    60  		{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID4), true},
    61  		{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID), false},     // wrong block id
    62  		{vote1, makeVote(t, val, "mychain2", 0, 10, 2, 1, blockID2), false}, // wrong chain id
    63  		{vote1, makeVote(t, val, chainID, 1, 10, 2, 1, blockID2), false},    // wrong val index
    64  		{vote1, makeVote(t, val, chainID, 0, 11, 2, 1, blockID2), false},    // wrong height
    65  		{vote1, makeVote(t, val, chainID, 0, 10, 3, 1, blockID2), false},    // wrong round
    66  		{vote1, makeVote(t, val, chainID, 0, 10, 2, 2, blockID2), false},    // wrong step
    67  		{vote1, makeVote(t, val2, chainID, 0, 10, 2, 1, blockID), false},    // wrong validator
    68  		{vote1, badVote, false}, // signed by wrong key
    69  	}
    70  
    71  	pubKey, err := val.GetPubKey()
    72  	require.NoError(t, err)
    73  	for _, c := range cases {
    74  		ev := &DuplicateVoteEvidence{
    75  			VoteA: c.vote1,
    76  			VoteB: c.vote2,
    77  		}
    78  		if c.valid {
    79  			assert.Nil(t, ev.Verify(chainID, pubKey), "evidence should be valid")
    80  		} else {
    81  			assert.NotNil(t, ev.Verify(chainID, pubKey), "evidence should be invalid")
    82  		}
    83  	}
    84  }
    85  
    86  func TestDuplicatedVoteEvidence(t *testing.T) {
    87  	ev := randomDuplicatedVoteEvidence(t)
    88  
    89  	assert.True(t, ev.Equal(ev))
    90  	assert.False(t, ev.Equal(&DuplicateVoteEvidence{}))
    91  }
    92  
    93  func TestEvidenceList(t *testing.T) {
    94  	ev := randomDuplicatedVoteEvidence(t)
    95  	evl := EvidenceList([]Evidence{ev})
    96  
    97  	assert.NotNil(t, evl.Hash())
    98  	assert.True(t, evl.Has(ev))
    99  	assert.False(t, evl.Has(&DuplicateVoteEvidence{}))
   100  }
   101  
   102  func TestMaxEvidenceBytes(t *testing.T) {
   103  	val := NewMockPV()
   104  	blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   105  	blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   106  	const chainID = "mychain"
   107  	ev := &DuplicateVoteEvidence{
   108  		PubKey: secp256k1.GenPrivKey().PubKey(), // use secp because it's pubkey is longer
   109  		VoteA:  makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID),
   110  		VoteB:  makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2),
   111  	}
   112  
   113  	bz, err := cdc.MarshalBinaryLengthPrefixed(ev)
   114  	require.NoError(t, err)
   115  
   116  	assert.EqualValues(t, MaxEvidenceBytes, len(bz))
   117  }
   118  
   119  func randomDuplicatedVoteEvidence(t *testing.T) *DuplicateVoteEvidence {
   120  	val := NewMockPV()
   121  	blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
   122  	blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
   123  	const chainID = "mychain"
   124  	return &DuplicateVoteEvidence{
   125  		VoteA: makeVote(t, val, chainID, 0, 10, 2, 1, blockID),
   126  		VoteB: makeVote(t, val, chainID, 0, 10, 2, 1, blockID2),
   127  	}
   128  }
   129  
   130  func TestDuplicateVoteEvidenceValidation(t *testing.T) {
   131  	val := NewMockPV()
   132  	blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   133  	blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   134  	const chainID = "mychain"
   135  
   136  	testCases := []struct {
   137  		testName         string
   138  		malleateEvidence func(*DuplicateVoteEvidence)
   139  		expectErr        bool
   140  	}{
   141  		{"Good DuplicateVoteEvidence", func(ev *DuplicateVoteEvidence) {}, false},
   142  		{"Nil vote A", func(ev *DuplicateVoteEvidence) { ev.VoteA = nil }, true},
   143  		{"Nil vote B", func(ev *DuplicateVoteEvidence) { ev.VoteB = nil }, true},
   144  		{"Nil votes", func(ev *DuplicateVoteEvidence) {
   145  			ev.VoteA = nil
   146  			ev.VoteB = nil
   147  		}, true},
   148  		{"Invalid vote type", func(ev *DuplicateVoteEvidence) {
   149  			ev.VoteA = makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0, blockID2)
   150  		}, true},
   151  		{"Invalid vote order", func(ev *DuplicateVoteEvidence) {
   152  			swap := ev.VoteA.Copy()
   153  			ev.VoteA = ev.VoteB.Copy()
   154  			ev.VoteB = swap
   155  		}, false},
   156  	}
   157  	for _, tc := range testCases {
   158  		tc := tc
   159  		t.Run(tc.testName, func(t *testing.T) {
   160  			pk := secp256k1.GenPrivKey().PubKey()
   161  			vote1 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID)
   162  			vote2 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID2)
   163  			ev := NewDuplicateVoteEvidence(pk, vote1, vote2)
   164  			tc.malleateEvidence(ev)
   165  			assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   166  		})
   167  	}
   168  }
   169  
   170  func TestMockGoodEvidenceValidateBasic(t *testing.T) {
   171  	goodEvidence := NewMockEvidence(int64(1), time.Now(), 1, []byte{1})
   172  	assert.Nil(t, goodEvidence.ValidateBasic())
   173  }
   174  
   175  func TestMockBadEvidenceValidateBasic(t *testing.T) {
   176  	badEvidence := NewMockEvidence(int64(1), time.Now(), 1, []byte{1})
   177  	assert.Nil(t, badEvidence.ValidateBasic())
   178  }
   179  
   180  func TestEvidenceProto(t *testing.T) {
   181  	// -------- Votes --------
   182  	val := NewMockPV()
   183  	blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   184  	blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   185  	const chainID = "mychain"
   186  	v := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, 1, 0x01, blockID)
   187  	v2 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, 2, 0x01, blockID2)
   188  
   189  	tests := []struct {
   190  		testName string
   191  		evidence Evidence
   192  		wantErr  bool
   193  		wantErr2 bool
   194  	}{
   195  		{"&DuplicateVoteEvidence empty fail", &DuplicateVoteEvidence{}, true, true},
   196  		{"&DuplicateVoteEvidence nil voteB", &DuplicateVoteEvidence{VoteA: v, VoteB: nil}, true, true},
   197  		{"&DuplicateVoteEvidence nil voteA", &DuplicateVoteEvidence{VoteA: nil, VoteB: v}, true, true},
   198  		{"&DuplicateVoteEvidence success", &DuplicateVoteEvidence{VoteA: v2, VoteB: v,
   199  			PubKey: val.PrivKey.PubKey()}, false, false},
   200  	}
   201  	for _, tt := range tests {
   202  		tt := tt
   203  		t.Run(tt.testName, func(t *testing.T) {
   204  			pb, err := EvidenceToProto(tt.evidence)
   205  			if tt.wantErr {
   206  				assert.Error(t, err, tt.testName)
   207  				return
   208  			}
   209  			assert.NoError(t, err, tt.testName)
   210  
   211  			evi, err := EvidenceFromProto(pb)
   212  			if tt.wantErr2 {
   213  				assert.Error(t, err, tt.testName)
   214  				return
   215  			}
   216  			require.Equal(t, tt.evidence, evi, tt.testName)
   217  		})
   218  	}
   219  }