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.

203 lines
5.4 KiB

abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
abci: Synchronize FinalizeBlock with the updated specification (#7983) This change set implements the most recent version of `FinalizeBlock`. # What does this change actually contain? * This change set is rather large but fear not! The majority of the files touched and changes are renaming `ResponseDeliverTx` to `ExecTxResult`. This should be a pretty inoffensive change since they're effectively the same type but with a different name. * The `execBlockOnProxyApp` was totally removed since it served as just a wrapper around the logic that is now mostly encapsulated within `FinalizeBlock` * The `updateState` helper function has been made a public method on `State`. It was being exposed as a shim through the testing infrastructure, so this seemed innocuous. * Tests already existed to ensure that the application received the `ByzantineValidators` and the `ValidatorUpdates`, but one was fixed up to ensure that `LastCommitInfo` was being sent across. * Tests were removed from the `psql` indexer that seemed to search for an event in the indexer that was not being created. # Questions for reviewers * We store this [ABCIResponses](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/proto/tendermint/state/types.pb.go#L37) type in the data base as the block results. This type has changed since v0.35 to contain the `FinalizeBlock` response. I'm wondering if we need to do any shimming to keep the old data retrieveable? * Similarly, this change is exposed via the RPC through [ResultBlockResults](https://github.com/tendermint/tendermint/blob/5721a13ab1f4479f9807f449f0bf5c536b9a05f2/rpc/coretypes/responses.go#L69) changing. Should we somehow shim or notify for this change? closes: #7658
2 years ago
  1. package commands
  2. import (
  3. "context"
  4. "errors"
  5. "testing"
  6. "github.com/spf13/cobra"
  7. "github.com/stretchr/testify/mock"
  8. "github.com/stretchr/testify/require"
  9. dbm "github.com/tendermint/tm-db"
  10. abcitypes "github.com/tendermint/tendermint/abci/types"
  11. "github.com/tendermint/tendermint/config"
  12. "github.com/tendermint/tendermint/internal/state/indexer"
  13. "github.com/tendermint/tendermint/internal/state/mocks"
  14. "github.com/tendermint/tendermint/libs/log"
  15. prototmstate "github.com/tendermint/tendermint/proto/tendermint/state"
  16. "github.com/tendermint/tendermint/types"
  17. _ "github.com/lib/pq" // for the psql sink
  18. )
  19. const (
  20. height int64 = 10
  21. base int64 = 2
  22. )
  23. func setupReIndexEventCmd(ctx context.Context, conf *config.Config, logger log.Logger) *cobra.Command {
  24. cmd := MakeReindexEventCommand(conf, logger)
  25. reIndexEventCmd := &cobra.Command{
  26. Use: cmd.Use,
  27. Run: func(cmd *cobra.Command, args []string) {},
  28. }
  29. _ = reIndexEventCmd.ExecuteContext(ctx)
  30. return reIndexEventCmd
  31. }
  32. func TestReIndexEventCheckHeight(t *testing.T) {
  33. mockBlockStore := &mocks.BlockStore{}
  34. mockBlockStore.
  35. On("Base").Return(base).
  36. On("Height").Return(height)
  37. testCases := []struct {
  38. startHeight int64
  39. endHeight int64
  40. validHeight bool
  41. }{
  42. {0, 0, true},
  43. {0, base, true},
  44. {0, base - 1, false},
  45. {0, height, true},
  46. {0, height + 1, true},
  47. {0, 0, true},
  48. {base - 1, 0, false},
  49. {base, 0, true},
  50. {base, base, true},
  51. {base, base - 1, false},
  52. {base, height, true},
  53. {base, height + 1, true},
  54. {height, 0, true},
  55. {height, base, false},
  56. {height, height - 1, false},
  57. {height, height, true},
  58. {height, height + 1, true},
  59. {height + 1, 0, false},
  60. }
  61. for _, tc := range testCases {
  62. err := checkValidHeight(mockBlockStore, checkValidHeightArgs{startHeight: tc.startHeight, endHeight: tc.endHeight})
  63. if tc.validHeight {
  64. require.NoError(t, err)
  65. } else {
  66. require.Error(t, err)
  67. }
  68. }
  69. }
  70. func TestLoadEventSink(t *testing.T) {
  71. testCases := []struct {
  72. sinks []string
  73. connURL string
  74. loadErr bool
  75. }{
  76. {[]string{}, "", true},
  77. {[]string{"NULL"}, "", true},
  78. {[]string{"KV"}, "", false},
  79. {[]string{"KV", "KV"}, "", true},
  80. {[]string{"PSQL"}, "", true}, // true because empty connect url
  81. {[]string{"PSQL"}, "wrongUrl", true}, // true because wrong connect url
  82. // skip to test PSQL connect with correct url
  83. {[]string{"UnsupportedSinkType"}, "wrongUrl", true},
  84. }
  85. for _, tc := range testCases {
  86. cfg := config.TestConfig()
  87. cfg.TxIndex.Indexer = tc.sinks
  88. cfg.TxIndex.PsqlConn = tc.connURL
  89. _, err := loadEventSinks(cfg)
  90. if tc.loadErr {
  91. require.Error(t, err)
  92. } else {
  93. require.NoError(t, err)
  94. }
  95. }
  96. }
  97. func TestLoadBlockStore(t *testing.T) {
  98. testCfg, err := config.ResetTestRoot(t.TempDir(), t.Name())
  99. require.NoError(t, err)
  100. testCfg.DBBackend = "goleveldb"
  101. _, _, err = loadStateAndBlockStore(testCfg)
  102. // we should return an error because the state store and block store
  103. // don't yet exist
  104. require.Error(t, err)
  105. dbType := dbm.BackendType(testCfg.DBBackend)
  106. bsdb, err := dbm.NewDB("blockstore", dbType, testCfg.DBDir())
  107. require.NoError(t, err)
  108. bsdb.Close()
  109. ssdb, err := dbm.NewDB("state", dbType, testCfg.DBDir())
  110. require.NoError(t, err)
  111. ssdb.Close()
  112. bs, ss, err := loadStateAndBlockStore(testCfg)
  113. require.NoError(t, err)
  114. require.NotNil(t, bs)
  115. require.NotNil(t, ss)
  116. }
  117. func TestReIndexEvent(t *testing.T) {
  118. mockBlockStore := &mocks.BlockStore{}
  119. mockStateStore := &mocks.Store{}
  120. mockEventSink := &mocks.EventSink{}
  121. mockBlockStore.
  122. On("Base").Return(base).
  123. On("Height").Return(height).
  124. On("LoadBlock", base).Return(nil).Once().
  125. On("LoadBlock", base).Return(&types.Block{Data: types.Data{Txs: types.Txs{make(types.Tx, 1)}}}).
  126. On("LoadBlock", height).Return(&types.Block{Data: types.Data{Txs: types.Txs{make(types.Tx, 1)}}})
  127. mockEventSink.
  128. On("Type").Return(indexer.KV).
  129. On("IndexBlockEvents", mock.AnythingOfType("types.EventDataNewBlockHeader")).Return(errors.New("")).Once().
  130. On("IndexBlockEvents", mock.AnythingOfType("types.EventDataNewBlockHeader")).Return(nil).
  131. On("IndexTxEvents", mock.AnythingOfType("[]*types.TxResult")).Return(errors.New("")).Once().
  132. On("IndexTxEvents", mock.AnythingOfType("[]*types.TxResult")).Return(nil)
  133. dtx := abcitypes.ExecTxResult{}
  134. abciResp := &prototmstate.ABCIResponses{
  135. FinalizeBlock: &abcitypes.ResponseFinalizeBlock{
  136. TxResults: []*abcitypes.ExecTxResult{&dtx},
  137. },
  138. }
  139. mockStateStore.
  140. On("LoadABCIResponses", base).Return(nil, errors.New("")).Once().
  141. On("LoadABCIResponses", base).Return(abciResp, nil).
  142. On("LoadABCIResponses", height).Return(abciResp, nil)
  143. testCases := []struct {
  144. startHeight int64
  145. endHeight int64
  146. reIndexErr bool
  147. }{
  148. {base, height, true}, // LoadBlock error
  149. {base, height, true}, // LoadABCIResponses error
  150. {base, height, true}, // index block event error
  151. {base, height, true}, // index tx event error
  152. {base, base, false},
  153. {height, height, false},
  154. }
  155. ctx, cancel := context.WithCancel(context.Background())
  156. defer cancel()
  157. logger := log.NewNopLogger()
  158. conf := config.DefaultConfig()
  159. for _, tc := range testCases {
  160. err := eventReIndex(
  161. setupReIndexEventCmd(ctx, conf, logger),
  162. eventReIndexArgs{
  163. sinks: []indexer.EventSink{mockEventSink},
  164. blockStore: mockBlockStore,
  165. stateStore: mockStateStore,
  166. startHeight: tc.startHeight,
  167. endHeight: tc.endHeight,
  168. })
  169. if tc.reIndexErr {
  170. require.Error(t, err)
  171. } else {
  172. require.NoError(t, err)
  173. }
  174. }
  175. }