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.

252 lines
7.0 KiB

7 years ago
  1. package evidence
  2. import (
  3. "os"
  4. "testing"
  5. "time"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/require"
  8. dbm "github.com/tendermint/tm-db"
  9. sm "github.com/tendermint/tendermint/state"
  10. "github.com/tendermint/tendermint/store"
  11. "github.com/tendermint/tendermint/types"
  12. tmtime "github.com/tendermint/tendermint/types/time"
  13. )
  14. func TestMain(m *testing.M) {
  15. RegisterMockEvidences()
  16. code := m.Run()
  17. os.Exit(code)
  18. }
  19. func TestEvidencePool(t *testing.T) {
  20. var (
  21. valAddr = []byte("val1")
  22. height = int64(52)
  23. stateDB = initializeValidatorState(valAddr, height)
  24. evidenceDB = dbm.NewMemDB()
  25. blockStoreDB = dbm.NewMemDB()
  26. blockStore = initializeBlockStore(blockStoreDB, sm.LoadState(stateDB), valAddr)
  27. evidenceTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
  28. goodEvidence = types.NewMockEvidence(height, time.Now(), valAddr)
  29. badEvidence = types.NewMockEvidence(1, evidenceTime, valAddr)
  30. )
  31. pool, err := NewPool(stateDB, evidenceDB, blockStore)
  32. require.NoError(t, err)
  33. // bad evidence
  34. err = pool.AddEvidence(badEvidence)
  35. if assert.Error(t, err) {
  36. assert.Contains(t, err.Error(), "is too old; min height is 32 and evidence can not be older than")
  37. }
  38. // good evidence
  39. evAdded := make(chan struct{})
  40. go func() {
  41. <-pool.EvidenceWaitChan()
  42. close(evAdded)
  43. }()
  44. err = pool.AddEvidence(goodEvidence)
  45. require.NoError(t, err)
  46. select {
  47. case <-evAdded:
  48. case <-time.After(5 * time.Second):
  49. t.Fatal("evidence was not added after 5s")
  50. }
  51. assert.Equal(t, 1, pool.evidenceList.Len())
  52. // if we send it again, it shouldnt add and return an error
  53. err = pool.AddEvidence(goodEvidence)
  54. assert.Error(t, err)
  55. assert.Equal(t, 1, pool.evidenceList.Len())
  56. }
  57. func TestEvidencePoolIsCommitted(t *testing.T) {
  58. var (
  59. valAddr = []byte("validator_address")
  60. height = int64(1)
  61. lastBlockTime = time.Now()
  62. stateDB = initializeValidatorState(valAddr, height)
  63. evidenceDB = dbm.NewMemDB()
  64. blockStoreDB = dbm.NewMemDB()
  65. blockStore = initializeBlockStore(blockStoreDB, sm.LoadState(stateDB), valAddr)
  66. )
  67. pool, err := NewPool(stateDB, evidenceDB, blockStore)
  68. require.NoError(t, err)
  69. // evidence not seen yet:
  70. evidence := types.NewMockEvidence(height, time.Now(), valAddr)
  71. assert.False(t, pool.IsCommitted(evidence))
  72. // evidence seen but not yet committed:
  73. assert.NoError(t, pool.AddEvidence(evidence))
  74. assert.False(t, pool.IsCommitted(evidence))
  75. // evidence seen and committed:
  76. pool.MarkEvidenceAsCommitted(height, lastBlockTime, []types.Evidence{evidence})
  77. assert.True(t, pool.IsCommitted(evidence))
  78. }
  79. func TestEvidencePoolAddEvidence(t *testing.T) {
  80. var (
  81. valAddr = []byte("val1")
  82. height = int64(30)
  83. stateDB = initializeValidatorState(valAddr, height)
  84. evidenceDB = dbm.NewMemDB()
  85. blockStoreDB = dbm.NewMemDB()
  86. blockStore = initializeBlockStore(blockStoreDB, sm.LoadState(stateDB), valAddr)
  87. evidenceTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
  88. )
  89. pool, err := NewPool(stateDB, evidenceDB, blockStore)
  90. require.NoError(t, err)
  91. testCases := []struct {
  92. evHeight int64
  93. evTime time.Time
  94. expErr bool
  95. evDescription string
  96. }{
  97. {height, time.Now(), false, "valid evidence"},
  98. {height, evidenceTime, false, "valid evidence (despite old time)"},
  99. {int64(1), time.Now(), false, "valid evidence (despite old height)"},
  100. {int64(1), evidenceTime, true,
  101. "evidence from height 1 (created at: 2019-01-01 00:00:00 +0000 UTC) is too old"},
  102. }
  103. for _, tc := range testCases {
  104. tc := tc
  105. t.Run(tc.evDescription, func(t *testing.T) {
  106. ev := types.NewMockEvidence(tc.evHeight, tc.evTime, valAddr)
  107. err := pool.AddEvidence(ev)
  108. if tc.expErr {
  109. assert.Error(t, err)
  110. t.Log(err)
  111. }
  112. })
  113. }
  114. }
  115. func TestEvidencePoolUpdate(t *testing.T) {
  116. var (
  117. valAddr = []byte("validator_address")
  118. height = int64(1)
  119. stateDB = initializeValidatorState(valAddr, height)
  120. evidenceDB = dbm.NewMemDB()
  121. blockStoreDB = dbm.NewMemDB()
  122. state = sm.LoadState(stateDB)
  123. blockStore = initializeBlockStore(blockStoreDB, state, valAddr)
  124. )
  125. pool, err := NewPool(stateDB, evidenceDB, blockStore)
  126. require.NoError(t, err)
  127. // create new block (no need to save it to blockStore)
  128. evidence := types.NewMockEvidence(height, time.Now(), valAddr)
  129. lastCommit := makeCommit(height, valAddr)
  130. block := types.MakeBlock(height+1, []types.Tx{}, lastCommit, []types.Evidence{evidence})
  131. // update state (partially)
  132. state.LastBlockHeight = height + 1
  133. pool.Update(block, state)
  134. // a) Update marks evidence as committed
  135. assert.True(t, pool.IsCommitted(evidence))
  136. // b) Update updates valToLastHeight map
  137. assert.Equal(t, height+1, pool.ValidatorLastHeight(valAddr))
  138. }
  139. func TestEvidencePoolNewPool(t *testing.T) {
  140. var (
  141. valAddr = []byte("validator_address")
  142. height = int64(1)
  143. stateDB = initializeValidatorState(valAddr, height)
  144. evidenceDB = dbm.NewMemDB()
  145. blockStoreDB = dbm.NewMemDB()
  146. state = sm.LoadState(stateDB)
  147. blockStore = initializeBlockStore(blockStoreDB, state, valAddr)
  148. )
  149. pool, err := NewPool(stateDB, evidenceDB, blockStore)
  150. require.NoError(t, err)
  151. assert.Equal(t, height, pool.ValidatorLastHeight(valAddr))
  152. assert.EqualValues(t, 0, pool.ValidatorLastHeight([]byte("non-existent-validator")))
  153. }
  154. func initializeValidatorState(valAddr []byte, height int64) dbm.DB {
  155. stateDB := dbm.NewMemDB()
  156. // create validator set and state
  157. valSet := &types.ValidatorSet{
  158. Validators: []*types.Validator{
  159. {Address: valAddr, VotingPower: 0},
  160. },
  161. }
  162. state := sm.State{
  163. LastBlockHeight: height,
  164. LastBlockTime: tmtime.Now(),
  165. LastValidators: valSet,
  166. Validators: valSet,
  167. NextValidators: valSet.CopyIncrementProposerPriority(1),
  168. LastHeightValidatorsChanged: 1,
  169. ConsensusParams: types.ConsensusParams{
  170. Block: types.BlockParams{
  171. MaxBytes: 22020096,
  172. MaxGas: -1,
  173. },
  174. Evidence: types.EvidenceParams{
  175. MaxAgeNumBlocks: 20,
  176. MaxAgeDuration: 48 * time.Hour,
  177. },
  178. },
  179. }
  180. // save all states up to height
  181. for i := int64(0); i <= height; i++ {
  182. state.LastBlockHeight = i
  183. sm.SaveState(stateDB, state)
  184. }
  185. return stateDB
  186. }
  187. // initializeBlockStore creates a block storage and populates it w/ a dummy
  188. // block at +height+.
  189. func initializeBlockStore(db dbm.DB, state sm.State, valAddr []byte) *store.BlockStore {
  190. blockStore := store.NewBlockStore(db)
  191. for i := int64(1); i <= state.LastBlockHeight; i++ {
  192. lastCommit := makeCommit(i-1, valAddr)
  193. block, _ := state.MakeBlock(i, []types.Tx{}, lastCommit, nil,
  194. state.Validators.GetProposer().Address)
  195. const parts = 1
  196. partSet := block.MakePartSet(parts)
  197. seenCommit := makeCommit(i, valAddr)
  198. blockStore.SaveBlock(block, partSet, seenCommit)
  199. }
  200. return blockStore
  201. }
  202. func makeCommit(height int64, valAddr []byte) *types.Commit {
  203. commitSigs := []types.CommitSig{{
  204. BlockIDFlag: types.BlockIDFlagCommit,
  205. ValidatorAddress: valAddr,
  206. Timestamp: time.Now(),
  207. Signature: []byte("Signature"),
  208. }}
  209. return types.NewCommit(height, 0, types.BlockID{}, commitSigs)
  210. }