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.

180 lines
5.5 KiB

  1. package evidence
  2. import (
  3. "fmt"
  4. "testing"
  5. "time"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/mock"
  8. "github.com/tendermint/tendermint/crypto"
  9. "github.com/tendermint/tendermint/crypto/tmhash"
  10. "github.com/tendermint/tendermint/evidence/mocks"
  11. tmrand "github.com/tendermint/tendermint/libs/rand"
  12. "github.com/tendermint/tendermint/types"
  13. )
  14. func TestVerifyEvidenceWrongAddress(t *testing.T) {
  15. var height int64 = 4
  16. val := types.NewMockPV()
  17. stateStore := initializeValidatorState(val, height)
  18. state := stateStore.LoadState()
  19. blockStore := &mocks.BlockStore{}
  20. blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return(
  21. &types.BlockMeta{Header: types.Header{Time: defaultEvidenceTime}},
  22. )
  23. evidence := types.NewMockDuplicateVoteEvidence(1, defaultEvidenceTime, evidenceChainID)
  24. err := VerifyEvidence(evidence, state, stateStore, blockStore)
  25. errMsg := fmt.Sprintf("address %X was not a validator at height 1", evidence.Address())
  26. if assert.Error(t, err) {
  27. assert.Equal(t, err.Error(), errMsg)
  28. }
  29. }
  30. func TestVerifyEvidenceExpiredEvidence(t *testing.T) {
  31. var height int64 = 4
  32. val := types.NewMockPV()
  33. stateStore := initializeValidatorState(val, height)
  34. state := stateStore.LoadState()
  35. state.ConsensusParams.Evidence.MaxAgeNumBlocks = 1
  36. expiredEvidenceTime := time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC)
  37. blockStore := &mocks.BlockStore{}
  38. blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return(
  39. &types.BlockMeta{Header: types.Header{Time: expiredEvidenceTime}},
  40. )
  41. expiredEv := types.NewMockDuplicateVoteEvidenceWithValidator(1, expiredEvidenceTime, val, evidenceChainID)
  42. err := VerifyEvidence(expiredEv, state, stateStore, blockStore)
  43. errMsg := "evidence from height 1 (created at: 2018-01-01 00:00:00 +0000 UTC) is too old"
  44. if assert.Error(t, err) {
  45. assert.Equal(t, err.Error()[:len(errMsg)], errMsg)
  46. }
  47. }
  48. func TestVerifyEvidenceInvalidTime(t *testing.T) {
  49. height := int64(4)
  50. val := types.NewMockPV()
  51. stateStore := initializeValidatorState(val, height)
  52. state := stateStore.LoadState()
  53. blockStore := &mocks.BlockStore{}
  54. blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return(
  55. &types.BlockMeta{Header: types.Header{Time: defaultEvidenceTime}},
  56. )
  57. differentTime := time.Date(2019, 2, 1, 0, 0, 0, 0, time.UTC)
  58. ev := types.NewMockDuplicateVoteEvidenceWithValidator(height, differentTime, val, evidenceChainID)
  59. err := VerifyEvidence(ev, state, stateStore, blockStore)
  60. errMsg := "evidence time (2019-02-01 00:00:00 +0000 UTC) is different to the time" +
  61. " of the header we have for the same height (2019-01-01 00:00:00 +0000 UTC)"
  62. if assert.Error(t, err) {
  63. assert.Equal(t, errMsg, err.Error())
  64. }
  65. }
  66. func TestVerifyEvidenceWithLunaticValidatorEvidence(t *testing.T) {
  67. var height int64 = 4
  68. val := types.NewMockPV()
  69. stateStore := initializeValidatorState(val, height)
  70. blockID := types.BlockID{
  71. Hash: tmrand.Bytes(tmhash.Size),
  72. PartSetHeader: types.PartSetHeader{
  73. Total: 1,
  74. Hash: tmrand.Bytes(tmhash.Size),
  75. },
  76. }
  77. h := &types.Header{
  78. ChainID: evidenceChainID,
  79. Height: 3,
  80. Time: defaultEvidenceTime,
  81. LastBlockID: blockID,
  82. LastCommitHash: tmhash.Sum([]byte("last_commit_hash")),
  83. DataHash: tmhash.Sum([]byte("data_hash")),
  84. ValidatorsHash: tmhash.Sum([]byte("validators_hash")),
  85. NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")),
  86. ConsensusHash: tmhash.Sum([]byte("consensus_hash")),
  87. AppHash: tmhash.Sum([]byte("app_hash")),
  88. LastResultsHash: tmhash.Sum([]byte("last_results_hash")),
  89. EvidenceHash: tmhash.Sum([]byte("evidence_hash")),
  90. ProposerAddress: crypto.AddressHash([]byte("proposer_address")),
  91. }
  92. blockStore := &mocks.BlockStore{}
  93. blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return(
  94. &types.BlockMeta{Header: *h},
  95. )
  96. validH1 := *h
  97. validH1.ValidatorsHash = tmhash.Sum([]byte("different_validators_hash"))
  98. validH2 := validH1
  99. validH2.Time = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
  100. badH1 := validH1
  101. badH1.ChainID = "different_chain_id"
  102. badH2 := *h
  103. badH2.DataHash = tmhash.Sum([]byte("different_data_hash"))
  104. testCases := []struct {
  105. Header *types.Header
  106. ExpErr bool
  107. ErrMsg string
  108. }{
  109. {
  110. h,
  111. true,
  112. "ValidatorsHash matches committed hash",
  113. },
  114. {
  115. &validH1,
  116. false,
  117. "",
  118. },
  119. {
  120. &validH2,
  121. false,
  122. "",
  123. },
  124. {
  125. &badH1,
  126. true,
  127. "chainID do not match: test_chain vs different_chain_id",
  128. },
  129. {
  130. &badH2,
  131. true,
  132. "ValidatorsHash matches committed hash", // it doesn't recognise that the data hashes are different
  133. },
  134. }
  135. for idx, tc := range testCases {
  136. ev := types.NewLunaticValidatorEvidence(tc.Header,
  137. makeValidVoteForHeader(tc.Header, val), "ValidatorsHash", defaultEvidenceTime)
  138. err := VerifyEvidence(ev, stateStore.LoadState(), stateStore, blockStore)
  139. if tc.ExpErr {
  140. if assert.Error(t, err, fmt.Sprintf("expected an error for case: %d", idx)) {
  141. assert.Equal(t, tc.ErrMsg, err.Error(), fmt.Sprintf("case: %d", idx))
  142. }
  143. } else {
  144. assert.NoError(t, err, fmt.Sprintf("did not expect an error for case: %d", idx))
  145. }
  146. }
  147. }
  148. func makeValidVoteForHeader(header *types.Header, val types.MockPV) *types.Vote {
  149. vote := makeVote(header.Height, 1, 0, val.PrivKey.PubKey().Address(), types.BlockID{
  150. Hash: header.Hash(),
  151. PartSetHeader: types.PartSetHeader{
  152. Total: 100,
  153. Hash: crypto.CRandBytes(tmhash.Size),
  154. },
  155. }, defaultEvidenceTime)
  156. v := vote.ToProto()
  157. err := val.SignVote(evidenceChainID, v)
  158. if err != nil {
  159. panic("verify_test: failed to sign vote for header")
  160. }
  161. vote.Signature = v.Signature
  162. return vote
  163. }