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.

366 lines
9.5 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. ---
  2. order: 2
  3. ---
  4. # Using ABCI-CLI
  5. To facilitate testing and debugging of ABCI servers and simple apps, we
  6. built a CLI, the `abci-cli`, for sending ABCI messages from the command
  7. line.
  8. ## Install
  9. Make sure you [have Go installed](https://golang.org/doc/install).
  10. Next, install the `abci-cli` tool and example applications:
  11. ```sh
  12. mkdir -p $GOPATH/src/github.com/tendermint
  13. cd $GOPATH/src/github.com/tendermint
  14. git clone https://github.com/tendermint/tendermint.git
  15. cd tendermint
  16. make tools
  17. make install_abci
  18. ```
  19. Now run `abci-cli` to see the list of commands:
  20. ```sh
  21. Usage:
  22. abci-cli [command]
  23. Available Commands:
  24. batch Run a batch of abci commands against an application
  25. check_tx Validate a tx
  26. commit Commit the application state and return the Merkle root hash
  27. console Start an interactive abci console for multiple commands
  28. counter ABCI demo example
  29. deliver_tx Deliver a new tx to the application
  30. kvstore ABCI demo example
  31. echo Have the application echo a message
  32. help Help about any command
  33. info Get some info about the application
  34. query Query the application state
  35. set_option Set an options on the application
  36. Flags:
  37. --abci string socket or grpc (default "socket")
  38. --address string address of application socket (default "tcp://127.0.0.1:26658")
  39. -h, --help help for abci-cli
  40. -v, --verbose print the command and results as if it were a console session
  41. Use "abci-cli [command] --help" for more information about a command.
  42. ```
  43. ## KVStore - First Example
  44. The `abci-cli` tool lets us send ABCI messages to our application, to
  45. help build and debug them.
  46. The most important messages are `deliver_tx`, `check_tx`, and `commit`,
  47. but there are others for convenience, configuration, and information
  48. purposes.
  49. We'll start a kvstore application, which was installed at the same time
  50. as `abci-cli` above. The kvstore just stores transactions in a merkle
  51. tree.
  52. Its code can be found
  53. [here](https://github.com/tendermint/tendermint/blob/master/abci/cmd/abci-cli/abci-cli.go)
  54. and looks like:
  55. ```go
  56. func cmdKVStore(cmd *cobra.Command, args []string) error {
  57. logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
  58. // Create the application - in memory or persisted to disk
  59. var app types.Application
  60. if flagPersist == "" {
  61. app = kvstore.NewKVStoreApplication()
  62. } else {
  63. app = kvstore.NewPersistentKVStoreApplication(flagPersist)
  64. app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore"))
  65. }
  66. // Start the listener
  67. srv, err := server.NewServer(flagAddrD, flagAbci, app)
  68. if err != nil {
  69. return err
  70. }
  71. srv.SetLogger(logger.With("module", "abci-server"))
  72. if err := srv.Start(); err != nil {
  73. return err
  74. }
  75. // Stop upon receiving SIGTERM or CTRL-C.
  76. tmos.TrapSignal(logger, func() {
  77. // Cleanup
  78. srv.Stop()
  79. })
  80. // Run forever.
  81. select {}
  82. }
  83. ```
  84. Start by running:
  85. ```sh
  86. abci-cli kvstore
  87. ```
  88. And in another terminal, run
  89. ```sh
  90. abci-cli echo hello
  91. abci-cli info
  92. ```
  93. You'll see something like:
  94. ```sh
  95. -> data: hello
  96. -> data.hex: 68656C6C6F
  97. ```
  98. and:
  99. ```sh
  100. -> data: {"size":0}
  101. -> data.hex: 7B2273697A65223A307D
  102. ```
  103. An ABCI application must provide two things:
  104. - a socket server
  105. - a handler for ABCI messages
  106. When we run the `abci-cli` tool we open a new connection to the
  107. application's socket server, send the given ABCI message, and wait for a
  108. response.
  109. The server may be generic for a particular language, and we provide a
  110. [reference implementation in
  111. Golang](https://github.com/tendermint/tendermint/tree/master/abci/server). See the
  112. [list of other ABCI implementations](https://github.com/tendermint/awesome#ecosystem) for servers in
  113. other languages.
  114. The handler is specific to the application, and may be arbitrary, so
  115. long as it is deterministic and conforms to the ABCI interface
  116. specification.
  117. So when we run `abci-cli info`, we open a new connection to the ABCI
  118. server, which calls the `Info()` method on the application, which tells
  119. us the number of transactions in our Merkle tree.
  120. Now, since every command opens a new connection, we provide the
  121. `abci-cli console` and `abci-cli batch` commands, to allow multiple ABCI
  122. messages to be sent over a single connection.
  123. Running `abci-cli console` should drop you in an interactive console for
  124. speaking ABCI messages to your application.
  125. Try running these commands:
  126. ```sh
  127. > echo hello
  128. -> code: OK
  129. -> data: hello
  130. -> data.hex: 0x68656C6C6F
  131. > info
  132. -> code: OK
  133. -> data: {"size":0}
  134. -> data.hex: 0x7B2273697A65223A307D
  135. > commit
  136. -> code: OK
  137. -> data.hex: 0x0000000000000000
  138. > deliver_tx "abc"
  139. -> code: OK
  140. > info
  141. -> code: OK
  142. -> data: {"size":1}
  143. -> data.hex: 0x7B2273697A65223A317D
  144. > commit
  145. -> code: OK
  146. -> data.hex: 0x0200000000000000
  147. > query "abc"
  148. -> code: OK
  149. -> log: exists
  150. -> height: 2
  151. -> value: abc
  152. -> value.hex: 616263
  153. > deliver_tx "def=xyz"
  154. -> code: OK
  155. > commit
  156. -> code: OK
  157. -> data.hex: 0x0400000000000000
  158. > query "def"
  159. -> code: OK
  160. -> log: exists
  161. -> height: 3
  162. -> value: xyz
  163. -> value.hex: 78797A
  164. ```
  165. Note that if we do `deliver_tx "abc"` it will store `(abc, abc)`, but if
  166. we do `deliver_tx "abc=efg"` it will store `(abc, efg)`.
  167. Similarly, you could put the commands in a file and run
  168. `abci-cli --verbose batch < myfile`.
  169. ## Counter - Another Example
  170. Now that we've got the hang of it, let's try another application, the
  171. "counter" app.
  172. Like the kvstore app, its code can be found
  173. [here](https://github.com/tendermint/tendermint/blob/master/abci/cmd/abci-cli/abci-cli.go)
  174. and looks like:
  175. ```sh
  176. func cmdCounter(cmd *cobra.Command, args []string) error {
  177. app := counter.NewCounterApplication(flagSerial)
  178. logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
  179. // Start the listener
  180. srv, err := server.NewServer(flagAddrC, flagAbci, app)
  181. if err != nil {
  182. return err
  183. }
  184. srv.SetLogger(logger.With("module", "abci-server"))
  185. if err := srv.Start(); err != nil {
  186. return err
  187. }
  188. // Stop upon receiving SIGTERM or CTRL-C.
  189. tmos.TrapSignal(logger, func() {
  190. // Cleanup
  191. srv.Stop()
  192. })
  193. // Run forever.
  194. select {}
  195. }
  196. ```
  197. The counter app doesn't use a Merkle tree, it just counts how many times
  198. we've sent a transaction, asked for a hash, or committed the state. The
  199. result of `commit` is just the number of transactions sent.
  200. This application has two modes: `serial=off` and `serial=on`.
  201. When `serial=on`, transactions must be a big-endian encoded incrementing
  202. integer, starting at 0.
  203. If `serial=off`, there are no restrictions on transactions.
  204. We can toggle the value of `serial` using the `set_option` ABCI message.
  205. When `serial=on`, some transactions are invalid. In a live blockchain,
  206. transactions collect in memory before they are committed into blocks. To
  207. avoid wasting resources on invalid transactions, ABCI provides the
  208. `check_tx` message, which application developers can use to accept or
  209. reject transactions, before they are stored in memory or gossipped to
  210. other peers.
  211. In this instance of the counter app, `check_tx` only allows transactions
  212. whose integer is greater than the last committed one.
  213. Let's kill the console and the kvstore application, and start the
  214. counter app:
  215. ```sh
  216. abci-cli counter
  217. ```
  218. In another window, start the `abci-cli console`:
  219. ```sh
  220. > set_option serial on
  221. -> code: OK
  222. -> log: OK (SetOption doesn't return anything.)
  223. > check_tx 0x00
  224. -> code: OK
  225. > check_tx 0xff
  226. -> code: OK
  227. > deliver_tx 0x00
  228. -> code: OK
  229. > check_tx 0x00
  230. -> code: BadNonce
  231. -> log: Invalid nonce. Expected >= 1, got 0
  232. > deliver_tx 0x01
  233. -> code: OK
  234. > deliver_tx 0x04
  235. -> code: BadNonce
  236. -> log: Invalid nonce. Expected 2, got 4
  237. > info
  238. -> code: OK
  239. -> data: {"hashes":0,"txs":2}
  240. -> data.hex: 0x7B22686173686573223A302C22747873223A327D
  241. ```
  242. This is a very simple application, but between `counter` and `kvstore`,
  243. its easy to see how you can build out arbitrary application states on
  244. top of the ABCI. [Hyperledger's
  245. Burrow](https://github.com/hyperledger/burrow) also runs atop ABCI,
  246. bringing with it Ethereum-like accounts, the Ethereum virtual-machine,
  247. Monax's permissioning scheme, and native contracts extensions.
  248. But the ultimate flexibility comes from being able to write the
  249. application easily in any language.
  250. We have implemented the counter in a number of languages [see the
  251. example directory](https://github.com/tendermint/tendermint/tree/master/abci/example).
  252. To run the Node.js version, fist download & install [the Javascript ABCI server](https://github.com/tendermint/js-abci):
  253. ```sh
  254. git clone https://github.com/tendermint/js-abci.git
  255. cd js-abci
  256. npm install abci
  257. ```
  258. Now you can start the app:
  259. ```bash
  260. node example/counter.js
  261. ```
  262. (you'll have to kill the other counter application process). In another
  263. window, run the console and those previous ABCI commands. You should get
  264. the same results as for the Go version.
  265. ## Bounties
  266. Want to write the counter app in your favorite language?! We'd be happy
  267. to add you to our [ecosystem](https://github.com/tendermint/awesome#ecosystem)!
  268. See [funding](https://github.com/interchainio/funding) opportunities from the
  269. [Interchain Foundation](https://interchain.io/) for implementations in new languages and more.
  270. The `abci-cli` is designed strictly for testing and debugging. In a real
  271. deployment, the role of sending messages is taken by Tendermint, which
  272. connects to the app using three separate connections, each with its own
  273. pattern of messages.
  274. For more information, see the [application developers
  275. guide](./app-development.md). For examples of running an ABCI app with
  276. Tendermint, see the [getting started guide](./getting-started.md).
  277. Next is the ABCI specification.