github.com/okex/exchain@v1.8.0/libs/tendermint/types/evidence_test.go (about)

     1  package types
     2  
     3  import (
     4  	"math"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/okex/exchain/libs/tendermint/crypto"
     9  	"github.com/okex/exchain/libs/tendermint/crypto/ed25519"
    10  
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"github.com/okex/exchain/libs/tendermint/crypto/secp256k1"
    15  	"github.com/okex/exchain/libs/tendermint/crypto/tmhash"
    16  )
    17  
    18  type voteData struct {
    19  	vote1 *Vote
    20  	vote2 *Vote
    21  	valid bool
    22  }
    23  
    24  func makeVote(
    25  	t *testing.T, val PrivValidator, chainID string, valIndex int, height int64, round, step int, blockID BlockID,
    26  ) *Vote {
    27  	pubKey, err := val.GetPubKey()
    28  	require.NoError(t, err)
    29  	v := &Vote{
    30  		ValidatorAddress: pubKey.Address(),
    31  		ValidatorIndex:   valIndex,
    32  		Height:           height,
    33  		Round:            round,
    34  		Type:             SignedMsgType(step),
    35  		BlockID:          blockID,
    36  	}
    37  	err = val.SignVote(chainID, v)
    38  	if err != nil {
    39  		panic(err)
    40  	}
    41  	return v
    42  }
    43  
    44  func TestEvidence(t *testing.T) {
    45  	val := NewMockPV()
    46  	val2 := NewMockPV()
    47  
    48  	blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
    49  	blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
    50  	blockID3 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash"))
    51  	blockID4 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash2"))
    52  
    53  	const chainID = "mychain"
    54  
    55  	vote1 := makeVote(t, val, chainID, 0, 10, 2, 1, blockID)
    56  	badVote := makeVote(t, val, chainID, 0, 10, 2, 1, blockID)
    57  	err := val2.SignVote(chainID, badVote)
    58  	assert.NoError(t, err)
    59  
    60  	cases := []voteData{
    61  		{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID2), true}, // different block ids
    62  		{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID3), true},
    63  		{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID4), true},
    64  		{vote1, makeVote(t, val, chainID, 0, 10, 2, 1, blockID), false},     // wrong block id
    65  		{vote1, makeVote(t, val, "mychain2", 0, 10, 2, 1, blockID2), false}, // wrong chain id
    66  		{vote1, makeVote(t, val, chainID, 1, 10, 2, 1, blockID2), false},    // wrong val index
    67  		{vote1, makeVote(t, val, chainID, 0, 11, 2, 1, blockID2), false},    // wrong height
    68  		{vote1, makeVote(t, val, chainID, 0, 10, 3, 1, blockID2), false},    // wrong round
    69  		{vote1, makeVote(t, val, chainID, 0, 10, 2, 2, blockID2), false},    // wrong step
    70  		{vote1, makeVote(t, val2, chainID, 0, 10, 2, 1, blockID), false},    // wrong validator
    71  		{vote1, badVote, false}, // signed by wrong key
    72  	}
    73  
    74  	pubKey, err := val.GetPubKey()
    75  	require.NoError(t, err)
    76  	for _, c := range cases {
    77  		ev := &DuplicateVoteEvidence{
    78  			VoteA: c.vote1,
    79  			VoteB: c.vote2,
    80  		}
    81  		if c.valid {
    82  			assert.Nil(t, ev.Verify(chainID, pubKey), "evidence should be valid")
    83  		} else {
    84  			assert.NotNil(t, ev.Verify(chainID, pubKey), "evidence should be invalid")
    85  		}
    86  	}
    87  }
    88  
    89  func TestDuplicatedVoteEvidence(t *testing.T) {
    90  	ev := randomDuplicatedVoteEvidence(t)
    91  
    92  	assert.True(t, ev.Equal(ev))
    93  	assert.False(t, ev.Equal(&DuplicateVoteEvidence{}))
    94  }
    95  
    96  func TestEvidenceList(t *testing.T) {
    97  	ev := randomDuplicatedVoteEvidence(t)
    98  	evl := EvidenceList([]Evidence{ev})
    99  
   100  	assert.NotNil(t, evl.Hash())
   101  	assert.True(t, evl.Has(ev))
   102  	assert.False(t, evl.Has(&DuplicateVoteEvidence{}))
   103  }
   104  
   105  func TestMaxEvidenceBytes(t *testing.T) {
   106  	val := NewMockPV()
   107  	blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   108  	blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   109  	const chainID = "mychain"
   110  	ev := &DuplicateVoteEvidence{
   111  		PubKey: secp256k1.GenPrivKey().PubKey(), // use secp because it's pubkey is longer
   112  		VoteA:  makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID),
   113  		VoteB:  makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2),
   114  	}
   115  
   116  	bz, err := cdc.MarshalBinaryLengthPrefixed(ev)
   117  	require.NoError(t, err)
   118  
   119  	assert.EqualValues(t, MaxEvidenceBytes, len(bz))
   120  }
   121  
   122  func randomDuplicatedVoteEvidence(t *testing.T) *DuplicateVoteEvidence {
   123  	val := NewMockPV()
   124  	blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
   125  	blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
   126  	const chainID = "mychain"
   127  	return &DuplicateVoteEvidence{
   128  		VoteA: makeVote(t, val, chainID, 0, 10, 2, 1, blockID),
   129  		VoteB: makeVote(t, val, chainID, 0, 10, 2, 1, blockID2),
   130  	}
   131  }
   132  
   133  func TestDuplicateVoteEvidenceValidation(t *testing.T) {
   134  	val := NewMockPV()
   135  	blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   136  	blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   137  	const chainID = "mychain"
   138  
   139  	testCases := []struct {
   140  		testName         string
   141  		malleateEvidence func(*DuplicateVoteEvidence)
   142  		expectErr        bool
   143  	}{
   144  		{"Good DuplicateVoteEvidence", func(ev *DuplicateVoteEvidence) {}, false},
   145  		{"Nil vote A", func(ev *DuplicateVoteEvidence) { ev.VoteA = nil }, true},
   146  		{"Nil vote B", func(ev *DuplicateVoteEvidence) { ev.VoteB = nil }, true},
   147  		{"Nil votes", func(ev *DuplicateVoteEvidence) {
   148  			ev.VoteA = nil
   149  			ev.VoteB = nil
   150  		}, true},
   151  		{"Invalid vote type", func(ev *DuplicateVoteEvidence) {
   152  			ev.VoteA = makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0, blockID2)
   153  		}, true},
   154  		{"Invalid vote order", func(ev *DuplicateVoteEvidence) {
   155  			swap := ev.VoteA.Copy()
   156  			ev.VoteA = ev.VoteB.Copy()
   157  			ev.VoteB = swap
   158  		}, true},
   159  	}
   160  	for _, tc := range testCases {
   161  		tc := tc
   162  		t.Run(tc.testName, func(t *testing.T) {
   163  			pk := secp256k1.GenPrivKey().PubKey()
   164  			vote1 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID)
   165  			vote2 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID2)
   166  			ev := NewDuplicateVoteEvidence(pk, vote1, vote2)
   167  			tc.malleateEvidence(ev)
   168  			assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   169  		})
   170  	}
   171  }
   172  
   173  func TestMockGoodEvidenceValidateBasic(t *testing.T) {
   174  	goodEvidence := NewMockEvidence(int64(1), time.Now(), 1, []byte{1})
   175  	assert.Nil(t, goodEvidence.ValidateBasic())
   176  }
   177  
   178  func TestMockBadEvidenceValidateBasic(t *testing.T) {
   179  	badEvidence := NewMockEvidence(int64(1), time.Now(), 1, []byte{1})
   180  	assert.Nil(t, badEvidence.ValidateBasic())
   181  }
   182  
   183  func TestEvidenceProto(t *testing.T) {
   184  	// -------- Votes --------
   185  	val := NewMockPV()
   186  	blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   187  	blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   188  	const chainID = "mychain"
   189  	v := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, 1, 0x01, blockID)
   190  	v2 := makeVote(t, val, chainID, math.MaxInt64, math.MaxInt64, 2, 0x01, blockID2)
   191  
   192  	tests := []struct {
   193  		testName string
   194  		evidence Evidence
   195  		wantErr  bool
   196  		wantErr2 bool
   197  	}{
   198  		{"&DuplicateVoteEvidence empty fail", &DuplicateVoteEvidence{}, true, true},
   199  		{"&DuplicateVoteEvidence nil voteB", &DuplicateVoteEvidence{VoteA: v, VoteB: nil}, true, true},
   200  		{"&DuplicateVoteEvidence nil voteA", &DuplicateVoteEvidence{VoteA: nil, VoteB: v}, true, true},
   201  		{"&DuplicateVoteEvidence success", &DuplicateVoteEvidence{VoteA: v2, VoteB: v,
   202  			PubKey: val.PrivKey.PubKey()}, false, false},
   203  	}
   204  	for _, tt := range tests {
   205  		tt := tt
   206  		t.Run(tt.testName, func(t *testing.T) {
   207  			pb, err := EvidenceToProto(tt.evidence)
   208  			if tt.wantErr {
   209  				assert.Error(t, err, tt.testName)
   210  				return
   211  			}
   212  			assert.NoError(t, err, tt.testName)
   213  
   214  			evi, err := EvidenceFromProto(pb)
   215  			if tt.wantErr2 {
   216  				assert.Error(t, err, tt.testName)
   217  				return
   218  			}
   219  			require.Equal(t, tt.evidence, evi, tt.testName)
   220  		})
   221  	}
   222  }
   223  
   224  type emptyPubKey struct{}
   225  
   226  func (emptyPubKey) Address() crypto.Address {
   227  	return []byte("empty")
   228  }
   229  
   230  func (emptyPubKey) Bytes() []byte {
   231  	return []byte("empty")
   232  }
   233  
   234  func (emptyPubKey) VerifyBytes(msg []byte, sig []byte) bool {
   235  	return false
   236  }
   237  
   238  func (emptyPubKey) Equals(crypto.PubKey) bool {
   239  	return false
   240  }
   241  
   242  var _ crypto.PubKey = emptyPubKey{}
   243  
   244  func TestDuplicateVoteEvidenceAmino(t *testing.T) {
   245  	var duplicateVoteEvidenceTestCases = []DuplicateVoteEvidence{
   246  		{},
   247  		{
   248  			PubKey: secp256k1.GenPrivKey().PubKey(),
   249  			VoteA:  makeVote(t, NewMockPV(), "mychain", 0, 10, 2, 1, makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))),
   250  			VoteB:  makeVote(t, NewMockPV(), "mychain", 0, 10, 2, 1, makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))),
   251  		},
   252  		{
   253  			PubKey: ed25519.GenPrivKey().PubKey(),
   254  		},
   255  		{
   256  			PubKey: emptyPubKey{},
   257  			VoteA:  &Vote{},
   258  		},
   259  	}
   260  	cdc.RegisterConcrete(emptyPubKey{}, "emptyPubKey", nil)
   261  
   262  	for _, tc := range duplicateVoteEvidenceTestCases {
   263  		expectData, err := cdc.MarshalBinaryBare(tc)
   264  		require.NoError(t, err)
   265  
   266  		require.Equal(t, len(expectData), tc.AminoSize(cdc)+4)
   267  
   268  		var expectValue DuplicateVoteEvidence
   269  		err = cdc.UnmarshalBinaryBare(expectData, &expectValue)
   270  		require.NoError(t, err)
   271  
   272  		var actualValue DuplicateVoteEvidence
   273  		tmp, err := cdc.UnmarshalBinaryBareWithRegisteredUnmarshaller(expectData, &actualValue)
   274  		require.NoError(t, err)
   275  		_, ok := tmp.(DuplicateVoteEvidence)
   276  		require.False(t, ok)
   277  		_, ok = tmp.(*DuplicateVoteEvidence)
   278  		require.True(t, ok)
   279  		actualValue = *(tmp.(*DuplicateVoteEvidence))
   280  
   281  		require.EqualValues(t, expectValue, actualValue)
   282  	}
   283  }
   284  
   285  func TestEvidenceAmino(t *testing.T) {
   286  	var evidenceTestCases = []Evidence{
   287  		// nil,
   288  		&DuplicateVoteEvidence{},
   289  	}
   290  
   291  	for _, evi := range evidenceTestCases {
   292  		expectData, err := cdc.MarshalBinaryBare(evi)
   293  		require.NoError(t, err)
   294  
   295  		var expectValue Evidence
   296  		err = cdc.UnmarshalBinaryBare(expectData, &expectValue)
   297  		require.NoError(t, err)
   298  
   299  		var actualValue Evidence
   300  		tmp, err := cdc.UnmarshalBinaryBareWithRegisteredUnmarshaller(expectData, &actualValue)
   301  		require.NoError(t, err)
   302  		_, ok := tmp.(Evidence)
   303  		require.True(t, ok)
   304  		actualValue = (tmp.(Evidence))
   305  
   306  		require.EqualValues(t, expectValue, actualValue)
   307  	}
   308  
   309  	evidenceTestCases = []Evidence{
   310  		&MockEvidence{},
   311  		&MockRandomEvidence{},
   312  	}
   313  
   314  	for _, evi := range evidenceTestCases {
   315  		expectData, err := cdc.MarshalBinaryBare(evi)
   316  		require.NoError(t, err)
   317  
   318  		var expectValue Evidence
   319  		err = cdc.UnmarshalBinaryBare(expectData, &expectValue)
   320  		require.NoError(t, err)
   321  
   322  		var actualValue Evidence
   323  		_, err = cdc.UnmarshalBinaryBareWithRegisteredUnmarshaller(expectData, &actualValue)
   324  		require.Error(t, err)
   325  	}
   326  }