github.com/adoriasoft/tendermint@v0.34.0-dev1.0.20200722151356-96d84601a75a/rpc/client/evidence_test.go (about) 1 package client_test 2 3 import ( 4 "bytes" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 11 abci "github.com/tendermint/tendermint/abci/types" 12 "github.com/tendermint/tendermint/crypto" 13 "github.com/tendermint/tendermint/crypto/ed25519" 14 cryptoenc "github.com/tendermint/tendermint/crypto/encoding" 15 "github.com/tendermint/tendermint/crypto/tmhash" 16 "github.com/tendermint/tendermint/privval" 17 tmproto "github.com/tendermint/tendermint/proto/tendermint/types" 18 "github.com/tendermint/tendermint/rpc/client" 19 rpctest "github.com/tendermint/tendermint/rpc/test" 20 "github.com/tendermint/tendermint/types" 21 ) 22 23 func newEvidence(t *testing.T, val *privval.FilePV, 24 vote *types.Vote, vote2 *types.Vote, 25 chainID string) *types.DuplicateVoteEvidence { 26 27 var err error 28 29 v := vote.ToProto() 30 v2 := vote2.ToProto() 31 32 vote.Signature, err = val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v)) 33 require.NoError(t, err) 34 35 vote2.Signature, err = val.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v2)) 36 require.NoError(t, err) 37 38 return types.NewDuplicateVoteEvidence(vote, vote2) 39 } 40 41 func makeEvidences( 42 t *testing.T, 43 val *privval.FilePV, 44 chainID string, 45 ) (correct *types.DuplicateVoteEvidence, fakes []*types.DuplicateVoteEvidence) { 46 vote := types.Vote{ 47 ValidatorAddress: val.Key.Address, 48 ValidatorIndex: 0, 49 Height: 1, 50 Round: 0, 51 Type: tmproto.PrevoteType, 52 Timestamp: time.Now().UTC(), 53 BlockID: types.BlockID{ 54 Hash: tmhash.Sum([]byte("blockhash")), 55 PartSetHeader: types.PartSetHeader{ 56 Total: 1000, 57 Hash: tmhash.Sum([]byte("partset")), 58 }, 59 }, 60 } 61 62 vote2 := vote 63 vote2.BlockID.Hash = tmhash.Sum([]byte("blockhash2")) 64 correct = newEvidence(t, val, &vote, &vote2, chainID) 65 66 fakes = make([]*types.DuplicateVoteEvidence, 0) 67 68 // different address 69 { 70 v := vote2 71 v.ValidatorAddress = []byte("some_address") 72 fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) 73 } 74 75 // different index 76 { 77 v := vote2 78 v.ValidatorIndex = vote.ValidatorIndex + 1 79 fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) 80 } 81 82 // different height 83 { 84 v := vote2 85 v.Height = vote.Height + 1 86 fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) 87 } 88 89 // different round 90 { 91 v := vote2 92 v.Round = vote.Round + 1 93 fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) 94 } 95 96 // different type 97 { 98 v := vote2 99 v.Type = tmproto.PrecommitType 100 fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) 101 } 102 103 // exactly same vote 104 { 105 v := vote 106 fakes = append(fakes, newEvidence(t, val, &vote, &v, chainID)) 107 } 108 109 return correct, fakes 110 } 111 112 func TestBroadcastEvidence_DuplicateVoteEvidence(t *testing.T) { 113 var ( 114 config = rpctest.GetConfig() 115 chainID = config.ChainID() 116 pv = privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()) 117 ) 118 119 correct, fakes := makeEvidences(t, pv, chainID) 120 121 for i, c := range GetClients() { 122 t.Logf("client %d", i) 123 124 result, err := c.BroadcastEvidence(correct) 125 require.NoError(t, err, "BroadcastEvidence(%s) failed", correct) 126 assert.Equal(t, correct.Hash(), result.Hash, "expected result hash to match evidence hash") 127 128 status, err := c.Status() 129 require.NoError(t, err) 130 err = client.WaitForHeight(c, status.SyncInfo.LatestBlockHeight+2, nil) 131 require.NoError(t, err) 132 133 ed25519pub := pv.Key.PubKey.(ed25519.PubKey) 134 rawpub := ed25519pub.Bytes() 135 result2, err := c.ABCIQuery("/val", rawpub) 136 require.NoError(t, err) 137 qres := result2.Response 138 require.True(t, qres.IsOK()) 139 140 var v abci.ValidatorUpdate 141 err = abci.ReadMessage(bytes.NewReader(qres.Value), &v) 142 require.NoError(t, err, "Error reading query result, value %v", qres.Value) 143 144 pk, err := cryptoenc.PubKeyFromProto(v.PubKey) 145 require.NoError(t, err) 146 147 require.EqualValues(t, rawpub, pk.Bytes(), "Stored PubKey not equal with expected, value %v", string(qres.Value)) 148 require.Equal(t, int64(9), v.Power, "Stored Power not equal with expected, value %v", string(qres.Value)) 149 150 for _, fake := range fakes { 151 _, err := c.BroadcastEvidence(fake) 152 require.Error(t, err, "BroadcastEvidence(%s) succeeded, but the evidence was fake", fake) 153 } 154 } 155 } 156 157 func TestBroadcastEvidence_ConflictingHeadersEvidence(t *testing.T) { 158 var ( 159 config = rpctest.GetConfig() 160 chainID = config.ChainID() 161 pv = privval.LoadOrGenFilePV(config.PrivValidatorKeyFile(), config.PrivValidatorStateFile()) 162 ) 163 164 for i, c := range GetClients() { 165 t.Logf("client %d", i) 166 167 h1, err := c.Commit(nil) 168 require.NoError(t, err) 169 require.NotNil(t, h1.SignedHeader.Header) 170 171 // Create an alternative header with a different AppHash. 172 h2 := &types.SignedHeader{ 173 Header: &types.Header{ 174 Version: h1.Version, 175 ChainID: h1.ChainID, 176 Height: h1.Height, 177 Time: h1.Time, 178 LastBlockID: h1.LastBlockID, 179 LastCommitHash: h1.LastCommitHash, 180 DataHash: h1.DataHash, 181 ValidatorsHash: h1.ValidatorsHash, 182 NextValidatorsHash: h1.NextValidatorsHash, 183 ConsensusHash: h1.ConsensusHash, 184 AppHash: crypto.CRandBytes(32), 185 LastResultsHash: h1.LastResultsHash, 186 EvidenceHash: h1.EvidenceHash, 187 ProposerAddress: h1.ProposerAddress, 188 }, 189 Commit: types.NewCommit(h1.Height, 1, h1.Commit.BlockID, h1.Commit.Signatures), 190 } 191 h2.Commit.BlockID = types.BlockID{ 192 Hash: h2.Hash(), 193 PartSetHeader: types.PartSetHeader{Total: 1, Hash: crypto.CRandBytes(32)}, 194 } 195 vote := &types.Vote{ 196 ValidatorAddress: pv.Key.Address, 197 ValidatorIndex: 0, 198 Height: h2.Height, 199 Round: h2.Commit.Round, 200 Timestamp: h2.Time, 201 Type: tmproto.PrecommitType, 202 BlockID: h2.Commit.BlockID, 203 } 204 205 v := vote.ToProto() 206 signBytes, err := pv.Key.PrivKey.Sign(types.VoteSignBytes(chainID, v)) 207 require.NoError(t, err) 208 vote.Signature = v.Signature 209 210 h2.Commit.Signatures[0] = types.NewCommitSigForBlock(signBytes, pv.Key.Address, h2.Time) 211 212 t.Logf("h1 AppHash: %X", h1.AppHash) 213 t.Logf("h2 AppHash: %X", h2.AppHash) 214 215 ev := &types.ConflictingHeadersEvidence{ 216 H1: &h1.SignedHeader, 217 H2: h2, 218 } 219 220 result, err := c.BroadcastEvidence(ev) 221 require.NoError(t, err, "BroadcastEvidence(%s) failed", ev) 222 assert.Equal(t, ev.Hash(), result.Hash, "expected result hash to match evidence hash") 223 } 224 } 225 226 func TestBroadcastEmptyEvidence(t *testing.T) { 227 for _, c := range GetClients() { 228 _, err := c.BroadcastEvidence(nil) 229 assert.Error(t, err) 230 } 231 }