mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-17 07:01:20 +00:00
oomph
This commit is contained in:
402
docs/using-tendermint.md
Normal file
402
docs/using-tendermint.md
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
# Using Tendermint
|
||||||
|
|
||||||
|
This is a guide to using the `tendermint` program from the command line.
|
||||||
|
It assumes only that you have the `tendermint` binary installed and have
|
||||||
|
some rudimentary idea of what Tendermint and ABCI are.
|
||||||
|
|
||||||
|
You can see the help menu with `tendermint --help`, and the version
|
||||||
|
number with `tendermint version`.
|
||||||
|
|
||||||
|
## Directory Root
|
||||||
|
|
||||||
|
The default directory for blockchain data is `~/.tendermint`. Override
|
||||||
|
this by setting the `TMHOME` environment variable.
|
||||||
|
|
||||||
|
## Initialize
|
||||||
|
|
||||||
|
Initialize the root directory by running:
|
||||||
|
|
||||||
|
tendermint init
|
||||||
|
|
||||||
|
This will create a new private key (`priv_validator.json`), and a
|
||||||
|
genesis file (`genesis.json`) containing the associated public key, in
|
||||||
|
`$TMHOME/config`. This is all that's necessary to run a local testnet
|
||||||
|
with one validator.
|
||||||
|
|
||||||
|
For more elaborate initialization, see the tesnet command:
|
||||||
|
|
||||||
|
tendermint testnet --help
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
To run a Tendermint node, use
|
||||||
|
|
||||||
|
tendermint node
|
||||||
|
|
||||||
|
By default, Tendermint will try to connect to an ABCI application on
|
||||||
|
[127.0.0.1:46658](127.0.0.1:46658). If you have the `kvstore` ABCI app
|
||||||
|
installed, run it in another window. If you don't, kill Tendermint and
|
||||||
|
run an in-process version of the `kvstore` app:
|
||||||
|
|
||||||
|
tendermint node --proxy_app=kvstore
|
||||||
|
|
||||||
|
After a few seconds you should see blocks start streaming in. Note that
|
||||||
|
blocks are produced regularly, even if there are no transactions. See
|
||||||
|
*No Empty Blocks*, below, to modify this setting.
|
||||||
|
|
||||||
|
Tendermint supports in-process versions of the `counter`, `kvstore` and
|
||||||
|
`nil` apps that ship as examples in the [ABCI
|
||||||
|
repository](https://github.com/tendermint/abci). It's easy to compile
|
||||||
|
your own app in-process with Tendermint if it's written in Go. If your
|
||||||
|
app is not written in Go, simply run it in another process, and use the
|
||||||
|
`--proxy_app` flag to specify the address of the socket it is listening
|
||||||
|
on, for instance:
|
||||||
|
|
||||||
|
tendermint node --proxy_app=/var/run/abci.sock
|
||||||
|
|
||||||
|
## Transactions
|
||||||
|
|
||||||
|
To send a transaction, use `curl` to make requests to the Tendermint RPC
|
||||||
|
server, for example:
|
||||||
|
|
||||||
|
curl http://localhost:46657/broadcast_tx_commit?tx=\"abcd\"
|
||||||
|
|
||||||
|
We can see the chain's status at the `/status` end-point:
|
||||||
|
|
||||||
|
curl http://localhost:46657/status | json_pp
|
||||||
|
|
||||||
|
and the `latest_app_hash` in particular:
|
||||||
|
|
||||||
|
curl http://localhost:46657/status | json_pp | grep latest_app_hash
|
||||||
|
|
||||||
|
Visit http://localhost:46657> in your browser to see the list of other
|
||||||
|
endpoints. Some take no arguments (like `/status`), while others specify
|
||||||
|
the argument name and use `_` as a placeholder.
|
||||||
|
|
||||||
|
### Formatting
|
||||||
|
|
||||||
|
The following nuances when sending/formatting transactions should be
|
||||||
|
taken into account:
|
||||||
|
|
||||||
|
With `GET`:
|
||||||
|
|
||||||
|
To send a UTF8 string byte array, quote the value of the tx pramater:
|
||||||
|
|
||||||
|
curl 'http://localhost:46657/broadcast_tx_commit?tx="hello"'
|
||||||
|
|
||||||
|
which sends a 5 byte transaction: "h e l l o" \[68 65 6c 6c 6f\].
|
||||||
|
|
||||||
|
Note the URL must be wrapped with single quoes, else bash will ignore
|
||||||
|
the double quotes. To avoid the single quotes, escape the double quotes:
|
||||||
|
|
||||||
|
curl http://localhost:46657/broadcast_tx_commit?tx=\"hello\"
|
||||||
|
|
||||||
|
Using a special character:
|
||||||
|
|
||||||
|
curl 'http://localhost:46657/broadcast_tx_commit?tx="€5"'
|
||||||
|
|
||||||
|
sends a 4 byte transaction: "€5" (UTF8) \[e2 82 ac 35\].
|
||||||
|
|
||||||
|
To send as raw hex, omit quotes AND prefix the hex string with `0x`:
|
||||||
|
|
||||||
|
curl http://localhost:46657/broadcast_tx_commit?tx=0x01020304
|
||||||
|
|
||||||
|
which sends a 4 byte transaction: \[01 02 03 04\].
|
||||||
|
|
||||||
|
With `POST` (using `json`), the raw hex must be `base64` encoded:
|
||||||
|
|
||||||
|
curl --data-binary '{"jsonrpc":"2.0","id":"anything","method":"broadcast_tx_commit","params": {"tx": "AQIDBA=="}}' -H 'content-type:text/plain;' http://localhost:46657
|
||||||
|
|
||||||
|
which sends the same 4 byte transaction: \[01 02 03 04\].
|
||||||
|
|
||||||
|
Note that raw hex cannot be used in `POST` transactions.
|
||||||
|
|
||||||
|
## Reset
|
||||||
|
|
||||||
|
**WARNING: UNSAFE** Only do this in development and only if you can
|
||||||
|
afford to lose all blockchain data!
|
||||||
|
|
||||||
|
To reset a blockchain, stop the node, remove the `~/.tendermint/data`
|
||||||
|
directory and run
|
||||||
|
|
||||||
|
tendermint unsafe_reset_priv_validator
|
||||||
|
|
||||||
|
This final step is necessary to reset the `priv_validator.json`, which
|
||||||
|
otherwise prevents you from making conflicting votes in the consensus
|
||||||
|
(something that could get you in trouble if you do it on a real
|
||||||
|
blockchain). If you don't reset the `priv_validator.json`, your fresh
|
||||||
|
new blockchain will not make any blocks.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Tendermint uses a `config.toml` for configuration. For details, see [the
|
||||||
|
config specification](./specification/configuration.html).
|
||||||
|
|
||||||
|
Notable options include the socket address of the application
|
||||||
|
(`proxy_app`), the listening address of the Tendermint peer
|
||||||
|
(`p2p.laddr`), and the listening address of the RPC server
|
||||||
|
(`rpc.laddr`).
|
||||||
|
|
||||||
|
Some fields from the config file can be overwritten with flags.
|
||||||
|
|
||||||
|
## No Empty Blocks
|
||||||
|
|
||||||
|
This much requested feature was implemented in version 0.10.3. While the
|
||||||
|
default behaviour of `tendermint` is still to create blocks
|
||||||
|
approximately once per second, it is possible to disable empty blocks or
|
||||||
|
set a block creation interval. In the former case, blocks will be
|
||||||
|
created when there are new transactions or when the AppHash changes.
|
||||||
|
|
||||||
|
To configure Tendermint to not produce empty blocks unless there are
|
||||||
|
transactions or the app hash changes, run Tendermint with this
|
||||||
|
additional flag:
|
||||||
|
|
||||||
|
tendermint node --consensus.create_empty_blocks=false
|
||||||
|
|
||||||
|
or set the configuration via the `config.toml` file:
|
||||||
|
|
||||||
|
[consensus]
|
||||||
|
create_empty_blocks = false
|
||||||
|
|
||||||
|
Remember: because the default is to *create empty blocks*, avoiding
|
||||||
|
empty blocks requires the config option to be set to `false`.
|
||||||
|
|
||||||
|
The block interval setting allows for a delay (in seconds) between the
|
||||||
|
creation of each new empty block. It is set via the `config.toml`:
|
||||||
|
|
||||||
|
[consensus]
|
||||||
|
create_empty_blocks_interval = 5
|
||||||
|
|
||||||
|
With this setting, empty blocks will be produced every 5s if no block
|
||||||
|
has been produced otherwise, regardless of the value of
|
||||||
|
`create_empty_blocks`.
|
||||||
|
|
||||||
|
## Broadcast API
|
||||||
|
|
||||||
|
Earlier, we used the `broadcast_tx_commit` endpoint to send a
|
||||||
|
transaction. When a transaction is sent to a Tendermint node, it will
|
||||||
|
run via `CheckTx` against the application. If it passes `CheckTx`, it
|
||||||
|
will be included in the mempool, broadcasted to other peers, and
|
||||||
|
eventually included in a block.
|
||||||
|
|
||||||
|
Since there are multiple phases to processing a transaction, we offer
|
||||||
|
multiple endpoints to broadcast a transaction:
|
||||||
|
|
||||||
|
/broadcast_tx_async
|
||||||
|
/broadcast_tx_sync
|
||||||
|
/broadcast_tx_commit
|
||||||
|
|
||||||
|
These correspond to no-processing, processing through the mempool, and
|
||||||
|
processing through a block, respectively. That is, `broadcast_tx_async`,
|
||||||
|
will return right away without waiting to hear if the transaction is
|
||||||
|
even valid, while `broadcast_tx_sync` will return with the result of
|
||||||
|
running the transaction through `CheckTx`. Using `broadcast_tx_commit`
|
||||||
|
will wait until the transaction is committed in a block or until some
|
||||||
|
timeout is reached, but will return right away if the transaction does
|
||||||
|
not pass `CheckTx`. The return value for `broadcast_tx_commit` includes
|
||||||
|
two fields, `check_tx` and `deliver_tx`, pertaining to the result of
|
||||||
|
running the transaction through those ABCI messages.
|
||||||
|
|
||||||
|
The benefit of using `broadcast_tx_commit` is that the request returns
|
||||||
|
after the transaction is committed (i.e. included in a block), but that
|
||||||
|
can take on the order of a second. For a quick result, use
|
||||||
|
`broadcast_tx_sync`, but the transaction will not be committed until
|
||||||
|
later, and by that point its effect on the state may change.
|
||||||
|
|
||||||
|
Note: see the Transactions => Formatting section for details about
|
||||||
|
transaction formating.
|
||||||
|
|
||||||
|
## Tendermint Networks
|
||||||
|
|
||||||
|
When `tendermint init` is run, both a `genesis.json` and
|
||||||
|
`priv_validator.json` are created in `~/.tendermint/config`. The
|
||||||
|
`genesis.json` might look like:
|
||||||
|
|
||||||
|
{
|
||||||
|
"validators" : [
|
||||||
|
{
|
||||||
|
"pub_key" : {
|
||||||
|
"value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=",
|
||||||
|
"type" : "AC26791624DE60"
|
||||||
|
},
|
||||||
|
"power" : 10,
|
||||||
|
"name" : ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"app_hash" : "",
|
||||||
|
"chain_id" : "test-chain-rDlYSN",
|
||||||
|
"genesis_time" : "0001-01-01T00:00:00Z"
|
||||||
|
}
|
||||||
|
|
||||||
|
And the `priv_validator.json`:
|
||||||
|
|
||||||
|
{
|
||||||
|
"last_step" : 0,
|
||||||
|
"last_round" : 0,
|
||||||
|
"address" : "B788DEDE4F50AD8BC9462DE76741CCAFF87D51E2",
|
||||||
|
"pub_key" : {
|
||||||
|
"value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=",
|
||||||
|
"type" : "AC26791624DE60"
|
||||||
|
},
|
||||||
|
"last_height" : 0,
|
||||||
|
"priv_key" : {
|
||||||
|
"value" : "JPivl82x+LfVkp8i3ztoTjY6c6GJ4pBxQexErOCyhwqHeGT5ATxzpAtPJKnxNx/NyUnD8Ebv3OIYH+kgD4N88Q==",
|
||||||
|
"type" : "954568A3288910"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
The `priv_validator.json` actually contains a private key, and should
|
||||||
|
thus be kept absolutely secret; for now we work with the plain text.
|
||||||
|
Note the `last_` fields, which are used to prevent us from signing
|
||||||
|
conflicting messages.
|
||||||
|
|
||||||
|
Note also that the `pub_key` (the public key) in the
|
||||||
|
`priv_validator.json` is also present in the `genesis.json`.
|
||||||
|
|
||||||
|
The genesis file contains the list of public keys which may participate
|
||||||
|
in the consensus, and their corresponding voting power. Greater than 2/3
|
||||||
|
of the voting power must be active (i.e. the corresponding private keys
|
||||||
|
must be producing signatures) for the consensus to make progress. In our
|
||||||
|
case, the genesis file contains the public key of our
|
||||||
|
`priv_validator.json`, so a Tendermint node started with the default
|
||||||
|
root directory will be able to make progress. Voting power uses an int64
|
||||||
|
but must be positive, thus the range is: 0 through 9223372036854775807.
|
||||||
|
Because of how the current proposer selection algorithm works, we do not
|
||||||
|
recommend having voting powers greater than 10\^12 (ie. 1 trillion) (see
|
||||||
|
[Proposals section of Byzantine Consensus
|
||||||
|
Algorithm](./specification/byzantine-consensus-algorithm.html#proposals)
|
||||||
|
for details).
|
||||||
|
|
||||||
|
If we want to add more nodes to the network, we have two choices: we can
|
||||||
|
add a new validator node, who will also participate in the consensus by
|
||||||
|
proposing blocks and voting on them, or we can add a new non-validator
|
||||||
|
node, who will not participate directly, but will verify and keep up
|
||||||
|
with the consensus protocol.
|
||||||
|
|
||||||
|
### Peers
|
||||||
|
|
||||||
|
To connect to peers on start-up, specify them in the
|
||||||
|
`$TMHOME/config/config.toml` or on the command line. Use seeds to
|
||||||
|
specify seed nodes from which you can get many other peer addresses, and
|
||||||
|
`persistent_peers` to specify peers that your node will maintain
|
||||||
|
persistent connections with.
|
||||||
|
|
||||||
|
For instance,
|
||||||
|
|
||||||
|
tendermint node --p2p.seeds "f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:46656,0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:46656"
|
||||||
|
|
||||||
|
Alternatively, you can use the `/dial_seeds` endpoint of the RPC to
|
||||||
|
specify seeds for a running node to connect to:
|
||||||
|
|
||||||
|
curl 'localhost:46657/dial_seeds?seeds=\["f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:46656","0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:46656"\]'
|
||||||
|
|
||||||
|
Note, if the peer-exchange protocol (PEX) is enabled (default), you
|
||||||
|
should not normally need seeds after the first start. Peers will be
|
||||||
|
gossipping about known peers and forming a network, storing peer
|
||||||
|
addresses in the addrbook.
|
||||||
|
|
||||||
|
If you want Tendermint to connect to specific set of addresses and
|
||||||
|
maintain a persistent connection with each, you can use the
|
||||||
|
`--p2p.persistent_peers` flag or the corresponding setting in the
|
||||||
|
`config.toml` or the `/dial_peers` RPC endpoint to do it without
|
||||||
|
stopping Tendermint core instance.
|
||||||
|
|
||||||
|
tendermint node --p2p.persistent_peers "429fcf25974313b95673f58d77eacdd434402665@10.11.12.13:46656,96663a3dd0d7b9d17d4c8211b191af259621c693@10.11.12.14:46656"
|
||||||
|
curl 'localhost:46657/dial_peers?persistent=true&peers=\["429fcf25974313b95673f58d77eacdd434402665@10.11.12.13:46656","96663a3dd0d7b9d17d4c8211b191af259621c693@10.11.12.14:46656"\]'
|
||||||
|
|
||||||
|
### Adding a Non-Validator
|
||||||
|
|
||||||
|
Adding a non-validator is simple. Just copy the original `genesis.json`
|
||||||
|
to `~/.tendermint/config` on the new machine and start the node,
|
||||||
|
specifying seeds or persistent peers as necessary. If no seeds or
|
||||||
|
persistent peers are specified, the node won't make any blocks, because
|
||||||
|
it's not a validator, and it won't hear about any blocks, because it's
|
||||||
|
not connected to the other peer.
|
||||||
|
|
||||||
|
### Adding a Validator
|
||||||
|
|
||||||
|
The easiest way to add new validators is to do it in the `genesis.json`,
|
||||||
|
before starting the network. For instance, we could make a new
|
||||||
|
`priv_validator.json`, and copy it's `pub_key` into the above genesis.
|
||||||
|
|
||||||
|
We can generate a new `priv_validator.json` with the command:
|
||||||
|
|
||||||
|
tendermint gen_validator
|
||||||
|
|
||||||
|
Now we can update our genesis file. For instance, if the new
|
||||||
|
`priv_validator.json` looks like:
|
||||||
|
|
||||||
|
{
|
||||||
|
"address" : "5AF49D2A2D4F5AD4C7C8C4CC2FB020131E9C4902",
|
||||||
|
"pub_key" : {
|
||||||
|
"value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=",
|
||||||
|
"type" : "AC26791624DE60"
|
||||||
|
},
|
||||||
|
"priv_key" : {
|
||||||
|
"value" : "EDJY9W6zlAw+su6ITgTKg2nTZcHAH1NMTW5iwlgmNDuX1f35+OR4HMN88ZtQzsAwhETq4k3vzM3n6WTk5ii16Q==",
|
||||||
|
"type" : "954568A3288910"
|
||||||
|
},
|
||||||
|
"last_step" : 0,
|
||||||
|
"last_round" : 0,
|
||||||
|
"last_height" : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
then the new `genesis.json` will be:
|
||||||
|
|
||||||
|
{
|
||||||
|
"validators" : [
|
||||||
|
{
|
||||||
|
"pub_key" : {
|
||||||
|
"value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=",
|
||||||
|
"type" : "AC26791624DE60"
|
||||||
|
},
|
||||||
|
"power" : 10,
|
||||||
|
"name" : ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pub_key" : {
|
||||||
|
"value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=",
|
||||||
|
"type" : "AC26791624DE60"
|
||||||
|
},
|
||||||
|
"power" : 10,
|
||||||
|
"name" : ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"app_hash" : "",
|
||||||
|
"chain_id" : "test-chain-rDlYSN",
|
||||||
|
"genesis_time" : "0001-01-01T00:00:00Z"
|
||||||
|
}
|
||||||
|
|
||||||
|
Update the `genesis.json` in `~/.tendermint/config`. Copy the genesis
|
||||||
|
file and the new `priv_validator.json` to the `~/.tendermint/config` on
|
||||||
|
a new machine.
|
||||||
|
|
||||||
|
Now run `tendermint node` on both machines, and use either
|
||||||
|
`--p2p.persistent_peers` or the `/dial_peers` to get them to peer up.
|
||||||
|
They should start making blocks, and will only continue to do so as long
|
||||||
|
as both of them are online.
|
||||||
|
|
||||||
|
To make a Tendermint network that can tolerate one of the validators
|
||||||
|
failing, you need at least four validator nodes (> 2/3).
|
||||||
|
|
||||||
|
Updating validators in a live network is supported but must be
|
||||||
|
explicitly programmed by the application developer. See the [application
|
||||||
|
developers guide](./app-development.html) for more details.
|
||||||
|
|
||||||
|
### Local Network
|
||||||
|
|
||||||
|
To run a network locally, say on a single machine, you must change the
|
||||||
|
`_laddr` fields in the `config.toml` (or using the flags) so that the
|
||||||
|
listening addresses of the various sockets don't conflict. Additionally,
|
||||||
|
you must set `addrbook_strict=false` in the `config.toml`, otherwise
|
||||||
|
Tendermint's p2p library will deny making connections to peers with the
|
||||||
|
same IP address.
|
||||||
|
|
||||||
|
### Upgrading
|
||||||
|
|
||||||
|
The Tendermint development cycle currently includes a lot of breaking changes.
|
||||||
|
Upgrading from an old version to a new version usually means throwing
|
||||||
|
away the chain data. Try out the
|
||||||
|
[tm-migrate](https://github.com/hxzqlh/tm-tools) tool written by
|
||||||
|
[@hxzqlh](https://github.com/hxzqlh) if you are keen to preserve the
|
||||||
|
state of your chain when upgrading to newer versions.
|
@ -1,463 +0,0 @@
|
|||||||
Using Tendermint
|
|
||||||
================
|
|
||||||
|
|
||||||
This is a guide to using the ``tendermint`` program from the command
|
|
||||||
line. It assumes only that you have the ``tendermint`` binary installed
|
|
||||||
and have some rudimentary idea of what Tendermint and ABCI are.
|
|
||||||
|
|
||||||
You can see the help menu with ``tendermint --help``, and the version
|
|
||||||
number with ``tendermint version``.
|
|
||||||
|
|
||||||
Directory Root
|
|
||||||
--------------
|
|
||||||
|
|
||||||
The default directory for blockchain data is ``~/.tendermint``. Override
|
|
||||||
this by setting the ``TMHOME`` environment variable.
|
|
||||||
|
|
||||||
Initialize
|
|
||||||
----------
|
|
||||||
|
|
||||||
Initialize the root directory by running:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
tendermint init
|
|
||||||
|
|
||||||
This will create a new private key (``priv_validator.json``), and a
|
|
||||||
genesis file (``genesis.json``) containing the associated public key,
|
|
||||||
in ``$TMHOME/config``.
|
|
||||||
This is all that's necessary to run a local testnet with one validator.
|
|
||||||
|
|
||||||
For more elaborate initialization, see the `tesnet` command:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
tendermint testnet --help
|
|
||||||
|
|
||||||
Run
|
|
||||||
---
|
|
||||||
|
|
||||||
To run a Tendermint node, use
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
tendermint node
|
|
||||||
|
|
||||||
By default, Tendermint will try to connect to an ABCI application on
|
|
||||||
`127.0.0.1:46658 <127.0.0.1:46658>`__. If you have the ``kvstore`` ABCI
|
|
||||||
app installed, run it in another window. If you don't, kill Tendermint
|
|
||||||
and run an in-process version of the ``kvstore`` app:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
tendermint node --proxy_app=kvstore
|
|
||||||
|
|
||||||
After a few seconds you should see blocks start streaming in. Note that
|
|
||||||
blocks are produced regularly, even if there are no transactions. See *No Empty Blocks*, below, to modify this setting.
|
|
||||||
|
|
||||||
Tendermint supports in-process versions of the ``counter``, ``kvstore`` and ``nil``
|
|
||||||
apps that ship as examples in the `ABCI
|
|
||||||
repository <https://github.com/tendermint/abci>`__. It's easy to compile
|
|
||||||
your own app in-process with Tendermint if it's written in Go. If your
|
|
||||||
app is not written in Go, simply run it in another process, and use the
|
|
||||||
``--proxy_app`` flag to specify the address of the socket it is
|
|
||||||
listening on, for instance:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
tendermint node --proxy_app=/var/run/abci.sock
|
|
||||||
|
|
||||||
Transactions
|
|
||||||
------------
|
|
||||||
|
|
||||||
To send a transaction, use ``curl`` to make requests to the Tendermint
|
|
||||||
RPC server, for example:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
curl http://localhost:46657/broadcast_tx_commit?tx=\"abcd\"
|
|
||||||
|
|
||||||
We can see the chain's status at the ``/status`` end-point:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
curl http://localhost:46657/status | json_pp
|
|
||||||
|
|
||||||
and the ``latest_app_hash`` in particular:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
curl http://localhost:46657/status | json_pp | grep latest_app_hash
|
|
||||||
|
|
||||||
Visit http://localhost:46657 in your browser to see the list of other
|
|
||||||
endpoints. Some take no arguments (like ``/status``), while others
|
|
||||||
specify the argument name and use ``_`` as a placeholder.
|
|
||||||
|
|
||||||
Formatting
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
The following nuances when sending/formatting transactions should
|
|
||||||
be taken into account:
|
|
||||||
|
|
||||||
With ``GET``:
|
|
||||||
|
|
||||||
To send a UTF8 string byte array, quote the value of the tx pramater:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
curl 'http://localhost:46657/broadcast_tx_commit?tx="hello"'
|
|
||||||
|
|
||||||
which sends a 5 byte transaction: "h e l l o" [68 65 6c 6c 6f].
|
|
||||||
|
|
||||||
Note the URL must be wrapped with single quoes, else bash will ignore the double quotes.
|
|
||||||
To avoid the single quotes, escape the double quotes:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
curl http://localhost:46657/broadcast_tx_commit?tx=\"hello\"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Using a special character:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
curl 'http://localhost:46657/broadcast_tx_commit?tx="€5"'
|
|
||||||
|
|
||||||
sends a 4 byte transaction: "€5" (UTF8) [e2 82 ac 35].
|
|
||||||
|
|
||||||
To send as raw hex, omit quotes AND prefix the hex string with ``0x``:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
curl http://localhost:46657/broadcast_tx_commit?tx=0x01020304
|
|
||||||
|
|
||||||
which sends a 4 byte transaction: [01 02 03 04].
|
|
||||||
|
|
||||||
With ``POST`` (using ``json``), the raw hex must be ``base64`` encoded:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
curl --data-binary '{"jsonrpc":"2.0","id":"anything","method":"broadcast_tx_commit","params": {"tx": "AQIDBA=="}}' -H 'content-type:text/plain;' http://localhost:46657
|
|
||||||
|
|
||||||
which sends the same 4 byte transaction: [01 02 03 04].
|
|
||||||
|
|
||||||
Note that raw hex cannot be used in ``POST`` transactions.
|
|
||||||
|
|
||||||
Reset
|
|
||||||
-----
|
|
||||||
|
|
||||||
**WARNING: UNSAFE** Only do this in development and only if you can
|
|
||||||
afford to lose all blockchain data!
|
|
||||||
|
|
||||||
To reset a blockchain, stop the node, remove the ``~/.tendermint/data``
|
|
||||||
directory and run
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
tendermint unsafe_reset_priv_validator
|
|
||||||
|
|
||||||
This final step is necessary to reset the ``priv_validator.json``, which
|
|
||||||
otherwise prevents you from making conflicting votes in the consensus
|
|
||||||
(something that could get you in trouble if you do it on a real
|
|
||||||
blockchain). If you don't reset the ``priv_validator.json``, your fresh
|
|
||||||
new blockchain will not make any blocks.
|
|
||||||
|
|
||||||
Configuration
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Tendermint uses a ``config.toml`` for configuration. For details, see
|
|
||||||
`the config specification <./specification/configuration.html>`__.
|
|
||||||
|
|
||||||
Notable options include the socket address of the application
|
|
||||||
(``proxy_app``), the listening address of the Tendermint peer
|
|
||||||
(``p2p.laddr``), and the listening address of the RPC server
|
|
||||||
(``rpc.laddr``).
|
|
||||||
|
|
||||||
Some fields from the config file can be overwritten with flags.
|
|
||||||
|
|
||||||
No Empty Blocks
|
|
||||||
---------------
|
|
||||||
|
|
||||||
This much requested feature was implemented in version 0.10.3. While the
|
|
||||||
default behaviour of ``tendermint`` is still to create blocks approximately
|
|
||||||
once per second, it is possible to disable empty blocks or set a block creation
|
|
||||||
interval. In the former case, blocks will be created when there are new
|
|
||||||
transactions or when the AppHash changes.
|
|
||||||
|
|
||||||
To configure Tendermint to not produce empty blocks unless there are
|
|
||||||
transactions or the app hash changes, run Tendermint with this additional flag:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
tendermint node --consensus.create_empty_blocks=false
|
|
||||||
|
|
||||||
or set the configuration via the ``config.toml`` file:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
[consensus]
|
|
||||||
create_empty_blocks = false
|
|
||||||
|
|
||||||
Remember: because the default is to *create empty blocks*, avoiding empty blocks requires the config option to be set to ``false``.
|
|
||||||
|
|
||||||
The block interval setting allows for a delay (in seconds) between the creation of each new empty block. It is set via the ``config.toml``:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
[consensus]
|
|
||||||
create_empty_blocks_interval = 5
|
|
||||||
|
|
||||||
With this setting, empty blocks will be produced every 5s if no block has been produced otherwise,
|
|
||||||
regardless of the value of ``create_empty_blocks``.
|
|
||||||
|
|
||||||
Broadcast API
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Earlier, we used the ``broadcast_tx_commit`` endpoint to send a
|
|
||||||
transaction. When a transaction is sent to a Tendermint node, it will
|
|
||||||
run via ``CheckTx`` against the application. If it passes ``CheckTx``,
|
|
||||||
it will be included in the mempool, broadcasted to other peers, and
|
|
||||||
eventually included in a block.
|
|
||||||
|
|
||||||
Since there are multiple phases to processing a transaction, we offer
|
|
||||||
multiple endpoints to broadcast a transaction:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
/broadcast_tx_async
|
|
||||||
/broadcast_tx_sync
|
|
||||||
/broadcast_tx_commit
|
|
||||||
|
|
||||||
These correspond to no-processing, processing through the mempool, and
|
|
||||||
processing through a block, respectively. That is,
|
|
||||||
``broadcast_tx_async``, will return right away without waiting to hear
|
|
||||||
if the transaction is even valid, while ``broadcast_tx_sync`` will
|
|
||||||
return with the result of running the transaction through ``CheckTx``.
|
|
||||||
Using ``broadcast_tx_commit`` will wait until the transaction is
|
|
||||||
committed in a block or until some timeout is reached, but will return
|
|
||||||
right away if the transaction does not pass ``CheckTx``. The return
|
|
||||||
value for ``broadcast_tx_commit`` includes two fields, ``check_tx`` and
|
|
||||||
``deliver_tx``, pertaining to the result of running the transaction
|
|
||||||
through those ABCI messages.
|
|
||||||
|
|
||||||
The benefit of using ``broadcast_tx_commit`` is that the request returns
|
|
||||||
after the transaction is committed (i.e. included in a block), but that
|
|
||||||
can take on the order of a second. For a quick result, use
|
|
||||||
``broadcast_tx_sync``, but the transaction will not be committed until
|
|
||||||
later, and by that point its effect on the state may change.
|
|
||||||
|
|
||||||
Note: see the Transactions => Formatting section for details about
|
|
||||||
transaction formating.
|
|
||||||
|
|
||||||
Tendermint Networks
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
When ``tendermint init`` is run, both a ``genesis.json`` and
|
|
||||||
``priv_validator.json`` are created in ``~/.tendermint/config``. The
|
|
||||||
``genesis.json`` might look like:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
{
|
|
||||||
"validators" : [
|
|
||||||
{
|
|
||||||
"pub_key" : {
|
|
||||||
"value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=",
|
|
||||||
"type" : "AC26791624DE60"
|
|
||||||
},
|
|
||||||
"power" : 10,
|
|
||||||
"name" : ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"app_hash" : "",
|
|
||||||
"chain_id" : "test-chain-rDlYSN",
|
|
||||||
"genesis_time" : "0001-01-01T00:00:00Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
And the ``priv_validator.json``:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
{
|
|
||||||
"last_step" : 0,
|
|
||||||
"last_round" : 0,
|
|
||||||
"address" : "B788DEDE4F50AD8BC9462DE76741CCAFF87D51E2",
|
|
||||||
"pub_key" : {
|
|
||||||
"value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=",
|
|
||||||
"type" : "AC26791624DE60"
|
|
||||||
},
|
|
||||||
"last_height" : 0,
|
|
||||||
"priv_key" : {
|
|
||||||
"value" : "JPivl82x+LfVkp8i3ztoTjY6c6GJ4pBxQexErOCyhwqHeGT5ATxzpAtPJKnxNx/NyUnD8Ebv3OIYH+kgD4N88Q==",
|
|
||||||
"type" : "954568A3288910"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
The ``priv_validator.json`` actually contains a private key, and should
|
|
||||||
thus be kept absolutely secret; for now we work with the plain text.
|
|
||||||
Note the ``last_`` fields, which are used to prevent us from signing
|
|
||||||
conflicting messages.
|
|
||||||
|
|
||||||
Note also that the ``pub_key`` (the public key) in the
|
|
||||||
``priv_validator.json`` is also present in the ``genesis.json``.
|
|
||||||
|
|
||||||
The genesis file contains the list of public keys which may participate in the
|
|
||||||
consensus, and their corresponding voting power. Greater than 2/3 of the voting
|
|
||||||
power must be active (i.e. the corresponding private keys must be producing
|
|
||||||
signatures) for the consensus to make progress. In our case, the genesis file
|
|
||||||
contains the public key of our ``priv_validator.json``, so a Tendermint node
|
|
||||||
started with the default root directory will be able to make progress. Voting
|
|
||||||
power uses an `int64` but must be positive, thus the range is: 0 through
|
|
||||||
9223372036854775807. Because of how the current proposer selection algorithm works,
|
|
||||||
we do not recommend having voting powers greater than 10^12 (ie. 1 trillion)
|
|
||||||
(see `Proposals section of Byzantine Consensus Algorithm
|
|
||||||
<./specification/byzantine-consensus-algorithm.html#proposals>`__ for details).
|
|
||||||
|
|
||||||
If we want to add more nodes to the network, we have two choices: we can
|
|
||||||
add a new validator node, who will also participate in the consensus by
|
|
||||||
proposing blocks and voting on them, or we can add a new non-validator
|
|
||||||
node, who will not participate directly, but will verify and keep up
|
|
||||||
with the consensus protocol.
|
|
||||||
|
|
||||||
Peers
|
|
||||||
~~~~~
|
|
||||||
|
|
||||||
To connect to peers on start-up, specify them in the ``$TMHOME/config/config.toml`` or
|
|
||||||
on the command line. Use `seeds` to specify seed nodes from which you can get many other
|
|
||||||
peer addresses, and ``persistent_peers`` to specify peers that your node will maintain
|
|
||||||
persistent connections with.
|
|
||||||
|
|
||||||
For instance,
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
tendermint node --p2p.seeds "f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:46656,0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:46656"
|
|
||||||
|
|
||||||
Alternatively, you can use the ``/dial_seeds`` endpoint of the RPC to
|
|
||||||
specify seeds for a running node to connect to:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
curl 'localhost:46657/dial_seeds?seeds=\["f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@1.2.3.4:46656","0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@5.6.7.8:46656"\]'
|
|
||||||
|
|
||||||
Note, if the peer-exchange protocol (PEX) is enabled (default), you should not
|
|
||||||
normally need seeds after the first start. Peers will be gossipping about known
|
|
||||||
peers and forming a network, storing peer addresses in the addrbook.
|
|
||||||
|
|
||||||
If you want Tendermint to connect to specific set of addresses and maintain a
|
|
||||||
persistent connection with each, you can use the ``--p2p.persistent_peers``
|
|
||||||
flag or the corresponding setting in the ``config.toml`` or the
|
|
||||||
``/dial_peers`` RPC endpoint to do it without stopping Tendermint
|
|
||||||
core instance.
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
tendermint node --p2p.persistent_peers "429fcf25974313b95673f58d77eacdd434402665@10.11.12.13:46656,96663a3dd0d7b9d17d4c8211b191af259621c693@10.11.12.14:46656"
|
|
||||||
curl 'localhost:46657/dial_peers?persistent=true&peers=\["429fcf25974313b95673f58d77eacdd434402665@10.11.12.13:46656","96663a3dd0d7b9d17d4c8211b191af259621c693@10.11.12.14:46656"\]'
|
|
||||||
|
|
||||||
Adding a Non-Validator
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Adding a non-validator is simple. Just copy the original
|
|
||||||
``genesis.json`` to ``~/.tendermint/config`` on the new machine and start the
|
|
||||||
node, specifying seeds or persistent peers as necessary. If no seeds or persistent
|
|
||||||
peers are specified, the node won't make any blocks, because it's not a validator,
|
|
||||||
and it won't hear about any blocks, because it's not connected to the other peer.
|
|
||||||
|
|
||||||
Adding a Validator
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The easiest way to add new validators is to do it in the
|
|
||||||
``genesis.json``, before starting the network. For instance, we could
|
|
||||||
make a new ``priv_validator.json``, and copy it's ``pub_key`` into the
|
|
||||||
above genesis.
|
|
||||||
|
|
||||||
We can generate a new ``priv_validator.json`` with the command:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
tendermint gen_validator
|
|
||||||
|
|
||||||
Now we can update our genesis file. For instance, if the new
|
|
||||||
``priv_validator.json`` looks like:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
{
|
|
||||||
"address" : "5AF49D2A2D4F5AD4C7C8C4CC2FB020131E9C4902",
|
|
||||||
"pub_key" : {
|
|
||||||
"value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=",
|
|
||||||
"type" : "AC26791624DE60"
|
|
||||||
},
|
|
||||||
"priv_key" : {
|
|
||||||
"value" : "EDJY9W6zlAw+su6ITgTKg2nTZcHAH1NMTW5iwlgmNDuX1f35+OR4HMN88ZtQzsAwhETq4k3vzM3n6WTk5ii16Q==",
|
|
||||||
"type" : "954568A3288910"
|
|
||||||
},
|
|
||||||
"last_step" : 0,
|
|
||||||
"last_round" : 0,
|
|
||||||
"last_height" : 0
|
|
||||||
}
|
|
||||||
|
|
||||||
then the new ``genesis.json`` will be:
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
{
|
|
||||||
"validators" : [
|
|
||||||
{
|
|
||||||
"pub_key" : {
|
|
||||||
"value" : "h3hk+QE8c6QLTySp8TcfzclJw/BG79ziGB/pIA+DfPE=",
|
|
||||||
"type" : "AC26791624DE60"
|
|
||||||
},
|
|
||||||
"power" : 10,
|
|
||||||
"name" : ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pub_key" : {
|
|
||||||
"value" : "l9X9+fjkeBzDfPGbUM7AMIRE6uJN78zN5+lk5OYotek=",
|
|
||||||
"type" : "AC26791624DE60"
|
|
||||||
},
|
|
||||||
"power" : 10,
|
|
||||||
"name" : ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"app_hash" : "",
|
|
||||||
"chain_id" : "test-chain-rDlYSN",
|
|
||||||
"genesis_time" : "0001-01-01T00:00:00Z"
|
|
||||||
}
|
|
||||||
|
|
||||||
Update the ``genesis.json`` in ``~/.tendermint/config``. Copy the genesis file
|
|
||||||
and the new ``priv_validator.json`` to the ``~/.tendermint/config`` on a new
|
|
||||||
machine.
|
|
||||||
|
|
||||||
Now run ``tendermint node`` on both machines, and use either
|
|
||||||
``--p2p.persistent_peers`` or the ``/dial_peers`` to get them to peer up. They
|
|
||||||
should start making blocks, and will only continue to do so as long as
|
|
||||||
both of them are online.
|
|
||||||
|
|
||||||
To make a Tendermint network that can tolerate one of the validators
|
|
||||||
failing, you need at least four validator nodes (> 2/3).
|
|
||||||
|
|
||||||
Updating validators in a live network is supported but must be
|
|
||||||
explicitly programmed by the application developer. See the `application
|
|
||||||
developers guide <./app-development.html>`__ for more
|
|
||||||
details.
|
|
||||||
|
|
||||||
Local Network
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
To run a network locally, say on a single machine, you must change the
|
|
||||||
``_laddr`` fields in the ``config.toml`` (or using the flags) so that
|
|
||||||
the listening addresses of the various sockets don't conflict.
|
|
||||||
Additionally, you must set ``addrbook_strict=false`` in the
|
|
||||||
``config.toml``, otherwise Tendermint's p2p library will deny making
|
|
||||||
connections to peers with the same IP address.
|
|
||||||
|
|
||||||
Upgrading
|
|
||||||
~~~~~~~~~
|
|
||||||
|
|
||||||
The Tendermint development cycle includes a lot of breaking changes. Upgrading from
|
|
||||||
an old version to a new version usually means throwing away the chain data. Try out
|
|
||||||
the `tm-migrate <https://github.com/hxzqlh/tm-tools>`__ tool written by `@hxzqlh <https://github.com/hxzqlh>`__ if
|
|
||||||
you are keen to preserve the state of your chain when upgrading to newer versions.
|
|
Reference in New Issue
Block a user