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.

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