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.

696 lines
16 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
8 years ago
9 years ago
7 years ago
9 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
3 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
3 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
3 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
3 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
3 years ago
9 years ago
lint: Enable Golint (#4212) * Fix many golint errors * Fix golint errors in the 'lite' package * Don't export Pool.store * Fix typo * Revert unwanted changes * Fix errors in counter package * Fix linter errors in kvstore package * Fix linter error in example package * Fix error in tests package * Fix linter errors in v2 package * Fix linter errors in consensus package * Fix linter errors in evidence package * Fix linter error in fail package * Fix linter errors in query package * Fix linter errors in core package * Fix linter errors in node package * Fix linter errors in mempool package * Fix linter error in conn package * Fix linter errors in pex package * Rename PEXReactor export to Reactor * Fix linter errors in trust package * Fix linter errors in upnp package * Fix linter errors in p2p package * Fix linter errors in proxy package * Fix linter errors in mock_test package * Fix linter error in client_test package * Fix linter errors in coretypes package * Fix linter errors in coregrpc package * Fix linter errors in rpcserver package * Fix linter errors in rpctypes package * Fix linter errors in rpctest package * Fix linter error in json2wal script * Fix linter error in wal2json script * Fix linter errors in kv package * Fix linter error in state package * Fix linter error in grpc_client * Fix linter errors in types package * Fix linter error in version package * Fix remaining errors * Address review comments * Fix broken tests * Reconcile package coregrpc * Fix golangci bot error * Fix new golint errors * Fix broken reference * Enable golint linter * minor changes to bring golint into line * fix failing test * fix pex reactor naming * address PR comments
5 years ago
7 years ago
7 years ago
7 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
3 years ago
9 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
3 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
3 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
3 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
3 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package main
  2. import (
  3. "bufio"
  4. "encoding/hex"
  5. "errors"
  6. "fmt"
  7. "io"
  8. "os"
  9. "os/signal"
  10. "strings"
  11. "syscall"
  12. "github.com/spf13/cobra"
  13. "github.com/tendermint/tendermint/libs/log"
  14. "github.com/tendermint/tendermint/version"
  15. abciclient "github.com/tendermint/tendermint/abci/client"
  16. "github.com/tendermint/tendermint/abci/example/code"
  17. "github.com/tendermint/tendermint/abci/example/kvstore"
  18. "github.com/tendermint/tendermint/abci/server"
  19. servertest "github.com/tendermint/tendermint/abci/tests/server"
  20. "github.com/tendermint/tendermint/abci/types"
  21. "github.com/tendermint/tendermint/proto/tendermint/crypto"
  22. )
  23. // client is a global variable so it can be reused by the console
  24. var (
  25. client abciclient.Client
  26. )
  27. // flags
  28. var (
  29. // global
  30. flagAddress string
  31. flagAbci string
  32. flagVerbose bool // for the println output
  33. flagLogLevel string // for the logger
  34. // query
  35. flagPath string
  36. flagHeight int
  37. flagProve bool
  38. // kvstore
  39. flagPersist string
  40. )
  41. func RootCmmand(logger log.Logger) *cobra.Command {
  42. return &cobra.Command{
  43. Use: "abci-cli",
  44. Short: "the ABCI CLI tool wraps an ABCI client",
  45. Long: "the ABCI CLI tool wraps an ABCI client and is used for testing ABCI servers",
  46. PersistentPreRunE: func(cmd *cobra.Command, args []string) (err error) {
  47. switch cmd.Use {
  48. case "kvstore", "version":
  49. return nil
  50. }
  51. if client == nil {
  52. var err error
  53. client, err = abciclient.NewClient(logger.With("module", "abci-client"), flagAddress, flagAbci, false)
  54. if err != nil {
  55. return err
  56. }
  57. if err := client.Start(cmd.Context()); err != nil {
  58. return err
  59. }
  60. }
  61. return nil
  62. },
  63. }
  64. }
  65. // Structure for data passed to print response.
  66. type response struct {
  67. // generic abci response
  68. Data []byte
  69. Code uint32
  70. Info string
  71. Log string
  72. Query *queryResponse
  73. }
  74. type queryResponse struct {
  75. Key []byte
  76. Value []byte
  77. Height int64
  78. ProofOps *crypto.ProofOps
  79. }
  80. func Execute() error {
  81. logger, err := log.NewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo)
  82. if err != nil {
  83. return err
  84. }
  85. cmd := RootCmmand(logger)
  86. addGlobalFlags(cmd)
  87. addCommands(cmd, logger)
  88. return cmd.Execute()
  89. }
  90. func addGlobalFlags(cmd *cobra.Command) {
  91. cmd.PersistentFlags().StringVarP(&flagAddress,
  92. "address",
  93. "",
  94. "tcp://0.0.0.0:26658",
  95. "address of application socket")
  96. cmd.PersistentFlags().StringVarP(&flagAbci, "abci", "", "socket", "either socket or grpc")
  97. cmd.PersistentFlags().BoolVarP(&flagVerbose,
  98. "verbose",
  99. "v",
  100. false,
  101. "print the command and results as if it were a console session")
  102. cmd.PersistentFlags().StringVarP(&flagLogLevel, "log_level", "", "debug", "set the logger level")
  103. }
  104. func addCommands(cmd *cobra.Command, logger log.Logger) {
  105. cmd.AddCommand(batchCmd)
  106. cmd.AddCommand(consoleCmd)
  107. cmd.AddCommand(echoCmd)
  108. cmd.AddCommand(infoCmd)
  109. cmd.AddCommand(finalizeBlockCmd)
  110. cmd.AddCommand(checkTxCmd)
  111. cmd.AddCommand(commitCmd)
  112. cmd.AddCommand(versionCmd)
  113. cmd.AddCommand(testCmd)
  114. cmd.AddCommand(getQueryCmd())
  115. // examples
  116. cmd.AddCommand(getKVStoreCmd(logger))
  117. }
  118. var batchCmd = &cobra.Command{
  119. Use: "batch",
  120. Short: "run a batch of abci commands against an application",
  121. Long: `run a batch of abci commands against an application
  122. This command is run by piping in a file containing a series of commands
  123. you'd like to run:
  124. abci-cli batch < example.file
  125. where example.file looks something like:
  126. check_tx 0x00
  127. check_tx 0xff
  128. finalize_block 0x00
  129. check_tx 0x00
  130. finalize_block 0x01 0x04 0xff
  131. info
  132. `,
  133. Args: cobra.ExactArgs(0),
  134. RunE: cmdBatch,
  135. }
  136. var consoleCmd = &cobra.Command{
  137. Use: "console",
  138. Short: "start an interactive ABCI console for multiple commands",
  139. Long: `start an interactive ABCI console for multiple commands
  140. This command opens an interactive console for running any of the other commands
  141. without opening a new connection each time
  142. `,
  143. Args: cobra.ExactArgs(0),
  144. ValidArgs: []string{"echo", "info", "finalize_block", "check_tx", "commit", "query"},
  145. RunE: cmdConsole,
  146. }
  147. var echoCmd = &cobra.Command{
  148. Use: "echo",
  149. Short: "have the application echo a message",
  150. Long: "have the application echo a message",
  151. Args: cobra.ExactArgs(1),
  152. RunE: cmdEcho,
  153. }
  154. var infoCmd = &cobra.Command{
  155. Use: "info",
  156. Short: "get some info about the application",
  157. Long: "get some info about the application",
  158. Args: cobra.ExactArgs(0),
  159. RunE: cmdInfo,
  160. }
  161. var finalizeBlockCmd = &cobra.Command{
  162. Use: "finalize_block",
  163. Short: "deliver a block of transactions to the application",
  164. Long: "deliver a block of transactions to the application",
  165. Args: cobra.MinimumNArgs(1),
  166. RunE: cmdFinalizeBlock,
  167. }
  168. var checkTxCmd = &cobra.Command{
  169. Use: "check_tx",
  170. Short: "validate a transaction",
  171. Long: "validate a transaction",
  172. Args: cobra.ExactArgs(1),
  173. RunE: cmdCheckTx,
  174. }
  175. var commitCmd = &cobra.Command{
  176. Use: "commit",
  177. Short: "commit the application state and return the Merkle root hash",
  178. Long: "commit the application state and return the Merkle root hash",
  179. Args: cobra.ExactArgs(0),
  180. RunE: cmdCommit,
  181. }
  182. var versionCmd = &cobra.Command{
  183. Use: "version",
  184. Short: "print ABCI console version",
  185. Long: "print ABCI console version",
  186. Args: cobra.ExactArgs(0),
  187. RunE: func(cmd *cobra.Command, args []string) error {
  188. fmt.Println(version.ABCIVersion)
  189. return nil
  190. },
  191. }
  192. func getQueryCmd() *cobra.Command {
  193. cmd := &cobra.Command{
  194. Use: "query",
  195. Short: "query the application state",
  196. Long: "query the application state",
  197. Args: cobra.ExactArgs(1),
  198. RunE: cmdQuery,
  199. }
  200. cmd.PersistentFlags().StringVarP(&flagPath, "path", "", "/store", "path to prefix query with")
  201. cmd.PersistentFlags().IntVarP(&flagHeight, "height", "", 0, "height to query the blockchain at")
  202. cmd.PersistentFlags().BoolVarP(&flagProve,
  203. "prove",
  204. "",
  205. false,
  206. "whether or not to return a merkle proof of the query result")
  207. return cmd
  208. }
  209. func getKVStoreCmd(logger log.Logger) *cobra.Command {
  210. cmd := &cobra.Command{
  211. Use: "kvstore",
  212. Short: "ABCI demo example",
  213. Long: "ABCI demo example",
  214. Args: cobra.ExactArgs(0),
  215. RunE: makeKVStoreCmd(logger),
  216. }
  217. cmd.PersistentFlags().StringVarP(&flagPersist, "persist", "", "", "directory to use for a database")
  218. return cmd
  219. }
  220. var testCmd = &cobra.Command{
  221. Use: "test",
  222. Short: "run integration tests",
  223. Long: "run integration tests",
  224. Args: cobra.ExactArgs(0),
  225. RunE: cmdTest,
  226. }
  227. // Generates new Args array based off of previous call args to maintain flag persistence
  228. func persistentArgs(line []byte) []string {
  229. // generate the arguments to run from original os.Args
  230. // to maintain flag arguments
  231. args := os.Args
  232. args = args[:len(args)-1] // remove the previous command argument
  233. if len(line) > 0 { // prevents introduction of extra space leading to argument parse errors
  234. args = append(args, strings.Split(string(line), " ")...)
  235. }
  236. return args
  237. }
  238. //--------------------------------------------------------------------------------
  239. func compose(fs []func() error) error {
  240. if len(fs) == 0 {
  241. return nil
  242. }
  243. err := fs[0]()
  244. if err == nil {
  245. return compose(fs[1:])
  246. }
  247. return err
  248. }
  249. func cmdTest(cmd *cobra.Command, args []string) error {
  250. ctx := cmd.Context()
  251. return compose(
  252. []func() error{
  253. func() error { return servertest.InitChain(ctx, client) },
  254. func() error { return servertest.Commit(ctx, client, nil) },
  255. func() error {
  256. return servertest.FinalizeBlock(ctx, client, [][]byte{
  257. []byte("abc"),
  258. }, []uint32{
  259. code.CodeTypeBadNonce,
  260. }, nil)
  261. },
  262. func() error { return servertest.Commit(ctx, client, nil) },
  263. func() error {
  264. return servertest.FinalizeBlock(ctx, client, [][]byte{
  265. {0x00},
  266. }, []uint32{
  267. code.CodeTypeOK,
  268. }, nil)
  269. },
  270. func() error { return servertest.Commit(ctx, client, []byte{0, 0, 0, 0, 0, 0, 0, 1}) },
  271. func() error {
  272. return servertest.FinalizeBlock(ctx, client, [][]byte{
  273. {0x00},
  274. {0x01},
  275. {0x00, 0x02},
  276. {0x00, 0x03},
  277. {0x00, 0x00, 0x04},
  278. {0x00, 0x00, 0x06},
  279. }, []uint32{
  280. code.CodeTypeBadNonce,
  281. code.CodeTypeOK,
  282. code.CodeTypeOK,
  283. code.CodeTypeOK,
  284. code.CodeTypeOK,
  285. code.CodeTypeBadNonce,
  286. }, nil)
  287. },
  288. func() error { return servertest.Commit(ctx, client, []byte{0, 0, 0, 0, 0, 0, 0, 5}) },
  289. })
  290. }
  291. func cmdBatch(cmd *cobra.Command, args []string) error {
  292. bufReader := bufio.NewReader(os.Stdin)
  293. LOOP:
  294. for {
  295. line, more, err := bufReader.ReadLine()
  296. switch {
  297. case more:
  298. return errors.New("input line is too long")
  299. case err == io.EOF:
  300. break LOOP
  301. case len(line) == 0:
  302. continue
  303. case err != nil:
  304. return err
  305. }
  306. cmdArgs := persistentArgs(line)
  307. if err := muxOnCommands(cmd, cmdArgs); err != nil {
  308. return err
  309. }
  310. fmt.Println()
  311. }
  312. return nil
  313. }
  314. func cmdConsole(cmd *cobra.Command, args []string) error {
  315. for {
  316. fmt.Printf("> ")
  317. bufReader := bufio.NewReader(os.Stdin)
  318. line, more, err := bufReader.ReadLine()
  319. if more {
  320. return errors.New("input is too long")
  321. } else if err != nil {
  322. return err
  323. }
  324. pArgs := persistentArgs(line)
  325. if err := muxOnCommands(cmd, pArgs); err != nil {
  326. return err
  327. }
  328. }
  329. }
  330. func muxOnCommands(cmd *cobra.Command, pArgs []string) error {
  331. if len(pArgs) < 2 {
  332. return errors.New("expecting persistent args of the form: abci-cli [command] <...>")
  333. }
  334. // TODO: this parsing is fragile
  335. args := []string{}
  336. for i := 0; i < len(pArgs); i++ {
  337. arg := pArgs[i]
  338. // check for flags
  339. if strings.HasPrefix(arg, "-") {
  340. // if it has an equal, we can just skip
  341. if strings.Contains(arg, "=") {
  342. continue
  343. }
  344. // if its a boolean, we can just skip
  345. _, err := cmd.Flags().GetBool(strings.TrimLeft(arg, "-"))
  346. if err == nil {
  347. continue
  348. }
  349. // otherwise, we need to skip the next one too
  350. i++
  351. continue
  352. }
  353. // append the actual arg
  354. args = append(args, arg)
  355. }
  356. var subCommand string
  357. var actualArgs []string
  358. if len(args) > 1 {
  359. subCommand = args[1]
  360. }
  361. if len(args) > 2 {
  362. actualArgs = args[2:]
  363. }
  364. cmd.Use = subCommand // for later print statements ...
  365. switch strings.ToLower(subCommand) {
  366. case "check_tx":
  367. return cmdCheckTx(cmd, actualArgs)
  368. case "commit":
  369. return cmdCommit(cmd, actualArgs)
  370. case "finalize_block":
  371. return cmdFinalizeBlock(cmd, actualArgs)
  372. case "echo":
  373. return cmdEcho(cmd, actualArgs)
  374. case "info":
  375. return cmdInfo(cmd, actualArgs)
  376. case "query":
  377. return cmdQuery(cmd, actualArgs)
  378. default:
  379. return cmdUnimplemented(cmd, pArgs)
  380. }
  381. }
  382. func cmdUnimplemented(cmd *cobra.Command, args []string) error {
  383. msg := "unimplemented command"
  384. if len(args) > 0 {
  385. msg += fmt.Sprintf(" args: [%s]", strings.Join(args, " "))
  386. }
  387. printResponse(cmd, args, response{
  388. Code: codeBad,
  389. Log: msg,
  390. })
  391. fmt.Println("Available commands:")
  392. for _, cmd := range cmd.Commands() {
  393. fmt.Printf("%s: %s\n", cmd.Use, cmd.Short)
  394. }
  395. fmt.Println("Use \"[command] --help\" for more information about a command.")
  396. return nil
  397. }
  398. // Have the application echo a message
  399. func cmdEcho(cmd *cobra.Command, args []string) error {
  400. msg := ""
  401. if len(args) > 0 {
  402. msg = args[0]
  403. }
  404. res, err := client.Echo(cmd.Context(), msg)
  405. if err != nil {
  406. return err
  407. }
  408. printResponse(cmd, args, response{
  409. Data: []byte(res.Message),
  410. })
  411. return nil
  412. }
  413. // Get some info from the application
  414. func cmdInfo(cmd *cobra.Command, args []string) error {
  415. var version string
  416. if len(args) == 1 {
  417. version = args[0]
  418. }
  419. res, err := client.Info(cmd.Context(), types.RequestInfo{Version: version})
  420. if err != nil {
  421. return err
  422. }
  423. printResponse(cmd, args, response{
  424. Data: []byte(res.Data),
  425. })
  426. return nil
  427. }
  428. const codeBad uint32 = 10
  429. // Append a new tx to application
  430. func cmdFinalizeBlock(cmd *cobra.Command, args []string) error {
  431. if len(args) == 0 {
  432. printResponse(cmd, args, response{
  433. Code: codeBad,
  434. Log: "Must provide at least one transaction",
  435. })
  436. return nil
  437. }
  438. txs := make([][]byte, len(args))
  439. for i, arg := range args {
  440. txBytes, err := stringOrHexToBytes(arg)
  441. if err != nil {
  442. return err
  443. }
  444. txs[i] = txBytes
  445. }
  446. res, err := client.FinalizeBlock(cmd.Context(), types.RequestFinalizeBlock{Txs: txs})
  447. if err != nil {
  448. return err
  449. }
  450. for _, tx := range res.TxResults {
  451. printResponse(cmd, args, response{
  452. Code: tx.Code,
  453. Data: tx.Data,
  454. Info: tx.Info,
  455. Log: tx.Log,
  456. })
  457. }
  458. return nil
  459. }
  460. // Validate a tx
  461. func cmdCheckTx(cmd *cobra.Command, args []string) error {
  462. if len(args) == 0 {
  463. printResponse(cmd, args, response{
  464. Code: codeBad,
  465. Info: "want the tx",
  466. })
  467. return nil
  468. }
  469. txBytes, err := stringOrHexToBytes(args[0])
  470. if err != nil {
  471. return err
  472. }
  473. res, err := client.CheckTx(cmd.Context(), types.RequestCheckTx{Tx: txBytes})
  474. if err != nil {
  475. return err
  476. }
  477. printResponse(cmd, args, response{
  478. Code: res.Code,
  479. Data: res.Data,
  480. Info: res.Info,
  481. Log: res.Log,
  482. })
  483. return nil
  484. }
  485. // Get application Merkle root hash
  486. func cmdCommit(cmd *cobra.Command, args []string) error {
  487. res, err := client.Commit(cmd.Context())
  488. if err != nil {
  489. return err
  490. }
  491. printResponse(cmd, args, response{
  492. Data: res.Data,
  493. })
  494. return nil
  495. }
  496. // Query application state
  497. func cmdQuery(cmd *cobra.Command, args []string) error {
  498. if len(args) == 0 {
  499. printResponse(cmd, args, response{
  500. Code: codeBad,
  501. Info: "want the query",
  502. Log: "",
  503. })
  504. return nil
  505. }
  506. queryBytes, err := stringOrHexToBytes(args[0])
  507. if err != nil {
  508. return err
  509. }
  510. resQuery, err := client.Query(cmd.Context(), types.RequestQuery{
  511. Data: queryBytes,
  512. Path: flagPath,
  513. Height: int64(flagHeight),
  514. Prove: flagProve,
  515. })
  516. if err != nil {
  517. return err
  518. }
  519. printResponse(cmd, args, response{
  520. Code: resQuery.Code,
  521. Info: resQuery.Info,
  522. Log: resQuery.Log,
  523. Query: &queryResponse{
  524. Key: resQuery.Key,
  525. Value: resQuery.Value,
  526. Height: resQuery.Height,
  527. ProofOps: resQuery.ProofOps,
  528. },
  529. })
  530. return nil
  531. }
  532. func makeKVStoreCmd(logger log.Logger) func(*cobra.Command, []string) error {
  533. return func(cmd *cobra.Command, args []string) error {
  534. // Create the application - in memory or persisted to disk
  535. var app types.Application
  536. if flagPersist == "" {
  537. app = kvstore.NewApplication()
  538. } else {
  539. app = kvstore.NewPersistentKVStoreApplication(logger, flagPersist)
  540. }
  541. // Start the listener
  542. srv, err := server.NewServer(logger.With("module", "abci-server"), flagAddress, flagAbci, app)
  543. if err != nil {
  544. return err
  545. }
  546. ctx, cancel := signal.NotifyContext(cmd.Context(), syscall.SIGTERM)
  547. defer cancel()
  548. if err := srv.Start(ctx); err != nil {
  549. return err
  550. }
  551. // Run forever.
  552. <-ctx.Done()
  553. return nil
  554. }
  555. }
  556. //--------------------------------------------------------------------------------
  557. func printResponse(cmd *cobra.Command, args []string, rsp response) {
  558. if flagVerbose {
  559. fmt.Println(">", cmd.Use, strings.Join(args, " "))
  560. }
  561. // Always print the status code.
  562. if rsp.Code == types.CodeTypeOK {
  563. fmt.Printf("-> code: OK\n")
  564. } else {
  565. fmt.Printf("-> code: %d\n", rsp.Code)
  566. }
  567. if len(rsp.Data) != 0 {
  568. // Do no print this line when using the commit command
  569. // because the string comes out as gibberish
  570. if cmd.Use != "commit" {
  571. fmt.Printf("-> data: %s\n", rsp.Data)
  572. }
  573. fmt.Printf("-> data.hex: 0x%X\n", rsp.Data)
  574. }
  575. if rsp.Log != "" {
  576. fmt.Printf("-> log: %s\n", rsp.Log)
  577. }
  578. if rsp.Query != nil {
  579. fmt.Printf("-> height: %d\n", rsp.Query.Height)
  580. if rsp.Query.Key != nil {
  581. fmt.Printf("-> key: %s\n", rsp.Query.Key)
  582. fmt.Printf("-> key.hex: %X\n", rsp.Query.Key)
  583. }
  584. if rsp.Query.Value != nil {
  585. fmt.Printf("-> value: %s\n", rsp.Query.Value)
  586. fmt.Printf("-> value.hex: %X\n", rsp.Query.Value)
  587. }
  588. if rsp.Query.ProofOps != nil {
  589. fmt.Printf("-> proof: %#v\n", rsp.Query.ProofOps)
  590. }
  591. }
  592. }
  593. // NOTE: s is interpreted as a string unless prefixed with 0x
  594. func stringOrHexToBytes(s string) ([]byte, error) {
  595. if len(s) > 2 && strings.ToLower(s[:2]) == "0x" {
  596. b, err := hex.DecodeString(s[2:])
  597. if err != nil {
  598. err = fmt.Errorf("error decoding hex argument: %s", err.Error())
  599. return nil, err
  600. }
  601. return b, nil
  602. }
  603. if !strings.HasPrefix(s, "\"") || !strings.HasSuffix(s, "\"") {
  604. err := fmt.Errorf("invalid string arg: \"%s\". Must be quoted or a \"0x\"-prefixed hex string", s)
  605. return nil, err
  606. }
  607. return []byte(s[1 : len(s)-1]), nil
  608. }