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