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.

720 lines
17 KiB

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