You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
6.6 KiB

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