github.com/evdatsion/aphelion-dpos-bft@v0.32.1/types/evidence_test.go (about)

     1  package types
     2  
     3  import (
     4  	"math"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  	"github.com/evdatsion/aphelion-dpos-bft/crypto/secp256k1"
    10  	"github.com/evdatsion/aphelion-dpos-bft/crypto/tmhash"
    11  )
    12  
    13  type voteData struct {
    14  	vote1 *Vote
    15  	vote2 *Vote
    16  	valid bool
    17  }
    18  
    19  func makeVote(val PrivValidator, chainID string, valIndex int, height int64, round, step int, blockID BlockID) *Vote {
    20  	addr := val.GetPubKey().Address()
    21  	v := &Vote{
    22  		ValidatorAddress: addr,
    23  		ValidatorIndex:   valIndex,
    24  		Height:           height,
    25  		Round:            round,
    26  		Type:             SignedMsgType(step),
    27  		BlockID:          blockID,
    28  	}
    29  	err := val.SignVote(chainID, v)
    30  	if err != nil {
    31  		panic(err)
    32  	}
    33  	return v
    34  }
    35  
    36  func TestEvidence(t *testing.T) {
    37  	val := NewMockPV()
    38  	val2 := NewMockPV()
    39  
    40  	blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
    41  	blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
    42  	blockID3 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash"))
    43  	blockID4 := makeBlockID([]byte("blockhash"), 10000, []byte("partshash2"))
    44  
    45  	const chainID = "mychain"
    46  
    47  	vote1 := makeVote(val, chainID, 0, 10, 2, 1, blockID)
    48  	badVote := makeVote(val, chainID, 0, 10, 2, 1, blockID)
    49  	err := val2.SignVote(chainID, badVote)
    50  	if err != nil {
    51  		panic(err)
    52  	}
    53  
    54  	cases := []voteData{
    55  		{vote1, makeVote(val, chainID, 0, 10, 2, 1, blockID2), true}, // different block ids
    56  		{vote1, makeVote(val, chainID, 0, 10, 2, 1, blockID3), true},
    57  		{vote1, makeVote(val, chainID, 0, 10, 2, 1, blockID4), true},
    58  		{vote1, makeVote(val, chainID, 0, 10, 2, 1, blockID), false},     // wrong block id
    59  		{vote1, makeVote(val, "mychain2", 0, 10, 2, 1, blockID2), false}, // wrong chain id
    60  		{vote1, makeVote(val, chainID, 1, 10, 2, 1, blockID2), false},    // wrong val index
    61  		{vote1, makeVote(val, chainID, 0, 11, 2, 1, blockID2), false},    // wrong height
    62  		{vote1, makeVote(val, chainID, 0, 10, 3, 1, blockID2), false},    // wrong round
    63  		{vote1, makeVote(val, chainID, 0, 10, 2, 2, blockID2), false},    // wrong step
    64  		{vote1, makeVote(val2, chainID, 0, 10, 2, 1, blockID), false},    // wrong validator
    65  		{vote1, badVote, false}, // signed by wrong key
    66  	}
    67  
    68  	pubKey := val.GetPubKey()
    69  	for _, c := range cases {
    70  		ev := &DuplicateVoteEvidence{
    71  			VoteA: c.vote1,
    72  			VoteB: c.vote2,
    73  		}
    74  		if c.valid {
    75  			assert.Nil(t, ev.Verify(chainID, pubKey), "evidence should be valid")
    76  		} else {
    77  			assert.NotNil(t, ev.Verify(chainID, pubKey), "evidence should be invalid")
    78  		}
    79  	}
    80  }
    81  
    82  func TestDuplicatedVoteEvidence(t *testing.T) {
    83  	ev := randomDuplicatedVoteEvidence()
    84  
    85  	assert.True(t, ev.Equal(ev))
    86  	assert.False(t, ev.Equal(&DuplicateVoteEvidence{}))
    87  }
    88  
    89  func TestEvidenceList(t *testing.T) {
    90  	ev := randomDuplicatedVoteEvidence()
    91  	evl := EvidenceList([]Evidence{ev})
    92  
    93  	assert.NotNil(t, evl.Hash())
    94  	assert.True(t, evl.Has(ev))
    95  	assert.False(t, evl.Has(&DuplicateVoteEvidence{}))
    96  }
    97  
    98  func TestMaxEvidenceBytes(t *testing.T) {
    99  	val := NewMockPV()
   100  	blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   101  	blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   102  	const chainID = "mychain"
   103  	ev := &DuplicateVoteEvidence{
   104  		PubKey: secp256k1.GenPrivKey().PubKey(), // use secp because it's pubkey is longer
   105  		VoteA:  makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID),
   106  		VoteB:  makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, math.MaxInt64, blockID2),
   107  	}
   108  
   109  	bz, err := cdc.MarshalBinaryLengthPrefixed(ev)
   110  	require.NoError(t, err)
   111  
   112  	assert.EqualValues(t, MaxEvidenceBytes, len(bz))
   113  }
   114  
   115  func randomDuplicatedVoteEvidence() *DuplicateVoteEvidence {
   116  	val := NewMockPV()
   117  	blockID := makeBlockID([]byte("blockhash"), 1000, []byte("partshash"))
   118  	blockID2 := makeBlockID([]byte("blockhash2"), 1000, []byte("partshash"))
   119  	const chainID = "mychain"
   120  	return &DuplicateVoteEvidence{
   121  		VoteA: makeVote(val, chainID, 0, 10, 2, 1, blockID),
   122  		VoteB: makeVote(val, chainID, 0, 10, 2, 1, blockID2),
   123  	}
   124  }
   125  
   126  func TestDuplicateVoteEvidenceValidation(t *testing.T) {
   127  	val := NewMockPV()
   128  	blockID := makeBlockID(tmhash.Sum([]byte("blockhash")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   129  	blockID2 := makeBlockID(tmhash.Sum([]byte("blockhash2")), math.MaxInt64, tmhash.Sum([]byte("partshash")))
   130  	const chainID = "mychain"
   131  
   132  	testCases := []struct {
   133  		testName         string
   134  		malleateEvidence func(*DuplicateVoteEvidence)
   135  		expectErr        bool
   136  	}{
   137  		{"Good DuplicateVoteEvidence", func(ev *DuplicateVoteEvidence) {}, false},
   138  		{"Nil vote A", func(ev *DuplicateVoteEvidence) { ev.VoteA = nil }, true},
   139  		{"Nil vote B", func(ev *DuplicateVoteEvidence) { ev.VoteB = nil }, true},
   140  		{"Nil votes", func(ev *DuplicateVoteEvidence) {
   141  			ev.VoteA = nil
   142  			ev.VoteB = nil
   143  		}, true},
   144  		{"Invalid vote type", func(ev *DuplicateVoteEvidence) {
   145  			ev.VoteA = makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0, blockID2)
   146  		}, true},
   147  	}
   148  	for _, tc := range testCases {
   149  		t.Run(tc.testName, func(t *testing.T) {
   150  			ev := &DuplicateVoteEvidence{
   151  				PubKey: secp256k1.GenPrivKey().PubKey(),
   152  				VoteA:  makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID),
   153  				VoteB:  makeVote(val, chainID, math.MaxInt64, math.MaxInt64, math.MaxInt64, 0x02, blockID2),
   154  			}
   155  			tc.malleateEvidence(ev)
   156  			assert.Equal(t, tc.expectErr, ev.ValidateBasic() != nil, "Validate Basic had an unexpected result")
   157  		})
   158  	}
   159  }