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 }