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 }