Using the abci-cli
|
|
==================
|
|
|
|
To facilitate testing and debugging of ABCI servers and simple apps, we
|
|
built a CLI, the ``abci-cli``, for sending ABCI messages from the
|
|
command line.
|
|
|
|
Install
|
|
-------
|
|
|
|
Make sure you `have Go installed <https://golang.org/doc/install>`__ and
|
|
`put ``$GOPATH/bin`` in your
|
|
``$PATH`` <https://github.com/tendermint/tendermint/wiki/Setting-GOPATH>`__.
|
|
|
|
Next, install the ``abci-cli`` tool and example applications:
|
|
|
|
::
|
|
|
|
go get -u github.com/tendermint/abci/cmd/...
|
|
|
|
If this fails, you may need to use ``glide`` to get vendored
|
|
dependencies:
|
|
|
|
::
|
|
|
|
go get github.com/Masterminds/glide
|
|
cd $GOPATH/src/github.com/tendermint/abci
|
|
glide install
|
|
go install ./cmd/...
|
|
|
|
Now run ``abci-cli --help`` to see the list of commands:
|
|
|
|
::
|
|
|
|
COMMANDS:
|
|
batch Run a batch of ABCI commands against an application
|
|
console Start an interactive console for multiple commands
|
|
echo Have the application echo a message
|
|
info Get some info about the application
|
|
set_option Set an option on the application
|
|
deliver_tx Append a new tx to application
|
|
check_tx Validate a tx
|
|
commit Get application Merkle root hash
|
|
help, h Shows a list of commands or help for one command
|
|
|
|
GLOBAL OPTIONS:
|
|
--address "tcp://127.0.0.1:46658" address of application socket
|
|
--help, -h show help
|
|
--version, -v print the version
|
|
|
|
First Example - Dummy
|
|
---------------------
|
|
|
|
The ``abci-cli`` tool lets us send ABCI messages to our application, to
|
|
help build and debug them.
|
|
|
|
The most important messages are ``deliver_tx``, ``check_tx``, and
|
|
``commit``, but there are others for convenience, configuration, and
|
|
information purposes.
|
|
|
|
Let's start a dummy application, which was installed at the same time as
|
|
``abci-cli`` above. The dummy just stores transactions in a merkle tree:
|
|
|
|
::
|
|
|
|
dummy
|
|
|
|
In another terminal, run
|
|
|
|
::
|
|
|
|
abci-cli echo hello
|
|
abci-cli info
|
|
|
|
The application should echo ``hello`` and give you some information
|
|
about itself.
|
|
|
|
An ABCI application must provide two things:
|
|
|
|
- a socket server
|
|
- a handler for ABCI messages
|
|
|
|
When we run the ``abci-cli`` tool we open a new connection to the
|
|
application's socket server, send the given ABCI message, and wait for a
|
|
response.
|
|
|
|
The server may be generic for a particular language, and we provide a
|
|
`reference implementation in
|
|
Golang <https://github.com/tendermint/abci/tree/master/server>`__. See
|
|
the `list of other ABCI
|
|
implementations <https://tendermint.com/ecosystem>`__ for servers in
|
|
other languages.
|
|
|
|
The handler is specific to the application, and may be arbitrary, so
|
|
long as it is deterministic and conforms to the ABCI interface
|
|
specification.
|
|
|
|
So when we run ``abci-cli info``, we open a new connection to the ABCI
|
|
server, which calls the ``Info()`` method on the application, which
|
|
tells us the number of transactions in our Merkle tree.
|
|
|
|
Now, since every command opens a new connection, we provide the
|
|
``abci-cli console`` and ``abci-cli batch`` commands, to allow multiple
|
|
ABCI messages to be sent over a single connection.
|
|
|
|
Running ``abci-cli console`` should drop you in an interactive console
|
|
for speaking ABCI messages to your application.
|
|
|
|
Try running these commands:
|
|
|
|
::
|
|
|
|
> echo hello
|
|
-> data: hello
|
|
|
|
> info
|
|
-> data: {"size":0}
|
|
|
|
> commit
|
|
-> data: 0x
|
|
|
|
> deliver_tx "abc"
|
|
-> code: OK
|
|
|
|
> info
|
|
-> data: {"size":1}
|
|
|
|
> commit
|
|
-> data: 0x750502FC7E84BBD788ED589624F06CFA871845D1
|
|
|
|
> query "abc"
|
|
-> code: OK
|
|
-> data: {"index":0,"value":"abc","exists":true}
|
|
|
|
> deliver_tx "def=xyz"
|
|
-> code: OK
|
|
|
|
> commit
|
|
-> data: 0x76393B8A182E450286B0694C629ECB51B286EFD5
|
|
|
|
> query "def"
|
|
-> code: OK
|
|
-> data: {"index":1,"value":"xyz","exists":true}
|
|
|
|
Note that if we do ``deliver_tx "abc"`` it will store ``(abc, abc)``,
|
|
but if we do ``deliver_tx "abc=efg"`` it will store ``(abc, efg)``.
|
|
|
|
Similarly, you could put the commands in a file and run
|
|
``abci-cli --verbose batch < myfile``.
|
|
|
|
Another Example - Counter
|
|
-------------------------
|
|
|
|
Now that we've got the hang of it, let's try another application, the
|
|
"counter" app.
|
|
|
|
The counter app doesn't use a Merkle tree, it just counts how many times
|
|
we've sent a transaction, asked for a hash, or committed the state. The
|
|
result of ``commit`` is just the number of transactions sent.
|
|
|
|
This application has two modes: ``serial=off`` and ``serial=on``.
|
|
|
|
When ``serial=on``, transactions must be a big-endian encoded
|
|
incrementing integer, starting at 0.
|
|
|
|
If ``serial=off``, there are no restrictions on transactions.
|
|
|
|
We can toggle the value of ``serial`` using the ``set_option`` ABCI
|
|
message.
|
|
|
|
When ``serial=on``, some transactions are invalid. In a live blockchain,
|
|
transactions collect in memory before they are committed into blocks. To
|
|
avoid wasting resources on invalid transactions, ABCI provides the
|
|
``check_tx`` message, which application developers can use to accept or
|
|
reject transactions, before they are stored in memory or gossipped to
|
|
other peers.
|
|
|
|
In this instance of the counter app, ``check_tx`` only allows
|
|
transactions whose integer is greater than the last committed one.
|
|
|
|
Let's kill the console and the dummy application, and start the counter
|
|
app:
|
|
|
|
::
|
|
|
|
counter
|
|
|
|
In another window, start the ``abci-cli console``:
|
|
|
|
::
|
|
|
|
> set_option serial on
|
|
-> data: serial=on
|
|
|
|
> check_tx 0x00
|
|
-> code: OK
|
|
|
|
> check_tx 0xff
|
|
-> code: OK
|
|
|
|
> deliver_tx 0x00
|
|
-> code: OK
|
|
|
|
> check_tx 0x00
|
|
-> code: BadNonce
|
|
-> log: Invalid nonce. Expected >= 1, got 0
|
|
|
|
> deliver_tx 0x01
|
|
-> code: OK
|
|
|
|
> deliver_tx 0x04
|
|
-> code: BadNonce
|
|
-> log: Invalid nonce. Expected 2, got 4
|
|
|
|
> info
|
|
-> data: {"hashes":0,"txs":2}
|
|
|
|
This is a very simple application, but between ``counter`` and
|
|
``dummy``, its easy to see how you can build out arbitrary application
|
|
states on top of the ABCI. `Hyperledger's
|
|
Burrow <https://github.com/hyperledger/burrow>`__ also runs atop ABCI,
|
|
bringing with it Ethereum-like accounts, the Ethereum virtual-machine,
|
|
Monax's permissioning scheme, and native contracts extensions.
|
|
|
|
But the ultimate flexibility comes from being able to write the
|
|
application easily in any language.
|
|
|
|
We have implemented the counter in a number of languages (see the
|
|
example directory).
|
|
|
|
To run the Node JS version, ``cd`` to ``example/js`` and run
|
|
|
|
::
|
|
|
|
node app.js
|
|
|
|
(you'll have to kill the other counter application process). In another
|
|
window, run the console and those previous ABCI commands. You should get
|
|
the same results as for the Go version.
|
|
|
|
Want to write the counter app in your favorite language?! We'd be happy
|
|
to add you to our `ecosystem <https://tendermint.com/ecosystem>`__!
|
|
We're also offering `bounties <https://tendermint.com/bounties>`__ for
|
|
implementations in new languages!
|
|
|
|
Notes
|
|
-----
|
|
|
|
The ``abci-cli`` is designed strictly for testing and debugging. In a
|
|
real deployment, the role of sending messages is taken by Tendermint,
|
|
which connects to the app using three separate connections, each with
|
|
its own pattern of messages.
|
|
|
|
For more information, see the `application developers
|
|
guide </docs/guides/app-development>`__. For examples of running an ABCI
|
|
app with Tendermint, see the `introductory
|
|
guide </docs/getting-started/first-abci-app>`__.
|