diff --git a/.gitignore b/.gitignore index cd60f745..6d058766 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ test/logs coverage.txt docs/_build docs/tools -docs/abci-spec.rst +docs/abci-spec.md *.log scripts/wal2json/wal2json diff --git a/DOCKER/README.md b/DOCKER/README.md index fd05d1b0..43edce0f 100644 --- a/DOCKER/README.md +++ b/DOCKER/README.md @@ -1,4 +1,6 @@ -# Supported tags and respective `Dockerfile` links +# Docker + +## Supported tags and respective `Dockerfile` links - `0.17.1`, `latest` [(Dockerfile)](https://github.com/tendermint/tendermint/blob/208ac32fa266657bd6c304e84ec828aa252bb0b8/DOCKER/Dockerfile) - `0.15.0` [(Dockerfile)](https://github.com/tendermint/tendermint/blob/170777300ea92dc21a8aec1abc16cb51812513a4/DOCKER/Dockerfile) @@ -14,7 +16,7 @@ `develop` tag points to the [develop](https://github.com/tendermint/tendermint/tree/develop) branch. -# Quick reference +## Quick reference * **Where to get help:** https://cosmos.network/community @@ -25,7 +27,7 @@ * **Supported Docker versions:** [the latest release](https://github.com/moby/moby/releases) (down to 1.6 on a best-effort basis) -# Tendermint +## Tendermint Tendermint Core is Byzantine Fault Tolerant (BFT) middleware that takes a state transition machine, written in any programming language, and securely replicates it on many machines. @@ -33,9 +35,9 @@ For more background, see the [introduction](https://tendermint.readthedocs.io/en To get started developing applications, see the [application developers guide](https://tendermint.readthedocs.io/en/master/getting-started.html). -# How to use this image +## How to use this image -## Start one instance of the Tendermint core with the `kvstore` app +### Start one instance of the Tendermint core with the `kvstore` app A quick example of a built-in app and Tendermint core in one container. @@ -44,7 +46,7 @@ docker run -it --rm -v "/tmp:/tendermint" tendermint/tendermint init docker run -it --rm -v "/tmp:/tendermint" tendermint/tendermint node --proxy_app=kvstore ``` -# Local cluster +## Local cluster To run a 4-node network, see the `Makefile` in the root of [the repo](https://github.com/tendermint/tendermint/master/Makefile) and run: @@ -56,10 +58,10 @@ make localnet-start Note that this will build and use a different image than the ones provided here. -# License +## License - Tendermint's license is [Apache 2.0](https://github.com/tendermint/tendermint/master/LICENSE). -# Contributing +## Contributing Contributions are most welcome! See the [contributing file](https://github.com/tendermint/tendermint/blob/master/CONTRIBUTING.md) for more information. diff --git a/docs/abci-cli.md b/docs/abci-cli.md new file mode 100644 index 00000000..c827d147 --- /dev/null +++ b/docs/abci-cli.md @@ -0,0 +1,329 @@ +# Using 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). + +Next, install the `abci-cli` tool and example applications: + + go get -u github.com/tendermint/abci/cmd/abci-cli + +If this fails, you may need to use [dep](https://github.com/golang/dep) +to get vendored dependencies: + + cd $GOPATH/src/github.com/tendermint/abci + make get_tools + make get_vendor_deps + make install + +Now run `abci-cli` to see the list of commands: + + Usage: + abci-cli [command] + + Available Commands: + batch Run a batch of abci commands against an application + check_tx Validate a tx + commit Commit the application state and return the Merkle root hash + console Start an interactive abci console for multiple commands + counter ABCI demo example + deliver_tx Deliver a new tx to the application + kvstore ABCI demo example + echo Have the application echo a message + help Help about any command + info Get some info about the application + query Query the application state + set_option Set an options on the application + + Flags: + --abci string socket or grpc (default "socket") + --address string address of application socket (default "tcp://127.0.0.1:46658") + -h, --help help for abci-cli + -v, --verbose print the command and results as if it were a console session + + Use "abci-cli [command] --help" for more information about a command. + +## KVStore - First Example + +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. + +We'll start a kvstore application, which was installed at the same time +as `abci-cli` above. The kvstore just stores transactions in a merkle +tree. + +Its code can be found +[here](https://github.com/tendermint/abci/blob/master/cmd/abci-cli/abci-cli.go) +and looks like: + + func cmdKVStore(cmd *cobra.Command, args []string) error { + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + + // Create the application - in memory or persisted to disk + var app types.Application + if flagPersist == "" { + app = kvstore.NewKVStoreApplication() + } else { + app = kvstore.NewPersistentKVStoreApplication(flagPersist) + app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore")) + } + + // Start the listener + srv, err := server.NewServer(flagAddrD, flagAbci, app) + if err != nil { + return err + } + srv.SetLogger(logger.With("module", "abci-server")) + if err := srv.Start(); err != nil { + return err + } + + // Wait forever + cmn.TrapSignal(func() { + // Cleanup + srv.Stop() + }) + return nil + } + +Start by running: + + abci-cli kvstore + +And in another terminal, run + + abci-cli echo hello + abci-cli info + +You'll see something like: + + -> data: hello + -> data.hex: 68656C6C6F + +and: + + -> data: {"size":0} + -> data.hex: 7B2273697A65223A307D + +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](./ecosystem.html) 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 + -> code: OK + -> data: hello + -> data.hex: 0x68656C6C6F + + > info + -> code: OK + -> data: {"size":0} + -> data.hex: 0x7B2273697A65223A307D + + > commit + -> code: OK + -> data.hex: 0x0000000000000000 + + > deliver_tx "abc" + -> code: OK + + > info + -> code: OK + -> data: {"size":1} + -> data.hex: 0x7B2273697A65223A317D + + > commit + -> code: OK + -> data.hex: 0x0200000000000000 + + > query "abc" + -> code: OK + -> log: exists + -> height: 0 + -> value: abc + -> value.hex: 616263 + + > deliver_tx "def=xyz" + -> code: OK + + > commit + -> code: OK + -> data.hex: 0x0400000000000000 + + > query "def" + -> code: OK + -> log: exists + -> height: 0 + -> value: xyz + -> value.hex: 78797A + +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`. + +## Counter - Another Example + +Now that we've got the hang of it, let's try another application, the +"counter" app. + +Like the kvstore app, its code can be found +[here](https://github.com/tendermint/abci/blob/master/cmd/abci-cli/abci-cli.go) +and looks like: + + func cmdCounter(cmd *cobra.Command, args []string) error { + + app := counter.NewCounterApplication(flagSerial) + + logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + + // Start the listener + srv, err := server.NewServer(flagAddrC, flagAbci, app) + if err != nil { + return err + } + srv.SetLogger(logger.With("module", "abci-server")) + if err := srv.Start(); err != nil { + return err + } + + // Wait forever + cmn.TrapSignal(func() { + // Cleanup + srv.Stop() + }) + return nil + } + +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 kvstore application, and start the +counter app: + + abci-cli counter + +In another window, start the `abci-cli console`: + + > set_option serial on + -> code: OK + -> log: OK (SetOption doesn't return anything.) + + > 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 + -> code: OK + -> data: {"hashes":0,"txs":2} + -> data.hex: 0x7B22686173686573223A302C22747873223A327D + +This is a very simple application, but between `counter` and `kvstore`, +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](https://github.com/tendermint/abci/tree/master/example). + +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. + +## Bounties + +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://hackerone.com/tendermint/) for +implementations in new languages! + +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](./app-development.html). For examples of running an ABCI app with +Tendermint, see the [getting started guide](./getting-started.html). +Next is the ABCI specification. diff --git a/docs/abci-cli.rst b/docs/abci-cli.rst deleted file mode 100644 index d4a73723..00000000 --- a/docs/abci-cli.rst +++ /dev/null @@ -1,371 +0,0 @@ -Using 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 `__. - -Next, install the ``abci-cli`` tool and example applications: - -:: - - go get -u github.com/tendermint/abci/cmd/abci-cli - -If this fails, you may need to use `dep `__ to get vendored -dependencies: - -:: - - cd $GOPATH/src/github.com/tendermint/abci - make get_tools - make get_vendor_deps - make install - -Now run ``abci-cli`` to see the list of commands: - -:: - - Usage: - abci-cli [command] - - Available Commands: - batch Run a batch of abci commands against an application - check_tx Validate a tx - commit Commit the application state and return the Merkle root hash - console Start an interactive abci console for multiple commands - counter ABCI demo example - deliver_tx Deliver a new tx to the application - kvstore ABCI demo example - echo Have the application echo a message - help Help about any command - info Get some info about the application - query Query the application state - set_option Set an options on the application - - Flags: - --abci string socket or grpc (default "socket") - --address string address of application socket (default "tcp://127.0.0.1:46658") - -h, --help help for abci-cli - -v, --verbose print the command and results as if it were a console session - - Use "abci-cli [command] --help" for more information about a command. - - -KVStore - First Example ------------------------ - -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. - -We'll start a kvstore application, which was installed at the same time as -``abci-cli`` above. The kvstore just stores transactions in a merkle tree. - -Its code can be found `here `__ and looks like: - -.. container:: toggle - - .. container:: header - - **Show/Hide KVStore Example** - - .. code-block:: go - - func cmdKVStore(cmd *cobra.Command, args []string) error { - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - - // Create the application - in memory or persisted to disk - var app types.Application - if flagPersist == "" { - app = kvstore.NewKVStoreApplication() - } else { - app = kvstore.NewPersistentKVStoreApplication(flagPersist) - app.(*kvstore.PersistentKVStoreApplication).SetLogger(logger.With("module", "kvstore")) - } - - // Start the listener - srv, err := server.NewServer(flagAddrD, flagAbci, app) - if err != nil { - return err - } - srv.SetLogger(logger.With("module", "abci-server")) - if err := srv.Start(); err != nil { - return err - } - - // Wait forever - cmn.TrapSignal(func() { - // Cleanup - srv.Stop() - }) - return nil - } - -Start by running: - -:: - - abci-cli kvstore - -And in another terminal, run - -:: - - abci-cli echo hello - abci-cli info - -You'll see something like: - -:: - - -> data: hello - -> data.hex: 68656C6C6F - -and: - -:: - - -> data: {"size":0} - -> data.hex: 7B2273697A65223A307D - -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 `__. See -the `list of other ABCI -implementations <./ecosystem.html>`__ 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 - -> code: OK - -> data: hello - -> data.hex: 0x68656C6C6F - - > info - -> code: OK - -> data: {"size":0} - -> data.hex: 0x7B2273697A65223A307D - - > commit - -> code: OK - -> data.hex: 0x0000000000000000 - - > deliver_tx "abc" - -> code: OK - - > info - -> code: OK - -> data: {"size":1} - -> data.hex: 0x7B2273697A65223A317D - - > commit - -> code: OK - -> data.hex: 0x0200000000000000 - - > query "abc" - -> code: OK - -> log: exists - -> height: 0 - -> value: abc - -> value.hex: 616263 - - > deliver_tx "def=xyz" - -> code: OK - - > commit - -> code: OK - -> data.hex: 0x0400000000000000 - - > query "def" - -> code: OK - -> log: exists - -> height: 0 - -> value: xyz - -> value.hex: 78797A - -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``. - -Counter - Another Example -------------------------- - -Now that we've got the hang of it, let's try another application, the -"counter" app. - -Like the kvstore app, its code can be found `here `__ and looks like: - -.. container:: toggle - - .. container:: header - - **Show/Hide Counter Example** - - .. code-block:: go - - func cmdCounter(cmd *cobra.Command, args []string) error { - - app := counter.NewCounterApplication(flagSerial) - - logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout)) - - // Start the listener - srv, err := server.NewServer(flagAddrC, flagAbci, app) - if err != nil { - return err - } - srv.SetLogger(logger.With("module", "abci-server")) - if err := srv.Start(); err != nil { - return err - } - - // Wait forever - cmn.TrapSignal(func() { - // Cleanup - srv.Stop() - }) - return nil - } - - -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 kvstore application, and start the counter -app: - -:: - - abci-cli counter - -In another window, start the ``abci-cli console``: - -:: - - > set_option serial on - -> code: OK - -> log: OK (SetOption doesn't return anything.) - - > 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 - -> code: OK - -> data: {"hashes":0,"txs":2} - -> data.hex: 0x7B22686173686573223A302C22747873223A327D - -This is a very simple application, but between ``counter`` and -``kvstore``, its easy to see how you can build out arbitrary application -states on top of the ABCI. `Hyperledger's -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 `__! -We're also offering `bounties `__ for -implementations in new languages! - -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 <./app-development.html>`__. For examples of running an ABCI -app with Tendermint, see the `getting started -guide <./getting-started.html>`__. Next is the ABCI specification. diff --git a/docs/app-architecture.md b/docs/app-architecture.md new file mode 100644 index 00000000..64b1a379 --- /dev/null +++ b/docs/app-architecture.md @@ -0,0 +1,50 @@ +# Application Architecture Guide + +Here we provide a brief guide on the recommended architecture of a +Tendermint blockchain application. + +The following diagram provides a superb example: + + + +The end-user application here is the Cosmos Voyager, at the bottom left. +Voyager communicates with a REST API exposed by a local Light-Client +Daemon. The Light-Client Daemon is an application specific program that +communicates with Tendermint nodes and verifies Tendermint light-client +proofs through the Tendermint Core RPC. The Tendermint Core process +communicates with a local ABCI application, where the user query or +transaction is actually processed. + +The ABCI application must be a deterministic result of the Tendermint +consensus - any external influence on the application state that didn't +come through Tendermint could cause a consensus failure. Thus *nothing* +should communicate with the application except Tendermint via ABCI. + +If the application is written in Go, it can be compiled into the +Tendermint binary. Otherwise, it should use a unix socket to communicate +with Tendermint. If it's necessary to use TCP, extra care must be taken +to encrypt and authenticate the connection. + +All reads from the app happen through the Tendermint `/abci_query` +endpoint. All writes to the app happen through the Tendermint +`/broadcast_tx_*` endpoints. + +The Light-Client Daemon is what provides light clients (end users) with +nearly all the security of a full node. It formats and broadcasts +transactions, and verifies proofs of queries and transaction results. +Note that it need not be a daemon - the Light-Client logic could instead +be implemented in the same process as the end-user application. + +Note for those ABCI applications with weaker security requirements, the +functionality of the Light-Client Daemon can be moved into the ABCI +application process itself. That said, exposing the application process +to anything besides Tendermint over ABCI requires extreme caution, as +all transactions, and possibly all queries, should still pass through +Tendermint. + +See the following for more extensive documentation: +- [Interchain Standard for the Light-Client REST API](https://github.com/cosmos/cosmos-sdk/pull/1028) +- [Tendermint RPC Docs](https://tendermint.github.io/slate/) +- [Tendermint in Production](https://github.com/tendermint/tendermint/pull/1618) +- [Tendermint Basics](https://tendermint.readthedocs.io/en/master/using-tendermint.html) +- [ABCI spec](https://github.com/tendermint/abci/blob/develop/specification.md) diff --git a/docs/app-architecture.rst b/docs/app-architecture.rst deleted file mode 100644 index c303ba4a..00000000 --- a/docs/app-architecture.rst +++ /dev/null @@ -1,42 +0,0 @@ -Application Architecture Guide -============================== - -Here we provide a brief guide on the recommended architecture of a Tendermint blockchain -application. - -The following diagram provides a superb example: - -https://drive.google.com/open?id=1yR2XpRi9YCY9H9uMfcw8-RMJpvDyvjz9 - -The end-user application here is the Cosmos Voyager, at the bottom left. -Voyager communicates with a REST API exposed by a local Light-Client Daemon. -The Light-Client Daemon is an application specific program that communicates with -Tendermint nodes and verifies Tendermint light-client proofs through the Tendermint Core RPC. -The Tendermint Core process communicates with a local ABCI application, where the -user query or transaction is actually processed. - -The ABCI application must be a deterministic result of the Tendermint consensus - any external influence -on the application state that didn't come through Tendermint could cause a -consensus failure. Thus *nothing* should communicate with the application except Tendermint via ABCI. - -If the application is written in Go, it can be compiled into the Tendermint binary. -Otherwise, it should use a unix socket to communicate with Tendermint. -If it's necessary to use TCP, extra care must be taken to encrypt and authenticate the connection. - -All reads from the app happen through the Tendermint `/abci_query` endpoint. -All writes to the app happen through the Tendermint `/broadcast_tx_*` endpoints. - -The Light-Client Daemon is what provides light clients (end users) with nearly all the security of a full node. -It formats and broadcasts transactions, and verifies proofs of queries and transaction results. -Note that it need not be a daemon - the Light-Client logic could instead be implemented in the same process as the end-user application. - -Note for those ABCI applications with weaker security requirements, the functionality of the Light-Client Daemon can be moved -into the ABCI application process itself. That said, exposing the application process to anything besides Tendermint over ABCI -requires extreme caution, as all transactions, and possibly all queries, should still pass through Tendermint. - -See the following for more extensive documentation: -- [Interchain Standard for the Light-Client REST API](https://github.com/cosmos/cosmos-sdk/pull/1028) -- [Tendermint RPC Docs](https://tendermint.github.io/slate/) -- [Tendermint in Production](https://github.com/tendermint/tendermint/pull/1618) -- [Tendermint Basics](https://tendermint.readthedocs.io/en/master/using-tendermint.html) -- [ABCI spec](https://github.com/tendermint/abci/blob/master/specification.rst) diff --git a/docs/app-development.md b/docs/app-development.md new file mode 100644 index 00000000..48865767 --- /dev/null +++ b/docs/app-development.md @@ -0,0 +1,527 @@ +# Application Development Guide + +## ABCI Design + +The purpose of ABCI is to provide a clean interface between state +transition machines on one computer and the mechanics of their +replication across multiple computers. The former we call 'application +logic' and the latter the 'consensus engine'. Application logic +validates transactions and optionally executes transactions against some +persistent state. A consensus engine ensures all transactions are +replicated in the same order on every machine. We call each machine in a +consensus engine a 'validator', and each validator runs the same +transactions through the same application logic. In particular, we are +interested in blockchain-style consensus engines, where transactions are +committed in hash-linked blocks. + +The ABCI design has a few distinct components: + +- message protocol + - pairs of request and response messages + - consensus makes requests, application responds + - defined using protobuf +- server/client + - consensus engine runs the client + - application runs the server + - two implementations: + - async raw bytes + - grpc +- blockchain protocol + - abci is connection oriented + - Tendermint Core maintains three connections: + - [mempool connection](#mempool-connection): for checking if + transactions should be relayed before they are committed; + only uses `CheckTx` + - [consensus connection](#consensus-connection): for executing + transactions that have been committed. Message sequence is + -for every block + -`BeginBlock, [DeliverTx, ...], EndBlock, Commit` + - [query connection](#query-connection): for querying the + application state; only uses Query and Info + +The mempool and consensus logic act as clients, and each maintains an +open ABCI connection with the application, which hosts an ABCI server. +Shown are the request and response types sent on each connection. + +## Message Protocol + +The message protocol consists of pairs of requests and responses. Some +messages have no fields, while others may include byte-arrays, strings, +or integers. See the `message Request` and `message Response` +definitions in [the protobuf definition +file](https://github.com/tendermint/abci/blob/master/types/types.proto), +and the [protobuf +documentation](https://developers.google.com/protocol-buffers/docs/overview) +for more details. + +For each request, a server should respond with the corresponding +response, where order of requests is preserved in the order of +responses. + +## Server + +To use ABCI in your programming language of choice, there must be a ABCI +server in that language. Tendermint supports two kinds of implementation +of the server: + +- Asynchronous, raw socket server (Tendermint Socket Protocol, also + known as TSP or Teaspoon) +- GRPC + +Both can be tested using the `abci-cli` by setting the `--abci` flag +appropriately (ie. to `socket` or `grpc`). + +See examples, in various stages of maintenance, in +[Go](https://github.com/tendermint/abci/tree/master/server), +[JavaScript](https://github.com/tendermint/js-abci), +[Python](https://github.com/tendermint/abci/tree/master/example/python3/abci), +[C++](https://github.com/mdyring/cpp-tmsp), and +[Java](https://github.com/jTendermint/jabci). + +### GRPC + +If GRPC is available in your language, this is the easiest approach, +though it will have significant performance overhead. + +To get started with GRPC, copy in the [protobuf +file](https://github.com/tendermint/abci/blob/master/types/types.proto) +and compile it using the GRPC plugin for your language. For instance, +for golang, the command is `protoc --go_out=plugins=grpc:. types.proto`. +See the [grpc documentation for more details](http://www.grpc.io/docs/). +`protoc` will autogenerate all the necessary code for ABCI client and +server in your language, including whatever interface your application +must satisfy to be used by the ABCI server for handling requests. + +### TSP + +If GRPC is not available in your language, or you require higher +performance, or otherwise enjoy programming, you may implement your own +ABCI server using the Tendermint Socket Protocol, known affectionately +as Teaspoon. The first step is still to auto-generate the relevant data +types and codec in your language using `protoc`. Messages coming over +the socket are Protobuf3 encoded, but additionally length-prefixed to +facilitate use as a streaming protocol. Protobuf3 doesn't have an +official length-prefix standard, so we use our own. The first byte in +the prefix represents the length of the Big Endian encoded length. The +remaining bytes in the prefix are the Big Endian encoded length. + +For example, if the Protobuf3 encoded ABCI message is 0xDEADBEEF (4 +bytes), the length-prefixed message is 0x0104DEADBEEF. If the Protobuf3 +encoded ABCI message is 65535 bytes long, the length-prefixed message +would be like 0x02FFFF.... + +Note this prefixing does not apply for grpc. + +An ABCI server must also be able to support multiple connections, as +Tendermint uses three connections. + +## Client + +There are currently two use-cases for an ABCI client. One is a testing +tool, as in the `abci-cli`, which allows ABCI requests to be sent via +command line. The other is a consensus engine, such as Tendermint Core, +which makes requests to the application every time a new transaction is +received or a block is committed. + +It is unlikely that you will need to implement a client. For details of +our client, see +[here](https://github.com/tendermint/abci/tree/master/client). + +Most of the examples below are from [kvstore +application](https://github.com/tendermint/abci/blob/master/example/kvstore/kvstore.go), +which is a part of the abci repo. [persistent_kvstore +application](https://github.com/tendermint/abci/blob/master/example/kvstore/persistent_kvstore.go) +is used to show `BeginBlock`, `EndBlock` and `InitChain` example +implementations. + +## Blockchain Protocol + +In ABCI, a transaction is simply an arbitrary length byte-array. It is +the application's responsibility to define the transaction codec as they +please, and to use it for both CheckTx and DeliverTx. + +Note that there are two distinct means for running transactions, +corresponding to stages of 'awareness' of the transaction in the +network. The first stage is when a transaction is received by a +validator from a client into the so-called mempool or transaction pool +-this is where we use CheckTx. The second is when the transaction is +successfully committed on more than 2/3 of validators - where we use +DeliverTx. In the former case, it may not be necessary to run all the +state transitions associated with the transaction, as the transaction +may not ultimately be committed until some much later time, when the +result of its execution will be different. For instance, an Ethereum +ABCI app would check signatures and amounts in CheckTx, but would not +actually execute any contract code until the DeliverTx, so as to avoid +executing state transitions that have not been finalized. + +To formalize the distinction further, two explicit ABCI connections are +made between Tendermint Core and the application: the mempool connection +and the consensus connection. We also make a third connection, the query +connection, to query the local state of the app. + +### Mempool Connection + +The mempool connection is used *only* for CheckTx requests. Transactions +are run using CheckTx in the same order they were received by the +validator. If the CheckTx returns `OK`, the transaction is kept in +memory and relayed to other peers in the same order it was received. +Otherwise, it is discarded. + +CheckTx requests run concurrently with block processing; so they should +run against a copy of the main application state which is reset after +every block. This copy is necessary to track transitions made by a +sequence of CheckTx requests before they are included in a block. When a +block is committed, the application must ensure to reset the mempool +state to the latest committed state. Tendermint Core will then filter +through all transactions in the mempool, removing any that were included +in the block, and re-run the rest using CheckTx against the post-Commit +mempool state (this behaviour can be turned off with +`[mempool] recheck = false`). + +In go: + + func (app *KVStoreApplication) CheckTx(tx []byte) types.Result { + return types.OK + } + +In Java: + + ResponseCheckTx requestCheckTx(RequestCheckTx req) { + byte[] transaction = req.getTx().toByteArray(); + + // validate transaction + + if (notValid) { + return ResponseCheckTx.newBuilder().setCode(CodeType.BadNonce).setLog("invalid tx").build(); + } else { + return ResponseCheckTx.newBuilder().setCode(CodeType.OK).build(); + } + } + +### Replay Protection + +To prevent old transactions from being replayed, CheckTx must implement +replay protection. + +Tendermint provides the first defence layer by keeping a lightweight +in-memory cache of 100k (`[mempool] cache_size`) last transactions in +the mempool. If Tendermint is just started or the clients sent more than +100k transactions, old transactions may be sent to the application. So +it is important CheckTx implements some logic to handle them. + +There are cases where a transaction will (or may) become valid in some +future state, in which case you probably want to disable Tendermint's +cache. You can do that by setting `[mempool] cache_size = 0` in the +config. + +### Consensus Connection + +The consensus connection is used only when a new block is committed, and +communicates all information from the block in a series of requests: +`BeginBlock, [DeliverTx, ...], EndBlock, Commit`. That is, when a block +is committed in the consensus, we send a list of DeliverTx requests (one +for each transaction) sandwiched by BeginBlock and EndBlock requests, +and followed by a Commit. + +### DeliverTx + +DeliverTx is the workhorse of the blockchain. Tendermint sends the +DeliverTx requests asynchronously but in order, and relies on the +underlying socket protocol (ie. TCP) to ensure they are received by the +app in order. They have already been ordered in the global consensus by +the Tendermint protocol. + +DeliverTx returns a abci.Result, which includes a Code, Data, and Log. +The code may be non-zero (non-OK), meaning the corresponding transaction +should have been rejected by the mempool, but may have been included in +a block by a Byzantine proposer. + +The block header will be updated (TODO) to include some commitment to +the results of DeliverTx, be it a bitarray of non-OK transactions, or a +merkle root of the data returned by the DeliverTx requests, or both. + +In go: + + // tx is either "key=value" or just arbitrary bytes + func (app *KVStoreApplication) DeliverTx(tx []byte) types.Result { + parts := strings.Split(string(tx), "=") + if len(parts) == 2 { + app.state.Set([]byte(parts[0]), []byte(parts[1])) + } else { + app.state.Set(tx, tx) + } + return types.OK + } + +In Java: + + /** + * Using Protobuf types from the protoc compiler, we always start with a byte[] + */ + ResponseDeliverTx deliverTx(RequestDeliverTx request) { + byte[] transaction = request.getTx().toByteArray(); + + // validate your transaction + + if (notValid) { + return ResponseDeliverTx.newBuilder().setCode(CodeType.BadNonce).setLog("transaction was invalid").build(); + } else { + ResponseDeliverTx.newBuilder().setCode(CodeType.OK).build(); + } + + } + +### Commit + +Once all processing of the block is complete, Tendermint sends the +Commit request and blocks waiting for a response. While the mempool may +run concurrently with block processing (the BeginBlock, DeliverTxs, and +EndBlock), it is locked for the Commit request so that its state can be +safely reset during Commit. This means the app *MUST NOT* do any +blocking communication with the mempool (ie. broadcast\_tx) during +Commit, or there will be deadlock. Note also that all remaining +transactions in the mempool are replayed on the mempool connection +(CheckTx) following a commit. + +The app should respond to the Commit request with a byte array, which is +the deterministic state root of the application. It is included in the +header of the next block. It can be used to provide easily verified +Merkle-proofs of the state of the application. + +It is expected that the app will persist state to disk on Commit. The +option to have all transactions replayed from some previous block is the +job of the [Handshake](#handshake). + +In go: + + func (app *KVStoreApplication) Commit() types.Result { + hash := app.state.Hash() + return types.NewResultOK(hash, "") + } + +In Java: + + ResponseCommit requestCommit(RequestCommit requestCommit) { + + // update the internal app-state + byte[] newAppState = calculateAppState(); + + // and return it to the node + return ResponseCommit.newBuilder().setCode(CodeType.OK).setData(ByteString.copyFrom(newAppState)).build(); + } + +### BeginBlock + +The BeginBlock request can be used to run some code at the beginning of +every block. It also allows Tendermint to send the current block hash +and header to the application, before it sends any of the transactions. + +The app should remember the latest height and header (ie. from which it +has run a successful Commit) so that it can tell Tendermint where to +pick up from when it restarts. See information on the Handshake, below. + +In go: + + // Track the block hash and header information + func (app *PersistentKVStoreApplication) BeginBlock(params types.RequestBeginBlock) { + // update latest block info + app.blockHeader = params.Header + + // reset valset changes + app.changes = make([]*types.Validator, 0) + } + +In Java: + + /* + * all types come from protobuf definition + */ + ResponseBeginBlock requestBeginBlock(RequestBeginBlock req) { + + Header header = req.getHeader(); + byte[] prevAppHash = header.getAppHash().toByteArray(); + long prevHeight = header.getHeight(); + long numTxs = header.getNumTxs(); + + // run your pre-block logic. Maybe prepare a state snapshot, message components, etc + + return ResponseBeginBlock.newBuilder().build(); + } + +### EndBlock + +The EndBlock request can be used to run some code at the end of every +block. Additionally, the response may contain a list of validators, +which can be used to update the validator set. To add a new validator or +update an existing one, simply include them in the list returned in the +EndBlock response. To remove one, include it in the list with a `power` +equal to `0`. Tendermint core will take care of updating the validator +set. Note the change in voting power must be strictly less than 1/3 per +block if you want a light client to be able to prove the transition +externally. See the [light client +docs](https://godoc.org/github.com/tendermint/tendermint/lite#hdr-How_We_Track_Validators) +for details on how it tracks validators. + +In go: + + // Update the validator set + func (app *PersistentKVStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { + return types.ResponseEndBlock{ValidatorUpdates: app.ValUpdates} + } + +In Java: + + /* + * Assume that one validator changes. The new validator has a power of 10 + */ + ResponseEndBlock requestEndBlock(RequestEndBlock req) { + final long currentHeight = req.getHeight(); + final byte[] validatorPubKey = getValPubKey(); + + ResponseEndBlock.Builder builder = ResponseEndBlock.newBuilder(); + builder.addDiffs(1, Types.Validator.newBuilder().setPower(10L).setPubKey(ByteString.copyFrom(validatorPubKey)).build()); + + return builder.build(); + } + +### Query Connection + +This connection is used to query the application without engaging +consensus. It's exposed over the tendermint core rpc, so clients can +query the app without exposing a server on the app itself, but they must +serialize each query as a single byte array. Additionally, certain +"standardized" queries may be used to inform local decisions, for +instance about which peers to connect to. + +Tendermint Core currently uses the Query connection to filter peers upon +connecting, according to IP address or public key. For instance, +returning non-OK ABCI response to either of the following queries will +cause Tendermint to not connect to the corresponding peer: + +- `p2p/filter/addr/`, where `` is an IP address. +- `p2p/filter/pubkey/`, where `` is the hex-encoded + ED25519 key of the node (not it's validator key) + +Note: these query formats are subject to change! + +In go: + + func (app *KVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { + if reqQuery.Prove { + value, proof, exists := app.state.Proof(reqQuery.Data) + resQuery.Index = -1 // TODO make Proof return index + resQuery.Key = reqQuery.Data + resQuery.Value = value + resQuery.Proof = proof + if exists { + resQuery.Log = "exists" + } else { + resQuery.Log = "does not exist" + } + return + } else { + index, value, exists := app.state.Get(reqQuery.Data) + resQuery.Index = int64(index) + resQuery.Value = value + if exists { + resQuery.Log = "exists" + } else { + resQuery.Log = "does not exist" + } + return + } + } + +In Java: + + ResponseQuery requestQuery(RequestQuery req) { + final boolean isProveQuery = req.getProve(); + final ResponseQuery.Builder responseBuilder = ResponseQuery.newBuilder(); + + if (isProveQuery) { + com.app.example.ProofResult proofResult = generateProof(req.getData().toByteArray()); + final byte[] proofAsByteArray = proofResult.getAsByteArray(); + + responseBuilder.setProof(ByteString.copyFrom(proofAsByteArray)); + responseBuilder.setKey(req.getData()); + responseBuilder.setValue(ByteString.copyFrom(proofResult.getData())); + responseBuilder.setLog(result.getLogValue()); + } else { + byte[] queryData = req.getData().toByteArray(); + + final com.app.example.QueryResult result = generateQueryResult(queryData); + + responseBuilder.setIndex(result.getIndex()); + responseBuilder.setValue(ByteString.copyFrom(result.getValue())); + responseBuilder.setLog(result.getLogValue()); + } + + return responseBuilder.build(); + } + +### Handshake + +When the app or tendermint restarts, they need to sync to a common +height. When an ABCI connection is first established, Tendermint will +call `Info` on the Query connection. The response should contain the +LastBlockHeight and LastBlockAppHash - the former is the last block for +which the app ran Commit successfully, the latter is the response from +that Commit. + +Using this information, Tendermint will determine what needs to be +replayed, if anything, against the app, to ensure both Tendermint and +the app are synced to the latest block height. + +If the app returns a LastBlockHeight of 0, Tendermint will just replay +all blocks. + +In go: + + func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { + return types.ResponseInfo{Data: cmn.Fmt("{\"size\":%v}", app.state.Size())} + } + +In Java: + + ResponseInfo requestInfo(RequestInfo req) { + final byte[] lastAppHash = getLastAppHash(); + final long lastHeight = getLastHeight(); + return ResponseInfo.newBuilder().setLastBlockAppHash(ByteString.copyFrom(lastAppHash)).setLastBlockHeight(lastHeight).build(); + } + +### Genesis + +`InitChain` will be called once upon the genesis. `params` includes the +initial validator set. Later on, it may be extended to take parts of the +consensus params. + +In go: + + // Save the validators in the merkle tree + func (app *PersistentKVStoreApplication) InitChain(params types.RequestInitChain) { + for _, v := range params.Validators { + r := app.updateValidator(v) + if r.IsErr() { + app.logger.Error("Error updating validators", "r", r) + } + } + } + +In Java: + + /* + * all types come from protobuf definition + */ + ResponseInitChain requestInitChain(RequestInitChain req) { + final int validatorsCount = req.getValidatorsCount(); + final List validatorsList = req.getValidatorsList(); + + validatorsList.forEach((validator) -> { + long power = validator.getPower(); + byte[] validatorPubKey = validator.getPubKey().toByteArray(); + + // do somehing for validator setup in app + }); + + return ResponseInitChain.newBuilder().build(); + } diff --git a/docs/app-development.rst b/docs/app-development.rst deleted file mode 100644 index 9aefa99c..00000000 --- a/docs/app-development.rst +++ /dev/null @@ -1,648 +0,0 @@ -Application Development Guide -============================= - -ABCI Design ------------ - -The purpose of ABCI is to provide a clean interface between state -transition machines on one computer and the mechanics of their -replication across multiple computers. The former we call 'application -logic' and the latter the 'consensus engine'. Application logic -validates transactions and optionally executes transactions against some -persistent state. A consensus engine ensures all transactions are -replicated in the same order on every machine. We call each machine in a -consensus engine a 'validator', and each validator runs the same -transactions through the same application logic. In particular, we are -interested in blockchain-style consensus engines, where transactions are -committed in hash-linked blocks. - -The ABCI design has a few distinct components: - -- message protocol - - - pairs of request and response messages - - consensus makes requests, application responds - - defined using protobuf - -- server/client - - - consensus engine runs the client - - application runs the server - - two implementations: - - - async raw bytes - - grpc - -- blockchain protocol - - - abci is connection oriented - - Tendermint Core maintains three connections: - - - `mempool connection <#mempool-connection>`__: for checking if - transactions should be relayed before they are committed; only - uses ``CheckTx`` - - `consensus connection <#consensus-connection>`__: for executing - transactions that have been committed. Message sequence is - - for every block - - ``BeginBlock, [DeliverTx, ...], EndBlock, Commit`` - - `query connection <#query-connection>`__: for querying the - application state; only uses Query and Info - -The mempool and consensus logic act as clients, and each maintains an -open ABCI connection with the application, which hosts an ABCI server. -Shown are the request and response types sent on each connection. - -Message Protocol ----------------- - -The message protocol consists of pairs of requests and responses. Some -messages have no fields, while others may include byte-arrays, strings, -or integers. See the ``message Request`` and ``message Response`` -definitions in `the protobuf definition -file `__, -and the `protobuf -documentation `__ -for more details. - -For each request, a server should respond with the corresponding -response, where order of requests is preserved in the order of -responses. - -Server ------- - -To use ABCI in your programming language of choice, there must be a ABCI -server in that language. Tendermint supports two kinds of implementation -of the server: - -- Asynchronous, raw socket server (Tendermint Socket Protocol, also - known as TSP or Teaspoon) -- GRPC - -Both can be tested using the ``abci-cli`` by setting the ``--abci`` flag -appropriately (ie. to ``socket`` or ``grpc``). - -See examples, in various stages of maintenance, in -`Go `__, -`JavaScript `__, -`Python `__, -`C++ `__, and -`Java `__. - -GRPC -~~~~ - -If GRPC is available in your language, this is the easiest approach, -though it will have significant performance overhead. - -To get started with GRPC, copy in the `protobuf -file `__ -and compile it using the GRPC plugin for your language. For instance, -for golang, the command is -``protoc --go_out=plugins=grpc:. types.proto``. See the `grpc -documentation for more details `__. ``protoc`` -will autogenerate all the necessary code for ABCI client and server in -your language, including whatever interface your application must -satisfy to be used by the ABCI server for handling requests. - -TSP -~~~ - -If GRPC is not available in your language, or you require higher -performance, or otherwise enjoy programming, you may implement your own -ABCI server using the Tendermint Socket Protocol, known affectionately -as Teaspoon. The first step is still to auto-generate the relevant data -types and codec in your language using ``protoc``. Messages coming over -the socket are Protobuf3 encoded, but additionally length-prefixed to -facilitate use as a streaming protocol. Protobuf3 doesn't have an -official length-prefix standard, so we use our own. The first byte in -the prefix represents the length of the Big Endian encoded length. The -remaining bytes in the prefix are the Big Endian encoded length. - -For example, if the Protobuf3 encoded ABCI message is 0xDEADBEEF (4 -bytes), the length-prefixed message is 0x0104DEADBEEF. If the Protobuf3 -encoded ABCI message is 65535 bytes long, the length-prefixed message -would be like 0x02FFFF.... - -Note this prefixing does not apply for grpc. - -An ABCI server must also be able to support multiple connections, as -Tendermint uses three connections. - -Client ------- - -There are currently two use-cases for an ABCI client. One is a testing -tool, as in the ``abci-cli``, which allows ABCI requests to be sent via -command line. The other is a consensus engine, such as Tendermint Core, -which makes requests to the application every time a new transaction is -received or a block is committed. - -It is unlikely that you will need to implement a client. For details of -our client, see -`here `__. - -Most of the examples below are from `kvstore application -`__, -which is a part of the abci repo. `persistent_kvstore application -`__ -is used to show ``BeginBlock``, ``EndBlock`` and ``InitChain`` -example implementations. - -Blockchain Protocol -------------------- - -In ABCI, a transaction is simply an arbitrary length byte-array. It is -the application's responsibility to define the transaction codec as they -please, and to use it for both CheckTx and DeliverTx. - -Note that there are two distinct means for running transactions, -corresponding to stages of 'awareness' of the transaction in the -network. The first stage is when a transaction is received by a -validator from a client into the so-called mempool or transaction pool - -this is where we use CheckTx. The second is when the transaction is -successfully committed on more than 2/3 of validators - where we use -DeliverTx. In the former case, it may not be necessary to run all the -state transitions associated with the transaction, as the transaction -may not ultimately be committed until some much later time, when the -result of its execution will be different. For instance, an Ethereum -ABCI app would check signatures and amounts in CheckTx, but would not -actually execute any contract code until the DeliverTx, so as to avoid -executing state transitions that have not been finalized. - -To formalize the distinction further, two explicit ABCI connections are -made between Tendermint Core and the application: the mempool connection -and the consensus connection. We also make a third connection, the query -connection, to query the local state of the app. - -Mempool Connection -~~~~~~~~~~~~~~~~~~ - -The mempool connection is used *only* for CheckTx requests. -Transactions are run using CheckTx in the same order they were -received by the validator. If the CheckTx returns ``OK``, the -transaction is kept in memory and relayed to other peers in the same -order it was received. Otherwise, it is discarded. - -CheckTx requests run concurrently with block processing; so they -should run against a copy of the main application state which is reset -after every block. This copy is necessary to track transitions made by -a sequence of CheckTx requests before they are included in a block. -When a block is committed, the application must ensure to reset the -mempool state to the latest committed state. Tendermint Core will then -filter through all transactions in the mempool, removing any that were -included in the block, and re-run the rest using CheckTx against the -post-Commit mempool state (this behaviour can be turned off with -``[mempool] recheck = false``). - -.. container:: toggle - - .. container:: header - - **Show/Hide Go Example** - - .. code-block:: go - - func (app *KVStoreApplication) CheckTx(tx []byte) types.Result { - return types.OK - } - -.. container:: toggle - - .. container:: header - - **Show/Hide Java Example** - - .. code-block:: java - - ResponseCheckTx requestCheckTx(RequestCheckTx req) { - byte[] transaction = req.getTx().toByteArray(); - - // validate transaction - - if (notValid) { - return ResponseCheckTx.newBuilder().setCode(CodeType.BadNonce).setLog("invalid tx").build(); - } else { - return ResponseCheckTx.newBuilder().setCode(CodeType.OK).build(); - } - } - -Replay Protection -^^^^^^^^^^^^^^^^^ -To prevent old transactions from being replayed, CheckTx must -implement replay protection. - -Tendermint provides the first defence layer by keeping a lightweight -in-memory cache of 100k (``[mempool] cache_size``) last transactions in -the mempool. If Tendermint is just started or the clients sent more -than 100k transactions, old transactions may be sent to the -application. So it is important CheckTx implements some logic to -handle them. - -There are cases where a transaction will (or may) become valid in some -future state, in which case you probably want to disable Tendermint's -cache. You can do that by setting ``[mempool] cache_size = 0`` in the -config. - -Consensus Connection -~~~~~~~~~~~~~~~~~~~~ - -The consensus connection is used only when a new block is committed, and -communicates all information from the block in a series of requests: -``BeginBlock, [DeliverTx, ...], EndBlock, Commit``. That is, when a -block is committed in the consensus, we send a list of DeliverTx -requests (one for each transaction) sandwiched by BeginBlock and -EndBlock requests, and followed by a Commit. - -DeliverTx -^^^^^^^^^ - -DeliverTx is the workhorse of the blockchain. Tendermint sends the -DeliverTx requests asynchronously but in order, and relies on the -underlying socket protocol (ie. TCP) to ensure they are received by the -app in order. They have already been ordered in the global consensus by -the Tendermint protocol. - -DeliverTx returns a abci.Result, which includes a Code, Data, and Log. -The code may be non-zero (non-OK), meaning the corresponding transaction -should have been rejected by the mempool, but may have been included in -a block by a Byzantine proposer. - -The block header will be updated (TODO) to include some commitment to -the results of DeliverTx, be it a bitarray of non-OK transactions, or a -merkle root of the data returned by the DeliverTx requests, or both. - -.. container:: toggle - - .. container:: header - - **Show/Hide Go Example** - - .. code-block:: go - - // tx is either "key=value" or just arbitrary bytes - func (app *KVStoreApplication) DeliverTx(tx []byte) types.Result { - parts := strings.Split(string(tx), "=") - if len(parts) == 2 { - app.state.Set([]byte(parts[0]), []byte(parts[1])) - } else { - app.state.Set(tx, tx) - } - return types.OK - } - -.. container:: toggle - - .. container:: header - - **Show/Hide Java Example** - - .. code-block:: java - - /** - * Using Protobuf types from the protoc compiler, we always start with a byte[] - */ - ResponseDeliverTx deliverTx(RequestDeliverTx request) { - byte[] transaction = request.getTx().toByteArray(); - - // validate your transaction - - if (notValid) { - return ResponseDeliverTx.newBuilder().setCode(CodeType.BadNonce).setLog("transaction was invalid").build(); - } else { - ResponseDeliverTx.newBuilder().setCode(CodeType.OK).build(); - } - - } - -Commit -^^^^^^ - -Once all processing of the block is complete, Tendermint sends the -Commit request and blocks waiting for a response. While the mempool may -run concurrently with block processing (the BeginBlock, DeliverTxs, and -EndBlock), it is locked for the Commit request so that its state can be -safely reset during Commit. This means the app *MUST NOT* do any -blocking communication with the mempool (ie. broadcast\_tx) during -Commit, or there will be deadlock. Note also that all remaining -transactions in the mempool are replayed on the mempool connection -(CheckTx) following a commit. - -The app should respond to the Commit request with a byte array, which is the deterministic -state root of the application. It is included in the header of the next -block. It can be used to provide easily verified Merkle-proofs of the -state of the application. - -It is expected that the app will persist state to disk on Commit. The -option to have all transactions replayed from some previous block is the -job of the `Handshake <#handshake>`__. - -.. container:: toggle - - .. container:: header - - **Show/Hide Go Example** - - .. code-block:: go - - func (app *KVStoreApplication) Commit() types.Result { - hash := app.state.Hash() - return types.NewResultOK(hash, "") - } - -.. container:: toggle - - .. container:: header - - **Show/Hide Java Example** - - .. code-block:: java - - ResponseCommit requestCommit(RequestCommit requestCommit) { - - // update the internal app-state - byte[] newAppState = calculateAppState(); - - // and return it to the node - return ResponseCommit.newBuilder().setCode(CodeType.OK).setData(ByteString.copyFrom(newAppState)).build(); - } - -BeginBlock -^^^^^^^^^^ - -The BeginBlock request can be used to run some code at the beginning of -every block. It also allows Tendermint to send the current block hash -and header to the application, before it sends any of the transactions. - -The app should remember the latest height and header (ie. from which it -has run a successful Commit) so that it can tell Tendermint where to -pick up from when it restarts. See information on the Handshake, below. - -.. container:: toggle - - .. container:: header - - **Show/Hide Go Example** - - .. code-block:: go - - // Track the block hash and header information - func (app *PersistentKVStoreApplication) BeginBlock(params types.RequestBeginBlock) { - // update latest block info - app.blockHeader = params.Header - - // reset valset changes - app.changes = make([]*types.Validator, 0) - } - -.. container:: toggle - - .. container:: header - - **Show/Hide Java Example** - - .. code-block:: java - - /* - * all types come from protobuf definition - */ - ResponseBeginBlock requestBeginBlock(RequestBeginBlock req) { - - Header header = req.getHeader(); - byte[] prevAppHash = header.getAppHash().toByteArray(); - long prevHeight = header.getHeight(); - long numTxs = header.getNumTxs(); - - // run your pre-block logic. Maybe prepare a state snapshot, message components, etc - - return ResponseBeginBlock.newBuilder().build(); - } - -EndBlock -^^^^^^^^ - -The EndBlock request can be used to run some code at the end of every block. -Additionally, the response may contain a list of validators, which can be used -to update the validator set. To add a new validator or update an existing one, -simply include them in the list returned in the EndBlock response. To remove -one, include it in the list with a ``power`` equal to ``0``. Tendermint core -will take care of updating the validator set. Note the change in voting power -must be strictly less than 1/3 per block if you want a light client to be able -to prove the transition externally. See the `light client docs -`__ -for details on how it tracks validators. - -.. container:: toggle - - .. container:: header - - **Show/Hide Go Example** - - .. code-block:: go - - // Update the validator set - func (app *PersistentKVStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock { - return types.ResponseEndBlock{ValidatorUpdates: app.ValUpdates} - } - -.. container:: toggle - - .. container:: header - - **Show/Hide Java Example** - - .. code-block:: java - - /* - * Assume that one validator changes. The new validator has a power of 10 - */ - ResponseEndBlock requestEndBlock(RequestEndBlock req) { - final long currentHeight = req.getHeight(); - final byte[] validatorPubKey = getValPubKey(); - - ResponseEndBlock.Builder builder = ResponseEndBlock.newBuilder(); - builder.addDiffs(1, Types.Validator.newBuilder().setPower(10L).setPubKey(ByteString.copyFrom(validatorPubKey)).build()); - - return builder.build(); - } - -Query Connection -~~~~~~~~~~~~~~~~ - -This connection is used to query the application without engaging -consensus. It's exposed over the tendermint core rpc, so clients can -query the app without exposing a server on the app itself, but they must -serialize each query as a single byte array. Additionally, certain -"standardized" queries may be used to inform local decisions, for -instance about which peers to connect to. - -Tendermint Core currently uses the Query connection to filter peers upon -connecting, according to IP address or public key. For instance, -returning non-OK ABCI response to either of the following queries will -cause Tendermint to not connect to the corresponding peer: - -- ``p2p/filter/addr/``, where ```` is an IP address. -- ``p2p/filter/pubkey/``, where ```` is the hex-encoded - ED25519 key of the node (not it's validator key) - -Note: these query formats are subject to change! - -.. container:: toggle - - .. container:: header - - **Show/Hide Go Example** - - .. code-block:: go - - func (app *KVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) { - if reqQuery.Prove { - value, proof, exists := app.state.Proof(reqQuery.Data) - resQuery.Index = -1 // TODO make Proof return index - resQuery.Key = reqQuery.Data - resQuery.Value = value - resQuery.Proof = proof - if exists { - resQuery.Log = "exists" - } else { - resQuery.Log = "does not exist" - } - return - } else { - index, value, exists := app.state.Get(reqQuery.Data) - resQuery.Index = int64(index) - resQuery.Value = value - if exists { - resQuery.Log = "exists" - } else { - resQuery.Log = "does not exist" - } - return - } - } - -.. container:: toggle - - .. container:: header - - **Show/Hide Java Example** - - .. code-block:: java - - ResponseQuery requestQuery(RequestQuery req) { - final boolean isProveQuery = req.getProve(); - final ResponseQuery.Builder responseBuilder = ResponseQuery.newBuilder(); - - if (isProveQuery) { - com.app.example.ProofResult proofResult = generateProof(req.getData().toByteArray()); - final byte[] proofAsByteArray = proofResult.getAsByteArray(); - - responseBuilder.setProof(ByteString.copyFrom(proofAsByteArray)); - responseBuilder.setKey(req.getData()); - responseBuilder.setValue(ByteString.copyFrom(proofResult.getData())); - responseBuilder.setLog(result.getLogValue()); - } else { - byte[] queryData = req.getData().toByteArray(); - - final com.app.example.QueryResult result = generateQueryResult(queryData); - - responseBuilder.setIndex(result.getIndex()); - responseBuilder.setValue(ByteString.copyFrom(result.getValue())); - responseBuilder.setLog(result.getLogValue()); - } - - return responseBuilder.build(); - } - -Handshake -~~~~~~~~~ - -When the app or tendermint restarts, they need to sync to a common -height. When an ABCI connection is first established, Tendermint will -call ``Info`` on the Query connection. The response should contain the -LastBlockHeight and LastBlockAppHash - the former is the last block for -which the app ran Commit successfully, the latter is the response -from that Commit. - -Using this information, Tendermint will determine what needs to be -replayed, if anything, against the app, to ensure both Tendermint and -the app are synced to the latest block height. - -If the app returns a LastBlockHeight of 0, Tendermint will just replay -all blocks. - -.. container:: toggle - - .. container:: header - - **Show/Hide Go Example** - - .. code-block:: go - - func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) { - return types.ResponseInfo{Data: cmn.Fmt("{\"size\":%v}", app.state.Size())} - } - -.. container:: toggle - - .. container:: header - - **Show/Hide Java Example** - - .. code-block:: java - - ResponseInfo requestInfo(RequestInfo req) { - final byte[] lastAppHash = getLastAppHash(); - final long lastHeight = getLastHeight(); - return ResponseInfo.newBuilder().setLastBlockAppHash(ByteString.copyFrom(lastAppHash)).setLastBlockHeight(lastHeight).build(); - } - -Genesis -~~~~~~~ - -``InitChain`` will be called once upon the genesis. ``params`` includes the -initial validator set. Later on, it may be extended to take parts of the -consensus params. - -.. container:: toggle - - .. container:: header - - **Show/Hide Go Example** - - .. code-block:: go - - // Save the validators in the merkle tree - func (app *PersistentKVStoreApplication) InitChain(params types.RequestInitChain) { - for _, v := range params.Validators { - r := app.updateValidator(v) - if r.IsErr() { - app.logger.Error("Error updating validators", "r", r) - } - } - } - -.. container:: toggle - - .. container:: header - - **Show/Hide Java Example** - - .. code-block:: java - - /* - * all types come from protobuf definition - */ - ResponseInitChain requestInitChain(RequestInitChain req) { - final int validatorsCount = req.getValidatorsCount(); - final List validatorsList = req.getValidatorsList(); - - validatorsList.forEach((validator) -> { - long power = validator.getPower(); - byte[] validatorPubKey = validator.getPubKey().toByteArray(); - - // do somehing for validator setup in app - }); - - return ResponseInitChain.newBuilder().build(); - } diff --git a/docs/conf.py b/docs/conf.py index 08617378..7d52a493 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -41,8 +41,15 @@ templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # -#source_suffix = ['.rst', '.md'] -source_suffix = '.rst' + +from recommonmark.parser import CommonMarkParser + +source_parsers = { + '.md': CommonMarkParser, +} + +source_suffix = ['.rst', '.md'] +#source_suffix = '.rst' # The master toctree document. master_doc = 'index' @@ -171,27 +178,29 @@ texinfo_documents = [ 'Database'), ] -# ---- customization ------------------------- +# ---------------- customizations ---------------------- +# for Docker README, below +from shutil import copyfile + +# tm-bench and tm-monitor tools_repo = "https://raw.githubusercontent.com/tendermint/tools/" tools_branch = "master" tools_dir = "./tools" -assets_dir = tools_dir + "/assets" + if os.path.isdir(tools_dir) != True: os.mkdir(tools_dir) -if os.path.isdir(assets_dir) != True: - os.mkdir(assets_dir) -urllib.urlretrieve(tools_repo+tools_branch+'/docker/README.rst', filename=tools_dir+'/docker.rst') +copyfile('../DOCKER/README.md', tools_dir+'/docker.md') -urllib.urlretrieve(tools_repo+tools_branch+'/tm-bench/README.rst', filename=tools_dir+'/benchmarking.rst') -urllib.urlretrieve(tools_repo+tools_branch+'/tm-monitor/README.rst', filename='tools/monitoring.rst') +urllib.urlretrieve(tools_repo+tools_branch+'/tm-bench/README.md', filename=tools_dir+'/benchmarking.md') +urllib.urlretrieve(tools_repo+tools_branch+'/tm-monitor/README.md', filename=tools_dir+'/monitoring.md') #### abci spec ################################# abci_repo = "https://raw.githubusercontent.com/tendermint/abci/" abci_branch = "develop" -urllib.urlretrieve(abci_repo+abci_branch+'/specification.rst', filename='abci-spec.rst') +urllib.urlretrieve(abci_repo+abci_branch+'/specification.md', filename='abci-spec.md') diff --git a/docs/deploy-testnets.md b/docs/deploy-testnets.md new file mode 100644 index 00000000..31deeb5a --- /dev/null +++ b/docs/deploy-testnets.md @@ -0,0 +1,68 @@ +# Deploy a Testnet + +Now that we've seen how ABCI works, and even played with a few +applications on a single validator node, it's time to deploy a test +network to four validator nodes. + +## Manual Deployments + +It's relatively easy to setup a Tendermint cluster manually. The only +requirements for a particular Tendermint node are a private key for the +validator, stored as `priv_validator.json`, a node key, stored as +`node_key.json` and a list of the public keys of all validators, stored +as `genesis.json`. These files should be stored in +`~/.tendermint/config`, or wherever the `$TMHOME` variable might be set +to. + +Here are the steps to setting up a testnet manually: + +1) Provision nodes on your cloud provider of choice +2) Install Tendermint and the application of interest on all nodes +3) Generate a private key and a node key for each validator using + `tendermint init` +4) Compile a list of public keys for each validator into a + `genesis.json` file and replace the existing file with it. +5) Run + `tendermint node --proxy_app=kvstore --p2p.persistent_peers=< peer addresses >` + on each node, where `< peer addresses >` is a comma separated list + of the IP:PORT combination for each node. The default port for + Tendermint is `46656`. Thus, if the IP addresses of your nodes were + `192.168.0.1, 192.168.0.2, 192.168.0.3, 192.168.0.4`, the command + would look like: + + + tendermint node --proxy_app=kvstore --p2p.persistent_peers=96663a3dd0d7b9d17d4c8211b191af259621c693@192.168.0.1:46656, 429fcf25974313b95673f58d77eacdd434402665@192.168.0.2:46656, 0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@192.168.0.3:46656, f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@192.168.0.4:46656 + +After a few seconds, all the nodes should connect to each other and +start making blocks! For more information, see the Tendermint Networks +section of [the guide to using Tendermint](using-tendermint.html). + +But wait! Steps 3 and 4 are quite manual. Instead, use [this +script](https://github.com/tendermint/tendermint/blob/develop/docs/examples/init_testnet.sh), +which does the heavy lifting for you. And it gets better. + +Instead of the previously linked script to initialize the files required +for a testnet, we have the `tendermint testnet` command. By default, +running `tendermint testnet` will create all the required files, just +like the script. Of course, you'll still need to manually edit some +fields in the `config.toml`. Alternatively, see the available flags to +auto-populate the `config.toml` with the fields that would otherwise be +passed in via flags when running `tendermint node`. As you might +imagine, this command is useful for manual or automated deployments. + +## Automated Deployments + +The easiest and fastest way to get a testnet up in less than 5 minutes. + +### Local + +With `docker` and `docker-compose` installed, run the command: + + make localnet-start + +from the root of the tendermint repository. This will spin up a 4-node +local testnet. Review the target in the Makefile to debug any problems. + +### Cloud + +See the [next section](./terraform-and-ansible.html) for details. diff --git a/docs/deploy-testnets.rst b/docs/deploy-testnets.rst deleted file mode 100644 index c5df973a..00000000 --- a/docs/deploy-testnets.rst +++ /dev/null @@ -1,64 +0,0 @@ -Deploy a Testnet -================ - -Now that we've seen how ABCI works, and even played with a few -applications on a single validator node, it's time to deploy a test -network to four validator nodes. - -Manual Deployments ------------------- - -It's relatively easy to setup a Tendermint cluster manually. The only -requirements for a particular Tendermint node are a private key for the -validator, stored as ``priv_validator.json``, a node key, stored as -``node_key.json`` and a list of the public keys of all validators, stored as -``genesis.json``. These files should be stored in ``~/.tendermint/config``, or -wherever the ``$TMHOME`` variable might be set to. - -Here are the steps to setting up a testnet manually: - -1) Provision nodes on your cloud provider of choice -2) Install Tendermint and the application of interest on all nodes -3) Generate a private key and a node key for each validator using - ``tendermint init`` -4) Compile a list of public keys for each validator into a - ``genesis.json`` file and replace the existing file with it. -5) Run ``tendermint node --proxy_app=kvstore --p2p.persistent_peers=< peer addresses >`` on each node, - where ``< peer addresses >`` is a comma separated list of the IP:PORT - combination for each node. The default port for Tendermint is - ``46656``. Thus, if the IP addresses of your nodes were - ``192.168.0.1, 192.168.0.2, 192.168.0.3, 192.168.0.4``, the command - would look like: - -:: - - tendermint node --proxy_app=kvstore --p2p.persistent_peers=96663a3dd0d7b9d17d4c8211b191af259621c693@192.168.0.1:46656, 429fcf25974313b95673f58d77eacdd434402665@192.168.0.2:46656, 0491d373a8e0fcf1023aaf18c51d6a1d0d4f31bd@192.168.0.3:46656, f9baeaa15fedf5e1ef7448dd60f46c01f1a9e9c4@192.168.0.4:46656 - -After a few seconds, all the nodes should connect to each other and start -making blocks! For more information, see the Tendermint Networks section -of `the guide to using Tendermint `__. - -But wait! Steps 3 and 4 are quite manual. Instead, use `this script `__, which does the heavy lifting for you. And it gets better. - -Instead of the previously linked script to initialize the files required for a testnet, we have the ``tendermint testnet`` command. By default, running ``tendermint testnet`` will create all the required files, just like the script. Of course, you'll still need to manually edit some fields in the ``config.toml``. Alternatively, see the available flags to auto-populate the ``config.toml`` with the fields that would otherwise be passed in via flags when running ``tendermint node``. As you might imagine, this command is useful for manual or automated deployments. - -Automated Deployments ---------------------- - -The easiest and fastest way to get a testnet up in less than 5 minutes. - -Local -^^^^^ - -With ``docker`` and ``docker-compose`` installed, run the command: - -:: - - make localnet-start - -from the root of the tendermint repository. This will spin up a 4-node local testnet. - -Cloud -^^^^^ - -See the `next section <./terraform-and-ansible.html>`__ for details. diff --git a/docs/determinism.rst b/docs/determinism.md similarity index 51% rename from docs/determinism.rst rename to docs/determinism.md index e3fbce3d..95958bb1 100644 --- a/docs/determinism.rst +++ b/docs/determinism.md @@ -1,8 +1,5 @@ -On Determinism -============== +# On Determinism Arguably, the most difficult part of blockchain programming is determinism - that is, ensuring that sources of indeterminism do not creep into the design of such systems. -See `this issue `__ for more information on the potential sources of indeterminism. - - +See [this issue](https://github.com/tendermint/abci/issues/56) for more information on the potential sources of indeterminism. diff --git a/docs/ecosystem.md b/docs/ecosystem.md new file mode 100644 index 00000000..9fbc56f8 --- /dev/null +++ b/docs/ecosystem.md @@ -0,0 +1,21 @@ +# Ecosystem + +The growing list of applications built using various pieces of the +Tendermint stack can be found at: + +- https://tendermint.com/ecosystem + +We thank the community for their contributions thus far and welcome the +addition of new projects. A pull request can be submitted to [this +file](https://github.com/tendermint/aib-data/blob/master/json/ecosystem.json) +to include your project. + +## Other Tools + +See [deploy testnets](./deploy-testnets.html) for information about all +the tools built by Tendermint. We have Kubernetes, Ansible, and +Terraform integrations. + +For upgrading from older to newer versions of tendermint and to migrate +your chain data, see [tm-migrator](https://github.com/hxzqlh/tm-tools) +written by @hxzqlh. diff --git a/docs/ecosystem.rst b/docs/ecosystem.rst deleted file mode 100644 index cfd3a6e5..00000000 --- a/docs/ecosystem.rst +++ /dev/null @@ -1,15 +0,0 @@ -Tendermint Ecosystem -==================== - -The growing list of applications built using various pieces of the Tendermint stack can be found at: - -* https://tendermint.com/ecosystem - -We thank the community for their contributions thus far and welcome the addition of new projects. A pull request can be submitted to `this file `__ to include your project. - -Other Tools ------------ - -See `deploy testnets <./deploy-testnets.html>`__ for information about all the tools built by Tendermint. We have Kubernetes, Ansible, and Terraform integrations. - -For upgrading from older to newer versions of tendermint and to migrate your chain data, see `tm-migrator `__ written by @hxzqlh. diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 00000000..7ec3c062 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,265 @@ +# Getting Started + +## First Tendermint App + +As a general purpose blockchain engine, Tendermint is agnostic to the +application you want to run. So, to run a complete blockchain that does +something useful, you must start two programs: one is Tendermint Core, +the other is your application, which can be written in any programming +language. Recall from [the intro to +ABCI](introduction.html#ABCI-Overview) that Tendermint Core handles all +the p2p and consensus stuff, and just forwards transactions to the +application when they need to be validated, or when they're ready to be +committed to a block. + +In this guide, we show you some examples of how to run an application +using Tendermint. + +### Install + +The first apps we will work with are written in Go. To install them, you +need to [install Go](https://golang.org/doc/install) and put +`$GOPATH/bin` in your `$PATH`; see +[here](https://github.com/tendermint/tendermint/wiki/Setting-GOPATH) for +more info. + +Then run + + go get -u github.com/tendermint/abci/cmd/abci-cli + +If there is an error, install and run the +[dep](https://github.com/golang/dep) tool to pin the dependencies: + + cd $GOPATH/src/github.com/tendermint/abci + make get_tools + make get_vendor_deps + make install + +Now you should have the `abci-cli` installed; you'll see a couple of +commands (`counter` and `kvstore`) that are example applications written +in Go. See below for an application written in JavaScript. + +Now, let's run some apps! + +## KVStore - A First Example + +The kvstore app is a [Merkle +tree](https://en.wikipedia.org/wiki/Merkle_tree) that just stores all +transactions. If the transaction contains an `=`, e.g. `key=value`, then +the `value` is stored under the `key` in the Merkle tree. Otherwise, the +full transaction bytes are stored as the key and the value. + +Let's start a kvstore application. + + abci-cli kvstore + +In another terminal, we can start Tendermint. If you have never run +Tendermint before, use: + + tendermint init + tendermint node + +If you have used Tendermint, you may want to reset the data for a new +blockchain by running `tendermint unsafe_reset_all`. Then you can run +`tendermint node` to start Tendermint, and connect to the app. For more +details, see [the guide on using Tendermint](./using-tendermint.html). + +You should see Tendermint making blocks! We can get the status of our +Tendermint node as follows: + + curl -s localhost:46657/status + +The `-s` just silences `curl`. For nicer output, pipe the result into a +tool like [jq](https://stedolan.github.io/jq/) or `json_pp`. + +Now let's send some transactions to the kvstore. + + curl -s 'localhost:46657/broadcast_tx_commit?tx="abcd"' + +Note the single quote (`'`) around the url, which ensures that the +double quotes (`"`) are not escaped by bash. This command sent a +transaction with bytes `abcd`, so `abcd` will be stored as both the key +and the value in the Merkle tree. The response should look something +like: + + { + "jsonrpc": "2.0", + "id": "", + "result": { + "check_tx": { + "fee": {} + }, + "deliver_tx": { + "tags": [ + { + "key": "YXBwLmNyZWF0b3I=", + "value": "amFl" + }, + { + "key": "YXBwLmtleQ==", + "value": "YWJjZA==" + } + ], + "fee": {} + }, + "hash": "9DF66553F98DE3C26E3C3317A3E4CED54F714E39", + "height": 14 + } + } + +We can confirm that our transaction worked and the value got stored by +querying the app: + + curl -s 'localhost:46657/abci_query?data="abcd"' + +The result should look like: + + { + "jsonrpc": "2.0", + "id": "", + "result": { + "response": { + "log": "exists", + "index": "-1", + "key": "YWJjZA==", + "value": "YWJjZA==" + } + } + } + +Note the `value` in the result (`YWJjZA==`); this is the base64-encoding +of the ASCII of `abcd`. You can verify this in a python 2 shell by +running `"61626364".decode('base64')` or in python 3 shell by running +`import codecs; codecs.decode("61626364", 'base64').decode('ascii')`. +Stay tuned for a future release that [makes this output more +human-readable](https://github.com/tendermint/abci/issues/32). + +Now let's try setting a different key and value: + + curl -s 'localhost:46657/broadcast_tx_commit?tx="name=satoshi"' + +Now if we query for `name`, we should get `satoshi`, or `c2F0b3NoaQ==` +in base64: + + curl -s 'localhost:46657/abci_query?data="name"' + +Try some other transactions and queries to make sure everything is +working! + +## Counter - Another Example + +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, or committed the state. + +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. + +In a live blockchain, transactions collect in memory before they are +committed into blocks. To avoid wasting resources on invalid +transactions, ABCI provides the `CheckTx` 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, with `serial=on`, `CheckTx` only +allows transactions whose integer is greater than the last committed +one. + +Let's kill the previous instance of `tendermint` and the `kvstore` +application, and start the counter app. We can enable `serial=on` with a +flag: + + abci-cli counter --serial + +In another window, reset then start Tendermint: + + tendermint unsafe_reset_all + tendermint node + +Once again, you can see the blocks streaming by. Let's send some +transactions. Since we have set `serial=on`, the first transaction must +be the number `0`: + + curl localhost:46657/broadcast_tx_commit?tx=0x00 + +Note the empty (hence successful) response. The next transaction must be +the number `1`. If instead, we try to send a `5`, we get an error: + + > curl localhost:46657/broadcast_tx_commit?tx=0x05 + { + "jsonrpc": "2.0", + "id": "", + "result": { + "check_tx": { + "fee": {} + }, + "deliver_tx": { + "code": 2, + "log": "Invalid nonce. Expected 1, got 5", + "fee": {} + }, + "hash": "33B93DFF98749B0D6996A70F64071347060DC19C", + "height": 34 + } + } + +But if we send a `1`, it works again: + + > curl localhost:46657/broadcast_tx_commit?tx=0x01 + { + "jsonrpc": "2.0", + "id": "", + "result": { + "check_tx": { + "fee": {} + }, + "deliver_tx": { + "fee": {} + }, + "hash": "F17854A977F6FA7EEA1BD758E296710B86F72F3D", + "height": 60 + } + } + +For more details on the `broadcast_tx` API, see [the guide on using +Tendermint](./using-tendermint.html). + +## CounterJS - Example in Another Language + +We also want to run applications in another language - in this case, +we'll run a Javascript version of the `counter`. To run it, you'll need +to [install node](https://nodejs.org/en/download/). + +You'll also need to fetch the relevant repository, from +[here](https://github.com/tendermint/js-abci) then install it. As go +devs, we keep all our code under the `$GOPATH`, so run: + + go get github.com/tendermint/js-abci &> /dev/null + cd $GOPATH/src/github.com/tendermint/js-abci/example + npm install + cd .. + +Kill the previous `counter` and `tendermint` processes. Now run the app: + + node example/app.js + +In another window, reset and start `tendermint`: + + tendermint unsafe_reset_all + tendermint node + +Once again, you should see blocks streaming by - but now, our +application is written in javascript! Try sending some transactions, and +like before - the results should be the same: + + curl localhost:46657/broadcast_tx_commit?tx=0x00 # ok + curl localhost:46657/broadcast_tx_commit?tx=0x05 # invalid nonce + curl localhost:46657/broadcast_tx_commit?tx=0x01 # ok + +Neat, eh? diff --git a/docs/getting-started.rst b/docs/getting-started.rst deleted file mode 100644 index 9c722f0f..00000000 --- a/docs/getting-started.rst +++ /dev/null @@ -1,325 +0,0 @@ -First Tendermint App -==================== - -As a general purpose blockchain engine, Tendermint is agnostic to the -application you want to run. So, to run a complete blockchain that does -something useful, you must start two programs: one is Tendermint Core, -the other is your application, which can be written in any programming -language. Recall from `the intro to ABCI `__ that -Tendermint Core handles all the p2p and consensus stuff, and just -forwards transactions to the application when they need to be validated, -or when they're ready to be committed to a block. - -In this guide, we show you some examples of how to run an application -using Tendermint. - -Install -------- - -The first apps we will work with are written in Go. To install them, you -need to `install Go `__ and put -``$GOPATH/bin`` in your -``$PATH``; see `here `__ for more info. - -Then run - -:: - - go get -u github.com/tendermint/abci/cmd/abci-cli - -If there is an error, install and run the `dep `__ tool to pin the -dependencies: - -:: - - cd $GOPATH/src/github.com/tendermint/abci - make get_tools - make get_vendor_deps - make install - -Now you should have the ``abci-cli`` installed; you'll see -a couple of commands (``counter`` and ``kvstore``) that are -example applications written in Go. See below for an application -written in JavaScript. - -Now, let's run some apps! - -KVStore - A First Example -------------------------- - -The kvstore app is a `Merkle -tree `__ that just stores all -transactions. If the transaction contains an ``=``, e.g. ``key=value``, -then the ``value`` is stored under the ``key`` in the Merkle tree. -Otherwise, the full transaction bytes are stored as the key and the -value. - -Let's start a kvstore application. - -:: - - abci-cli kvstore - -In another terminal, we can start Tendermint. If you have never run -Tendermint before, use: - -:: - - tendermint init - tendermint node - -If you have used Tendermint, you may want to reset the data for a new -blockchain by running ``tendermint unsafe_reset_all``. Then you can run -``tendermint node`` to start Tendermint, and connect to the app. For -more details, see `the guide on using -Tendermint <./using-tendermint.html>`__. - -You should see Tendermint making blocks! We can get the status of our -Tendermint node as follows: - -:: - - curl -s localhost:46657/status - -The ``-s`` just silences ``curl``. For nicer output, pipe the result into a -tool like `jq `__ or ``json_pp``. - -Now let's send some transactions to the kvstore. - -:: - - curl -s 'localhost:46657/broadcast_tx_commit?tx="abcd"' - -Note the single quote (``'``) around the url, which ensures that the -double quotes (``"``) are not escaped by bash. This command sent a -transaction with bytes ``abcd``, so ``abcd`` will be stored as both the -key and the value in the Merkle tree. The response should look something -like: - -:: - - { - "jsonrpc": "2.0", - "id": "", - "result": { - "check_tx": { - "fee": {} - }, - "deliver_tx": { - "tags": [ - { - "key": "YXBwLmNyZWF0b3I=", - "value": "amFl" - }, - { - "key": "YXBwLmtleQ==", - "value": "YWJjZA==" - } - ], - "fee": {} - }, - "hash": "9DF66553F98DE3C26E3C3317A3E4CED54F714E39", - "height": 14 - } - } - -We can confirm that our transaction worked and the value got stored by -querying the app: - -:: - - curl -s 'localhost:46657/abci_query?data="abcd"' - -The result should look like: - -:: - - { - "jsonrpc": "2.0", - "id": "", - "result": { - "response": { - "log": "exists", - "index": "-1", - "key": "YWJjZA==", - "value": "YWJjZA==" - } - } - } - -Note the ``value`` in the result (``YWJjZA==``); this is the -base64-encoding of the ASCII of ``abcd``. You can verify this in -a python 2 shell by running ``"61626364".decode('base64')`` or in python 3 shell by running ``import codecs; codecs.decode("61626364", 'base64').decode('ascii')``. Stay -tuned for a future release that `makes this output more human-readable `__. - -Now let's try setting a different key and value: - -:: - - curl -s 'localhost:46657/broadcast_tx_commit?tx="name=satoshi"' - -Now if we query for ``name``, we should get ``satoshi``, or -``c2F0b3NoaQ==`` in base64: - -:: - - curl -s 'localhost:46657/abci_query?data="name"' - -Try some other transactions and queries to make sure everything is -working! - -Counter - Another Example -------------------------- - -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, or committed the state. - -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. - -In a live blockchain, transactions collect in memory before they are -committed into blocks. To avoid wasting resources on invalid -transactions, ABCI provides the ``CheckTx`` 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, with ``serial=on``, ``CheckTx`` -only allows transactions whose integer is greater than the last -committed one. - -Let's kill the previous instance of ``tendermint`` and the ``kvstore`` -application, and start the counter app. We can enable ``serial=on`` with -a flag: - -:: - - abci-cli counter --serial - -In another window, reset then start Tendermint: - -:: - - tendermint unsafe_reset_all - tendermint node - -Once again, you can see the blocks streaming by. Let's send some -transactions. Since we have set ``serial=on``, the first transaction -must be the number ``0``: - -:: - - curl localhost:46657/broadcast_tx_commit?tx=0x00 - -Note the empty (hence successful) response. The next transaction must be -the number ``1``. If instead, we try to send a ``5``, we get an error: - -:: - - > curl localhost:46657/broadcast_tx_commit?tx=0x05 - { - "jsonrpc": "2.0", - "id": "", - "result": { - "check_tx": { - "fee": {} - }, - "deliver_tx": { - "code": 2, - "log": "Invalid nonce. Expected 1, got 5", - "fee": {} - }, - "hash": "33B93DFF98749B0D6996A70F64071347060DC19C", - "height": 34 - } - } - -But if we send a ``1``, it works again: - -:: - - > curl localhost:46657/broadcast_tx_commit?tx=0x01 - { - "jsonrpc": "2.0", - "id": "", - "result": { - "check_tx": { - "fee": {} - }, - "deliver_tx": { - "fee": {} - }, - "hash": "F17854A977F6FA7EEA1BD758E296710B86F72F3D", - "height": 60 - } - } - -For more details on the ``broadcast_tx`` API, see `the guide on using -Tendermint <./using-tendermint.html>`__. - -CounterJS - Example in Another Language ---------------------------------------- - -We also want to run applications in another language - in this case, -we'll run a Javascript version of the ``counter``. To run it, you'll -need to `install node `__. - -You'll also need to fetch the relevant repository, from `here `__ then install it. As go devs, we -keep all our code under the ``$GOPATH``, so run: - -:: - - go get github.com/tendermint/js-abci &> /dev/null - cd $GOPATH/src/github.com/tendermint/js-abci/example - npm install - cd .. - -Kill the previous ``counter`` and ``tendermint`` processes. Now run the -app: - -:: - - node example/app.js - -In another window, reset and start ``tendermint``: - -:: - - tendermint unsafe_reset_all - tendermint node - -Once again, you should see blocks streaming by - but now, our -application is written in javascript! Try sending some transactions, and -like before - the results should be the same: - -:: - - curl localhost:46657/broadcast_tx_commit?tx=0x00 # ok - curl localhost:46657/broadcast_tx_commit?tx=0x05 # invalid nonce - curl localhost:46657/broadcast_tx_commit?tx=0x01 # ok - -Neat, eh? - -Basecoin - A More Interesting Example -------------------------------------- - -We saved the best for last; the `Cosmos SDK `__ is a general purpose framework for building cryptocurrencies. Unlike the ``kvstore`` and ``counter``, which are strictly for example purposes. The reference implementation of Cosmos SDK is ``basecoin``, which demonstrates how to use the building blocks of the Cosmos SDK. - -The default ``basecoin`` application is a multi-asset cryptocurrency -that supports inter-blockchain communication (IBC). For more details on how -basecoin works and how to use it, see our `basecoin -guide `__ - -In this tutorial you learned how to run applications using Tendermint -on a single node. You saw how applications could be written in different -languages, and how to send transactions and query for the latest state. -But the true power of Tendermint comes from its ability to securely and -efficiently run an application across a distributed network of nodes, -while keeping them all in sync using its state-of-the-art consensus -protocol. Next, we show you how to deploy Tendermint testnets. diff --git a/docs/how-to-read-logs.rst b/docs/how-to-read-logs.md similarity index 75% rename from docs/how-to-read-logs.rst rename to docs/how-to-read-logs.md index e0c3f1b4..bace5c7e 100644 --- a/docs/how-to-read-logs.rst +++ b/docs/how-to-read-logs.md @@ -1,13 +1,9 @@ -How to read logs -================ +# How to read logs -Walk through example --------------------- +## Walkabout example We first create three connections (mempool, consensus and query) to the -application (running ``kvstore`` locally in this case). - -:: +application (running `kvstore` locally in this case). I[10-04|13:54:27.364] Starting multiAppConn module=proxy impl=multiAppConn I[10-04|13:54:27.366] Starting localClient module=abci-client connection=query impl=localClient @@ -16,16 +12,12 @@ application (running ``kvstore`` locally in this case). Then Tendermint Core and the application perform a handshake. -:: - I[10-04|13:54:27.367] ABCI Handshake module=consensus appHeight=90 appHash=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD I[10-04|13:54:27.368] ABCI Replay Blocks module=consensus appHeight=90 storeHeight=90 stateHeight=90 I[10-04|13:54:27.368] Completed ABCI Handshake - Tendermint and App are synced module=consensus appHeight=90 appHash=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD -After that, we start a few more things like the event switch, reactors, and -perform UPNP discover in order to detect the IP address. - -:: +After that, we start a few more things like the event switch, reactors, +and perform UPNP discover in order to detect the IP address. I[10-04|13:54:27.374] Starting EventSwitch module=types impl=EventSwitch I[10-04|13:54:27.375] This node is a validator module=consensus @@ -48,28 +40,21 @@ validator". It also could be just an observer (regular node). Next we replay all the messages from the WAL. -:: - I[10-04|13:54:30.390] Catchup by replaying consensus messages module=consensus height=91 I[10-04|13:54:30.390] Replay: New Step module=consensus height=91 round=0 step=RoundStepNewHeight I[10-04|13:54:30.390] Replay: Done module=consensus "Started node" message signals that everything is ready for work. -:: - I[10-04|13:54:30.391] Starting RPC HTTP server on tcp socket 0.0.0.0:46657 module=rpc-server I[10-04|13:54:30.392] Started node module=main nodeInfo="NodeInfo{id: DF22D7C92C91082324A1312F092AA1DA197FA598DBBFB6526E, moniker: anonymous, network: test-chain-3MNw2N [remote , listen 10.0.2.15:46656], version: 0.11.0-10f361fc ([wire_version=0.6.2 p2p_version=0.5.0 consensus_version=v1/0.2.2 rpc_version=0.7.0/3 tx_index=on rpc_addr=tcp://0.0.0.0:46657])}" -Next follows a standard block creation cycle, where we enter a new round, -propose a block, receive more than 2/3 of prevotes, then precommits and finally -have a chance to commit a block. For details, please refer to `Consensus -Overview -`__ -or `Byzantine Consensus Algorithm -`__. - -:: +Next follows a standard block creation cycle, where we enter a new +round, propose a block, receive more than 2/3 of prevotes, then +precommits and finally have a chance to commit a block. For details, +please refer to [Consensus +Overview](introduction.html#consensus-overview) or [Byzantine Consensus +Algorithm](specification.html). I[10-04|13:54:30.393] enterNewRound(91/0). Current: 91/0/RoundStepNewHeight module=consensus I[10-04|13:54:30.393] enterPropose(91/0). Current: 91/0/RoundStepNewRound module=consensus @@ -110,56 +95,36 @@ or `Byzantine Consensus Algorithm I[10-04|13:54:30.410] Committed state module=state height=91 txs=0 hash=E0FBAFBF6FCED8B9786DDFEB1A0D4FA2501BADAD I[10-04|13:54:30.410] Recheck txs module=mempool numtxs=0 height=91 -List of modules ---------------- +## List of modules -Here is the list of modules you may encounter in Tendermint's log and a little -overview what they do. +Here is the list of modules you may encounter in Tendermint's log and a +little overview what they do. -- ``abci-client`` As mentioned in `Application Development Guide - `__, - Tendermint acts as an ABCI client with respect to the application and - maintains 3 connections: mempool, consensus and query. The code used by - Tendermint Core can be found `here - `__. - -- ``blockchain`` - Provides storage, pool (a group of peers), and reactor for both storing and - exchanging blocks between peers. - -- ``consensus`` - The heart of Tendermint core, which is the implementation of the consensus - algorithm. Includes two "submodules": ``wal`` (write-ahead logging) for - ensuring data integrity and ``replay`` to replay blocks and messages on - recovery from a crash. - -- ``events`` - Simple event notification system. The list of events can be found - `here - `__. - You can subscribe to them by calling ``subscribe`` RPC method. - Refer to `RPC docs - `__ - for additional information. - -- ``mempool`` - Mempool module handles all incoming transactions, whenever they are - coming from peers or the application. - -- ``p2p`` - Provides an abstraction around peer-to-peer communication. For more details, - please check out the `README - `__. - -- ``rpc`` - `Tendermint's RPC `__. - -- ``rpc-server`` - RPC server. For implementation details, please read the `README `__. - -- ``state`` - Represents the latest state and execution submodule, which executes - blocks against the application. - -- ``types`` - A collection of the publicly exposed types and methods to work with them. +- `abci-client` As mentioned in [Application Development Guide](app-development.md#abci-design), Tendermint acts as an ABCI + client with respect to the application and maintains 3 connections: + mempool, consensus and query. The code used by Tendermint Core can + be found [here](https://github.com/tendermint/abci/tree/master/client). +- `blockchain` Provides storage, pool (a group of peers), and reactor + for both storing and exchanging blocks between peers. +- `consensus` The heart of Tendermint core, which is the + implementation of the consensus algorithm. Includes two + "submodules": `wal` (write-ahead logging) for ensuring data + integrity and `replay` to replay blocks and messages on recovery + from a crash. +- `events` Simple event notification system. The list of events can be + found + [here](https://github.com/tendermint/tendermint/blob/master/types/events.go). + You can subscribe to them by calling `subscribe` RPC method. Refer + to [RPC docs](specification/rpc.html) for additional information. +- `mempool` Mempool module handles all incoming transactions, whenever + they are coming from peers or the application. +- `p2p` Provides an abstraction around peer-to-peer communication. For + more details, please check out the + [README](https://github.com/tendermint/tendermint/blob/master/p2p/README.md). +- `rpc` [Tendermint's RPC](specification/rpc.html). +- `rpc-server` RPC server. For implementation details, please read the + [README](https://github.com/tendermint/tendermint/blob/master/rpc/lib/README.md). +- `state` Represents the latest state and execution submodule, which + executes blocks against the application. +- `types` A collection of the publicly exposed types and methods to + work with them. diff --git a/docs/index.rst b/docs/index.rst index f9d71429..b40db3bf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,24 +12,18 @@ Welcome to Tendermint! :width: 200px :align: center -Tendermint 101 --------------- +Introduction +------------ .. toctree:: - :maxdepth: 2 + :maxdepth: 1 - introduction.rst - install.rst - getting-started.rst - using-tendermint.rst - -Tendermint Ecosystem --------------------- - -.. toctree:: - :maxdepth: 2 - - ecosystem.rst + introduction.md + install.md + getting-started.md + using-tendermint.md + deploy-testnets.md + ecosystem.md Tendermint Tools ---------------- @@ -37,38 +31,38 @@ Tendermint Tools .. the tools/ files are pulled in from the tools repo .. see the bottom of conf.py .. toctree:: - :maxdepth: 2 + :maxdepth: 1 - deploy-testnets.rst - terraform-and-ansible.rst - tools/docker.rst - tools/benchmarking.rst - tools/monitoring.rst + tools/docker.md + terraform-and-ansible.md + tools/benchmarking.md + tools/monitoring.md -Tendermint 102 --------------- +ABCI, Apps, Logging, Etc +------------------------ .. toctree:: - :maxdepth: 2 + :maxdepth: 1 - abci-cli.rst - abci-spec.rst - app-architecture.rst - app-development.rst - subscribing-to-events-via-websocket.rst - indexing-transactions.rst - how-to-read-logs.rst - running-in-production.rst + abci-cli.md + abci-spec.md + app-architecture.md + app-development.md + subscribing-to-events-via-websocket.md + indexing-transactions.md + how-to-read-logs.md + running-in-production.md -Tendermint 201 --------------- +Research & Specification +------------------------ .. toctree:: - :maxdepth: 2 + :maxdepth: 1 - specification.rst - determinism.rst - transactional-semantics.rst + determinism.md + transactional-semantics.md + +.. specification.md ## keep this file for legacy purpose. needs to be fixed though * For a deeper dive, see `this thesis `__. * There is also the `original whitepaper `__, though it is now quite outdated. diff --git a/docs/indexing-transactions.rst b/docs/indexing-transactions.md similarity index 63% rename from docs/indexing-transactions.rst rename to docs/indexing-transactions.md index 2487a771..1563fec9 100644 --- a/docs/indexing-transactions.rst +++ b/docs/indexing-transactions.md @@ -1,12 +1,9 @@ -Indexing Transactions -===================== +# Indexing Transactions -Tendermint allows you to index transactions and later query or subscribe to -their results. +Tendermint allows you to index transactions and later query or subscribe +to their results. -Let's take a look at the ``[tx_index]`` config section: - -:: +Let's take a look at the `[tx_index]` config section: ##### transactions indexer configuration options ##### [tx_index] @@ -30,21 +27,18 @@ Let's take a look at the ``[tx_index]`` config section: # IndexAllTags (i.e. when given both, IndexTags will be indexed). index_all_tags = false -By default, Tendermint will index all transactions by their respective hashes -using an embedded simple indexer. Note, we are planning to add more options in -the future (e.g., Postgresql indexer). +By default, Tendermint will index all transactions by their respective +hashes using an embedded simple indexer. Note, we are planning to add +more options in the future (e.g., Postgresql indexer). -Adding tags ------------ +## Adding tags -In your application's ``DeliverTx`` method, add the ``Tags`` field with the +In your application's `DeliverTx` method, add the `Tags` field with the pairs of UTF-8 encoded strings (e.g. "account.owner": "Bob", "balance": "100.0", "date": "2018-01-02"). Example: -:: - func (app *KVStoreApplication) DeliverTx(tx []byte) types.Result { ... tags := []cmn.KVPair{ @@ -55,37 +49,32 @@ Example: return types.ResponseDeliverTx{Code: code.CodeTypeOK, Tags: tags} } -If you want Tendermint to only index transactions by "account.name" tag, in the -config set ``tx_index.index_tags="account.name"``. If you to index all tags, -set ``index_all_tags=true`` +If you want Tendermint to only index transactions by "account.name" tag, +in the config set `tx_index.index_tags="account.name"`. If you to index +all tags, set `index_all_tags=true` Note, there are a few predefined tags: -- ``tm.event`` (event type) -- ``tx.hash`` (transaction's hash) -- ``tx.height`` (height of the block transaction was committed in) +- `tm.event` (event type) +- `tx.hash` (transaction's hash) +- `tx.height` (height of the block transaction was committed in) Tendermint will throw a warning if you try to use any of the above keys. -Quering transactions --------------------- +## Querying transactions -You can query the transaction results by calling ``/tx_search`` RPC endpoint: - -:: +You can query the transaction results by calling `/tx_search` RPC +endpoint: curl "localhost:46657/tx_search?query=\"account.name='igor'\"&prove=true" -Check out `API docs `__ for more -information on query syntax and other options. +Check out [API docs](https://tendermint.github.io/slate/?shell#txsearch) +for more information on query syntax and other options. -Subscribing to transactions ---------------------------- +## Subscribing to transactions -Clients can subscribe to transactions with the given tags via Websocket by -providing a query to ``/subscribe`` RPC endpoint. - -:: +Clients can subscribe to transactions with the given tags via Websocket +by providing a query to `/subscribe` RPC endpoint. { "jsonrpc": "2.0", @@ -96,5 +85,5 @@ providing a query to ``/subscribe`` RPC endpoint. } } -Check out `API docs `__ for more -information on query syntax and other options. +Check out [API docs](https://tendermint.github.io/slate/#subscribe) for +more information on query syntax and other options. diff --git a/docs/introduction.md b/docs/introduction.md new file mode 100644 index 00000000..419071dc --- /dev/null +++ b/docs/introduction.md @@ -0,0 +1,331 @@ +# What is Tendermint? + +Tendermint is software for securely and consistently replicating an +application on many machines. By securely, we mean that Tendermint works +even if up to 1/3 of machines fail in arbitrary ways. By consistently, +we mean that every non-faulty machine sees the same transaction log and +computes the same state. Secure and consistent replication is a +fundamental problem in distributed systems; it plays a critical role in +the fault tolerance of a broad range of applications, from currencies, +to elections, to infrastructure orchestration, and beyond. + +The ability to tolerate machines failing in arbitrary ways, including +becoming malicious, is known as Byzantine fault tolerance (BFT). The +theory of BFT is decades old, but software implementations have only +became popular recently, due largely to the success of "blockchain +technology" like Bitcoin and Ethereum. Blockchain technology is just a +reformalization of BFT in a more modern setting, with emphasis on +peer-to-peer networking and cryptographic authentication. The name +derives from the way transactions are batched in blocks, where each +block contains a cryptographic hash of the previous one, forming a +chain. In practice, the blockchain data structure actually optimizes BFT +design. + +Tendermint consists of two chief technical components: a blockchain +consensus engine and a generic application interface. The consensus +engine, called Tendermint Core, ensures that the same transactions are +recorded on every machine in the same order. The application interface, +called the Application BlockChain Interface (ABCI), enables the +transactions to be processed in any programming language. Unlike other +blockchain and consensus solutions, which come pre-packaged with built +in state machines (like a fancy key-value store, or a quirky scripting +language), developers can use Tendermint for BFT state machine +replication of applications written in whatever programming language and +development environment is right for them. + +Tendermint is designed to be easy-to-use, simple-to-understand, highly +performant, and useful for a wide variety of distributed applications. + +## Tendermint vs. X + +Tendermint is broadly similar to two classes of software. The first +class consists of distributed key-value stores, like Zookeeper, etcd, +and consul, which use non-BFT consensus. The second class is known as +"blockchain technology", and consists of both cryptocurrencies like +Bitcoin and Ethereum, and alternative distributed ledger designs like +Hyperledger's Burrow. + +### Zookeeper, etcd, consul + +Zookeeper, etcd, and consul are all implementations of a key-value store +atop a classical, non-BFT consensus algorithm. Zookeeper uses a version +of Paxos called Zookeeper Atomic Broadcast, while etcd and consul use +the Raft consensus algorithm, which is much younger and simpler. A +typical cluster contains 3-5 machines, and can tolerate crash failures +in up to 1/2 of the machines, but even a single Byzantine fault can +destroy the system. + +Each offering provides a slightly different implementation of a +featureful key-value store, but all are generally focused around +providing basic services to distributed systems, such as dynamic +configuration, service discovery, locking, leader-election, and so on. + +Tendermint is in essence similar software, but with two key differences: +- It is Byzantine Fault Tolerant, meaning it can only tolerate up to a +1/3 of failures, but those failures can include arbitrary behaviour - +including hacking and malicious attacks. - It does not specify a +particular application, like a fancy key-value store. Instead, it +focuses on arbitrary state machine replication, so developers can build +the application logic that's right for them, from key-value store to +cryptocurrency to e-voting platform and beyond. + +The layout of this Tendermint website content is also ripped directly +and without shame from [consul.io](https://www.consul.io/) and the other +[Hashicorp sites](https://www.hashicorp.com/#tools). + +### Bitcoin, Ethereum, etc. + +Tendermint emerged in the tradition of cryptocurrencies like Bitcoin, +Ethereum, etc. with the goal of providing a more efficient and secure +consensus algorithm than Bitcoin's Proof of Work. In the early days, +Tendermint had a simple currency built in, and to participate in +consensus, users had to "bond" units of the currency into a security +deposit which could be revoked if they misbehaved -this is what made +Tendermint a Proof-of-Stake algorithm. + +Since then, Tendermint has evolved to be a general purpose blockchain +consensus engine that can host arbitrary application states. That means +it can be used as a plug-and-play replacement for the consensus engines +of other blockchain software. So one can take the current Ethereum code +base, whether in Rust, or Go, or Haskell, and run it as a ABCI +application using Tendermint consensus. Indeed, [we did that with +Ethereum](https://github.com/tendermint/ethermint). And we plan to do +the same for Bitcoin, ZCash, and various other deterministic +applications as well. + +Another example of a cryptocurrency application built on Tendermint is +[the Cosmos network](http://cosmos.network). + +### Other Blockchain Projects + +[Fabric](https://github.com/hyperledger/fabric) takes a similar approach +to Tendermint, but is more opinionated about how the state is managed, +and requires that all application behaviour runs in potentially many +docker containers, modules it calls "chaincode". It uses an +implementation of [PBFT](http://pmg.csail.mit.edu/papers/osdi99.pdf). +from a team at IBM that is [augmented to handle potentially +non-deterministic +chaincode](https://www.zurich.ibm.com/~cca/papers/sieve.pdf) It is +possible to implement this docker-based behaviour as a ABCI app in +Tendermint, though extending Tendermint to handle non-determinism +remains for future work. + +[Burrow](https://github.com/hyperledger/burrow) is an implementation of +the Ethereum Virtual Machine and Ethereum transaction mechanics, with +additional features for a name-registry, permissions, and native +contracts, and an alternative blockchain API. It uses Tendermint as its +consensus engine, and provides a particular application state. + +## ABCI Overview + +The [Application BlockChain Interface +(ABCI)](https://github.com/tendermint/abci) allows for Byzantine Fault +Tolerant replication of applications written in any programming +language. + +### Motivation + +Thus far, all blockchains "stacks" (such as +[Bitcoin](https://github.com/bitcoin/bitcoin)) have had a monolithic +design. That is, each blockchain stack is a single program that handles +all the concerns of a decentralized ledger; this includes P2P +connectivity, the "mempool" broadcasting of transactions, consensus on +the most recent block, account balances, Turing-complete contracts, +user-level permissions, etc. + +Using a monolithic architecture is typically bad practice in computer +science. It makes it difficult to reuse components of the code, and +attempts to do so result in complex maintenance procedures for forks of +the codebase. This is especially true when the codebase is not modular +in design and suffers from "spaghetti code". + +Another problem with monolithic design is that it limits you to the +language of the blockchain stack (or vice versa). In the case of +Ethereum which supports a Turing-complete bytecode virtual-machine, it +limits you to languages that compile down to that bytecode; today, those +are Serpent and Solidity. + +In contrast, our approach is to decouple the consensus engine and P2P +layers from the details of the application state of the particular +blockchain application. We do this by abstracting away the details of +the application to an interface, which is implemented as a socket +protocol. + +Thus we have an interface, the Application BlockChain Interface (ABCI), +and its primary implementation, the Tendermint Socket Protocol (TSP, or +Teaspoon). + +### Intro to ABCI + +[Tendermint Core](https://github.com/tendermint/tendermint) (the +"consensus engine") communicates with the application via a socket +protocol that satisfies the [ABCI](https://github.com/tendermint/abci). + +To draw an analogy, lets talk about a well-known cryptocurrency, +Bitcoin. Bitcoin is a cryptocurrency blockchain where each node +maintains a fully audited Unspent Transaction Output (UTXO) database. If +one wanted to create a Bitcoin-like system on top of ABCI, Tendermint +Core would be responsible for + +- Sharing blocks and transactions between nodes +- Establishing a canonical/immutable order of transactions + (the blockchain) + +The application will be responsible for + +- Maintaining the UTXO database +- Validating cryptographic signatures of transactions +- Preventing transactions from spending non-existent transactions +- Allowing clients to query the UTXO database. + +Tendermint is able to decompose the blockchain design by offering a very +simple API (ie. the ABCI) between the application process and consensus +process. + +The ABCI consists of 3 primary message types that get delivered from the +core to the application. The application replies with corresponding +response messages. + +The messages are specified here: [ABCI Message +Types](https://github.com/tendermint/abci#message-types). + +The **DeliverTx** message is the work horse of the application. Each +transaction in the blockchain is delivered with this message. The +application needs to validate each transaction received with the +**DeliverTx** message against the current state, application protocol, +and the cryptographic credentials of the transaction. A validated +transaction then needs to update the application state — by binding a +value into a key values store, or by updating the UTXO database, for +instance. + +The **CheckTx** message is similar to **DeliverTx**, but it's only for +validating transactions. Tendermint Core's mempool first checks the +validity of a transaction with **CheckTx**, and only relays valid +transactions to its peers. For instance, an application may check an +incrementing sequence number in the transaction and return an error upon +**CheckTx** if the sequence number is old. Alternatively, they might use +a capabilities based system that requires capabilities to be renewed +with every transaction. + +The **Commit** message is used to compute a cryptographic commitment to +the current application state, to be placed into the next block header. +This has some handy properties. Inconsistencies in updating that state +will now appear as blockchain forks which catches a whole class of +programming errors. This also simplifies the development of secure +lightweight clients, as Merkle-hash proofs can be verified by checking +against the block hash, and that the block hash is signed by a quorum. + +There can be multiple ABCI socket connections to an application. +Tendermint Core creates three ABCI connections to the application; one +for the validation of transactions when broadcasting in the mempool, one +for the consensus engine to run block proposals, and one more for +querying the application state. + +It's probably evident that applications designers need to very carefully +design their message handlers to create a blockchain that does anything +useful but this architecture provides a place to start. The diagram +below illustrates the flow of messages via ABCI. + +![](assets/abci.png) + +## A Note on Determinism + +The logic for blockchain transaction processing must be deterministic. +If the application logic weren't deterministic, consensus would not be +reached among the Tendermint Core replica nodes. + +Solidity on Ethereum is a great language of choice for blockchain +applications because, among other reasons, it is a completely +deterministic programming language. However, it's also possible to +create deterministic applications using existing popular languages like +Java, C++, Python, or Go. Game programmers and blockchain developers are +already familiar with creating deterministic programs by avoiding +sources of non-determinism such as: + +- random number generators (without deterministic seeding) +- race conditions on threads (or avoiding threads altogether) +- the system clock +- uninitialized memory (in unsafe programming languages like C + or C++) +- [floating point + arithmetic](http://gafferongames.com/networking-for-game-programmers/floating-point-determinism/) +- language features that are random (e.g. map iteration in Go) + +While programmers can avoid non-determinism by being careful, it is also +possible to create a special linter or static analyzer for each language +to check for determinism. In the future we may work with partners to +create such tools. + +## Consensus Overview + +Tendermint is an easy-to-understand, mostly asynchronous, BFT consensus +protocol. The protocol follows a simple state machine that looks like +this: + +![](assets/consensus_logic.png) + +Participants in the protocol are called **validators**; they take turns +proposing blocks of transactions and voting on them. Blocks are +committed in a chain, with one block at each **height**. A block may +fail to be committed, in which case the protocol moves to the next +**round**, and a new validator gets to propose a block for that height. +Two stages of voting are required to successfully commit a block; we +call them **pre-vote** and **pre-commit**. A block is committed when +more than 2/3 of validators pre-commit for the same block in the same +round. + +There is a picture of a couple doing the polka because validators are +doing something like a polka dance. When more than two-thirds of the +validators pre-vote for the same block, we call that a **polka**. Every +pre-commit must be justified by a polka in the same round. + +Validators may fail to commit a block for a number of reasons; the +current proposer may be offline, or the network may be slow. Tendermint +allows them to establish that a validator should be skipped. Validators +wait a small amount of time to receive a complete proposal block from +the proposer before voting to move to the next round. This reliance on a +timeout is what makes Tendermint a weakly synchronous protocol, rather +than an asynchronous one. However, the rest of the protocol is +asynchronous, and validators only make progress after hearing from more +than two-thirds of the validator set. A simplifying element of +Tendermint is that it uses the same mechanism to commit a block as it +does to skip to the next round. + +Assuming less than one-third of the validators are Byzantine, Tendermint +guarantees that safety will never be violated - that is, validators will +never commit conflicting blocks at the same height. To do this it +introduces a few **locking** rules which modulate which paths can be +followed in the flow diagram. Once a validator precommits a block, it is +locked on that block. Then, + +1) it must prevote for the block it is locked on +2) it can only unlock, and precommit for a new block, if there is a + polka for that block in a later round + +## Stake + +In many systems, not all validators will have the same "weight" in the +consensus protocol. Thus, we are not so much interested in one-third or +two-thirds of the validators, but in those proportions of the total +voting power, which may not be uniformly distributed across individual +validators. + +Since Tendermint can replicate arbitrary applications, it is possible to +define a currency, and denominate the voting power in that currency. +When voting power is denominated in a native currency, the system is +often referred to as Proof-of-Stake. Validators can be forced, by logic +in the application, to "bond" their currency holdings in a security +deposit that can be destroyed if they're found to misbehave in the +consensus protocol. This adds an economic element to the security of the +protocol, allowing one to quantify the cost of violating the assumption +that less than one-third of voting power is Byzantine. + +The [Cosmos Network](http://cosmos.network) is designed to use this +Proof-of-Stake mechanism across an array of cryptocurrencies implemented +as ABCI applications. + +The following diagram is Tendermint in a (technical) nutshell. [See here +for high resolution +version](https://github.com/mobfoundry/hackatom/blob/master/tminfo.pdf). + +![](assets/tm-transaction-flow.png) diff --git a/docs/introduction.rst b/docs/introduction.rst deleted file mode 100644 index ea0633ed..00000000 --- a/docs/introduction.rst +++ /dev/null @@ -1,231 +0,0 @@ -Introduction -============ - -Welcome to the Tendermint guide! This is the best place to start if you are new -to Tendermint. - -What is Tendermint? -------------------- - -Tendermint is software for securely and consistently replicating an application on many machines. -By securely, we mean that Tendermint works even if up to 1/3 of machines fail in arbitrary ways. -By consistently, we mean that every non-faulty machine sees the same transaction log and computes the same state. -Secure and consistent replication is a fundamental problem in distributed systems; -it plays a critical role in the fault tolerance of a broad range of applications, -from currencies, to elections, to infrastructure orchestration, and beyond. - -The ability to tolerate machines failing in arbitrary ways, including becoming malicious, is known as Byzantine fault tolerance (BFT). -The theory of BFT is decades old, but software implementations have only became popular recently, -due largely to the success of "blockchain technology" like Bitcoin and Ethereum. -Blockchain technology is just a reformalization of BFT in a more modern setting, -with emphasis on peer-to-peer networking and cryptographic authentication. -The name derives from the way transactions are batched in blocks, -where each block contains a cryptographic hash of the previous one, forming a chain. -In practice, the blockchain data structure actually optimizes BFT design. - -Tendermint consists of two chief technical components: a blockchain consensus engine and a generic application interface. -The consensus engine, called Tendermint Core, ensures that the same transactions are recorded on every machine in the same order. -The application interface, called the Application BlockChain Interface (ABCI), enables the transactions to be processed in any programming language. -Unlike other blockchain and consensus solutions, which come pre-packaged with built in state machines (like a fancy key-value store, -or a quirky scripting language), developers can use Tendermint for BFT state machine replication of applications written in -whatever programming language and development environment is right for them. - -Tendermint is designed to be easy-to-use, simple-to-understand, highly performant, and useful -for a wide variety of distributed applications. - -Tendermint vs. X ----------------- - -Tendermint vs. Other Software -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Tendermint is broadly similar to two classes of software. -The first class consists of distributed key-value stores, -like Zookeeper, etcd, and consul, which use non-BFT consensus. -The second class is known as "blockchain technology", -and consists of both cryptocurrencies like Bitcoin and Ethereum, -and alternative distributed ledger designs like Hyperledger's Burrow. - -Zookeeper, etcd, consul -~~~~~~~~~~~~~~~~~~~~~~~ - -Zookeeper, etcd, and consul are all implementations of a key-value store atop a classical, -non-BFT consensus algorithm. Zookeeper uses a version of Paxos called Zookeeper Atomic Broadcast, -while etcd and consul use the Raft consensus algorithm, which is much younger and simpler. -A typical cluster contains 3-5 machines, and can tolerate crash failures in up to 1/2 of the machines, -but even a single Byzantine fault can destroy the system. - -Each offering provides a slightly different implementation of a featureful key-value store, -but all are generally focused around providing basic services to distributed systems, -such as dynamic configuration, service discovery, locking, leader-election, and so on. - -Tendermint is in essence similar software, but with two key differences: -- It is Byzantine Fault Tolerant, meaning it can only tolerate up to a 1/3 of failures, -but those failures can include arbitrary behaviour - including hacking and malicious attacks. -- It does not specify a particular application, like a fancy key-value store. Instead, -it focuses on arbitrary state machine replication, so developers can build the application logic -that's right for them, from key-value store to cryptocurrency to e-voting platform and beyond. - -The layout of this Tendermint website content is also ripped directly and without shame from -`consul.io `__ and the other `Hashicorp sites `__. - -Bitcoin, Ethereum, etc. -~~~~~~~~~~~~~~~~~~~~~~~ - -Tendermint emerged in the tradition of cryptocurrencies like Bitcoin, Ethereum, etc. -with the goal of providing a more efficient and secure consensus algorithm than Bitcoin's Proof of Work. -In the early days, Tendermint had a simple currency built in, and to participate in consensus, -users had to "bond" units of the currency into a security deposit which could be revoked if they misbehaved - -this is what made Tendermint a Proof-of-Stake algorithm. - -Since then, Tendermint has evolved to be a general purpose blockchain consensus engine that can host arbitrary application states. -That means it can be used as a plug-and-play replacement for the consensus engines of other blockchain software. -So one can take the current Ethereum code base, whether in Rust, or Go, or Haskell, and run it as a ABCI application -using Tendermint consensus. Indeed, `we did that with Ethereum `__. -And we plan to do the same for Bitcoin, ZCash, and various other deterministic applications as well. - -Another example of a cryptocurrency application built on Tendermint is `the Cosmos network `__. - -Other Blockchain Projects -~~~~~~~~~~~~~~~~~~~~~~~~~ - -`Fabric `__ takes a similar approach to Tendermint, but is more opinionated about how the state is managed, -and requires that all application behaviour runs in potentially many docker containers, modules it calls "chaincode". -It uses an implementation of `PBFT `__. -from a team at IBM that is -`augmented to handle potentially non-deterministic chaincode `__ -It is possible to implement this docker-based behaviour as a ABCI app in Tendermint, -though extending Tendermint to handle non-determinism remains for future work. - -`Burrow `__ is an implementation of the Ethereum Virtual Machine and Ethereum transaction mechanics, -with additional features for a name-registry, permissions, and native contracts, and an alternative blockchain API. -It uses Tendermint as its consensus engine, and provides a particular application state. - -ABCI Overview -------------- - -The `Application BlockChain Interface (ABCI) `__ allows for Byzantine Fault Tolerant replication of applications written in any programming language. - -Motivation -~~~~~~~~~~ - -Thus far, all blockchains "stacks" (such as `Bitcoin `__) have had a monolithic design. That is, each blockchain stack is a single program that handles all the concerns of a decentralized ledger; this includes P2P connectivity, the "mempool" broadcasting of transactions, consensus on the most recent block, account balances, Turing-complete contracts, user-level permissions, etc. - -Using a monolithic architecture is typically bad practice in computer science. -It makes it difficult to reuse components of the code, and attempts to do so result in complex maintenance procedures for forks of the codebase. -This is especially true when the codebase is not modular in design and suffers from "spaghetti code". - -Another problem with monolithic design is that it limits you to the language of the blockchain stack (or vice versa). In the case of Ethereum which supports a Turing-complete bytecode virtual-machine, it limits you to languages that compile down to that bytecode; today, those are Serpent and Solidity. - -In contrast, our approach is to decouple the consensus engine and P2P layers from the details of the application state of the particular blockchain application. -We do this by abstracting away the details of the application to an interface, which is implemented as a socket protocol. - -Thus we have an interface, the Application BlockChain Interface (ABCI), and its primary implementation, the Tendermint Socket Protocol (TSP, or Teaspoon). - -Intro to ABCI -~~~~~~~~~~~~~ - -`Tendermint Core `__ (the "consensus engine") communicates with the application via a socket protocol that -satisfies the `ABCI `__. - -To draw an analogy, lets talk about a well-known cryptocurrency, Bitcoin. Bitcoin is a cryptocurrency blockchain where each node maintains a fully audited Unspent Transaction Output (UTXO) database. If one wanted to create a Bitcoin-like system on top of ABCI, Tendermint Core would be responsible for - -- Sharing blocks and transactions between nodes -- Establishing a canonical/immutable order of transactions (the blockchain) - -The application will be responsible for - -- Maintaining the UTXO database -- Validating cryptographic signatures of transactions -- Preventing transactions from spending non-existent transactions -- Allowing clients to query the UTXO database. - -Tendermint is able to decompose the blockchain design by offering a very simple API (ie. the ABCI) between the application process and consensus process. - -The ABCI consists of 3 primary message types that get delivered from the core to the application. The application replies with corresponding response messages. - -The messages are specified here: `ABCI Message Types `__. - -The **DeliverTx** message is the work horse of the application. Each transaction in the blockchain is delivered with this message. The application needs to validate each transaction received with the **DeliverTx** message against the current state, application protocol, and the cryptographic credentials of the transaction. A validated transaction then needs to update the application state — by binding a value into a key values store, or by updating the UTXO database, for instance. - -The **CheckTx** message is similar to **DeliverTx**, but it's only for validating transactions. Tendermint Core's mempool first checks the validity of a transaction with **CheckTx**, and only relays valid transactions to its peers. For instance, an application may check an incrementing sequence number in the transaction and return an error upon **CheckTx** if the sequence number is old. Alternatively, they might use a capabilities based system that requires capabilities to be renewed with every transaction. - -The **Commit** message is used to compute a cryptographic commitment to the current application state, to be placed into the next block header. This has some handy properties. Inconsistencies in updating that state will now appear as blockchain forks which catches a whole class of programming errors. This also simplifies the development of secure lightweight clients, as Merkle-hash proofs can be verified by checking against the block hash, and that the block hash is signed by a quorum. - -There can be multiple ABCI socket connections to an application. Tendermint Core creates three ABCI connections to the application; one for the validation of transactions when broadcasting in the mempool, one for the consensus engine to run block proposals, and one more for querying the application state. - -It's probably evident that applications designers need to very carefully design their message handlers to create a blockchain that does anything useful but this architecture provides a place to start. The diagram below illustrates the flow of messages via ABCI. - -.. figure:: assets/abci.png - -A Note on Determinism -~~~~~~~~~~~~~~~~~~~~~ - -The logic for blockchain transaction processing must be deterministic. If the application logic weren't deterministic, consensus would not be reached among the Tendermint Core replica nodes. - -Solidity on Ethereum is a great language of choice for blockchain applications because, among other reasons, it is a completely deterministic programming language. However, it's also possible to create deterministic applications using existing popular languages like Java, C++, Python, or Go. Game programmers and blockchain developers are already familiar with creating deterministic programs by avoiding sources of non-determinism such as: - - * random number generators (without deterministic seeding) - * race conditions on threads (or avoiding threads altogether) - * the system clock - * uninitialized memory (in unsafe programming languages like C or C++) - * `floating point arithmetic `__ - * language features that are random (e.g. map iteration in Go) - -While programmers can avoid non-determinism by being careful, it is also possible to create a special linter or static analyzer for each language to check for determinism. In the future we may work with partners to create such tools. - -Consensus Overview ------------------- - -Tendermint is an easy-to-understand, mostly asynchronous, BFT consensus protocol. -The protocol follows a simple state machine that looks like this: - -.. figure:: assets/consensus_logic.png - -Participants in the protocol are called **validators**; -they take turns proposing blocks of transactions and voting on them. -Blocks are committed in a chain, with one block at each **height**. -A block may fail to be committed, in which case the protocol moves to the next **round**, -and a new validator gets to propose a block for that height. -Two stages of voting are required to successfully commit a block; -we call them **pre-vote** and **pre-commit**. -A block is committed when more than 2/3 of validators pre-commit for the same block in the same round. - -There is a picture of a couple doing the polka because validators are doing something like a polka dance. -When more than two-thirds of the validators pre-vote for the same block, we call that a **polka**. -Every pre-commit must be justified by a polka in the same round. - -Validators may fail to commit a block for a number of reasons; -the current proposer may be offline, or the network may be slow. -Tendermint allows them to establish that a validator should be skipped. -Validators wait a small amount of time to receive a complete proposal block from the proposer before voting to move to the next round. -This reliance on a timeout is what makes Tendermint a weakly synchronous protocol, rather than an asynchronous one. -However, the rest of the protocol is asynchronous, and validators only make progress after hearing from more than two-thirds of the validator set. -A simplifying element of Tendermint is that it uses the same mechanism to commit a block as it does to skip to the next round. - -Assuming less than one-third of the validators are Byzantine, Tendermint guarantees that safety will never be violated - that is, validators will never commit conflicting blocks at the same height. -To do this it introduces a few **locking** rules which modulate which paths can be followed in the flow diagram. -Once a validator precommits a block, it is locked on that block. -Then, - -1) it must prevote for the block it is locked on -2) it can only unlock, and precommit for a new block, if there is a polka for that block in a later round - -Stake ------ - -In many systems, not all validators will have the same "weight" in the consensus protocol. -Thus, we are not so much interested in one-third or two-thirds of the validators, but in those proportions of the total voting power, -which may not be uniformly distributed across individual validators. - -Since Tendermint can replicate arbitrary applications, it is possible to define a currency, and denominate the voting power in that currency. -When voting power is denominated in a native currency, the system is often referred to as Proof-of-Stake. -Validators can be forced, by logic in the application, -to "bond" their currency holdings in a security deposit that can be destroyed if they're found to misbehave in the consensus protocol. -This adds an economic element to the security of the protocol, allowing one to quantify the cost of violating the assumption that less than one-third of voting power is Byzantine. - -The `Cosmos Network `__ is designed to use this Proof-of-Stake mechanism across an array of cryptocurrencies implemented as ABCI applications. - -The following diagram is Tendermint in a (technical) nutshell. `See here for high resolution version `__. - -.. figure:: assets/tm-transaction-flow.png diff --git a/docs/running-in-production.md b/docs/running-in-production.md new file mode 100644 index 00000000..e91e7ef7 --- /dev/null +++ b/docs/running-in-production.md @@ -0,0 +1,195 @@ +# Running in production + +## Logging + +Default logging level (`main:info,state:info,*:`) should suffice for +normal operation mode. Read [this +post](https://blog.cosmos.network/one-of-the-exciting-new-features-in-0-10-0-release-is-smart-log-level-flag-e2506b4ab756) +for details on how to configure `log_level` config variable. Some of the +modules can be found [here](./how-to-read-logs.md#list-of-modules). If +you're trying to debug Tendermint or asked to provide logs with debug +logging level, you can do so by running tendermint with +`--log_level="*:debug"`. + +## DOS Exposure and Mitigation + +Validators are supposed to setup [Sentry Node +Architecture](https://blog.cosmos.network/tendermint-explained-bringing-bft-based-pos-to-the-public-blockchain-domain-f22e274a0fdb) +to prevent Denial-of-service attacks. You can read more about it +[here](https://github.com/tendermint/aib-data/blob/develop/medium/TendermintBFT.md). + +### P2P + +The core of the Tendermint peer-to-peer system is `MConnection`. Each +connection has `MaxPacketMsgPayloadSize`, which is the maximum packet +size and bounded send & receive queues. One can impose restrictions on +send & receive rate per connection (`SendRate`, `RecvRate`). + +### RPC + +Endpoints returning multiple entries are limited by default to return 30 +elements (100 max). + +Rate-limiting and authentication are another key aspects to help protect +against DOS attacks. While in the future we may implement these +features, for now, validators are supposed to use external tools like +[NGINX](https://www.nginx.com/blog/rate-limiting-nginx/) or +[traefik](https://docs.traefik.io/configuration/commons/#rate-limiting) +to achieve the same things. + +## Debugging Tendermint + +If you ever have to debug Tendermint, the first thing you should +probably do is to check out the logs. See ["How to read +logs"](./how-to-read-logs.md), where we explain what certain log +statements mean. + +If, after skimming through the logs, things are not clear still, the +second TODO is to query the /status RPC endpoint. It provides the +necessary info: whenever the node is syncing or not, what height it is +on, etc. + + $ curl http(s)://{ip}:{rpcPort}/status + +`dump_consensus_state` will give you a detailed overview of the +consensus state (proposer, lastest validators, peers states). From it, +you should be able to figure out why, for example, the network had +halted. + + $ curl http(s)://{ip}:{rpcPort}/dump_consensus_state + +There is a reduced version of this endpoint - `consensus_state`, which +returns just the votes seen at the current height. + +- [Github Issues](https://github.com/tendermint/tendermint/issues) +- [StackOverflow + questions](https://stackoverflow.com/questions/tagged/tendermint) + +## Monitoring Tendermint + +Each Tendermint instance has a standard `/health` RPC endpoint, which +responds with 200 (OK) if everything is fine and 500 (or no response) - +if something is wrong. + +Other useful endpoints include mentioned earlier `/status`, `/net_info` and +`/validators`. + +We have a small tool, called `tm-monitor`, which outputs information from +the endpoints above plus some statistics. The tool can be found +[here](https://github.com/tendermint/tools/tree/master/tm-monitor). + +## What happens when my app dies? + +You are supposed to run Tendermint under a [process +supervisor](https://en.wikipedia.org/wiki/Process_supervision) (like +systemd or runit). It will ensure Tendermint is always running (despite +possible errors). + +Getting back to the original question, if your application dies, +Tendermint will panic. After a process supervisor restarts your +application, Tendermint should be able to reconnect successfully. The +order of restart does not matter for it. + +## Signal handling + +We catch SIGINT and SIGTERM and try to clean up nicely. For other +signals we use the default behaviour in Go: [Default behavior of signals +in Go +programs](https://golang.org/pkg/os/signal/#hdr-Default_behavior_of_signals_in_Go_programs). + +## Hardware + +### Processor and Memory + +While actual specs vary depending on the load and validators count, +minimal requirements are: + +- 1GB RAM +- 25GB of disk space +- 1.4 GHz CPU + +SSD disks are preferable for applications with high transaction +throughput. + +Recommended: + +- 2GB RAM +- 100GB SSD +- x64 2.0 GHz 2v CPU + +While for now, Tendermint stores all the history and it may require +significant disk space over time, we are planning to implement state +syncing (See +[this issue](https://github.com/tendermint/tendermint/issues/828)). So, +storing all the past blocks will not be necessary. + +### Operating Systems + +Tendermint can be compiled for a wide range of operating systems thanks +to Go language (the list of \$OS/\$ARCH pairs can be found +[here](https://golang.org/doc/install/source#environment)). + +While we do not favor any operation system, more secure and stable Linux +server distributions (like Centos) should be preferred over desktop +operation systems (like Mac OS). + +### Miscellaneous + +NOTE: if you are going to use Tendermint in a public domain, make sure +you read [hardware recommendations (see "4. +Hardware")](https://cosmos.network/validators) for a validator in the +Cosmos network. + +## Configuration parameters + +- `p2p.flush_throttle_timeout` `p2p.max_packet_msg_payload_size` + `p2p.send_rate` `p2p.recv_rate` + +If you are going to use Tendermint in a private domain and you have a +private high-speed network among your peers, it makes sense to lower +flush throttle timeout and increase other params. + + [p2p] + + send_rate=20000000 # 2MB/s + recv_rate=20000000 # 2MB/s + flush_throttle_timeout=10 + max_packet_msg_payload_size=10240 # 10KB + +- `mempool.recheck` + +After every block, Tendermint rechecks every transaction left in the +mempool to see if transactions committed in that block affected the +application state, so some of the transactions left may become invalid. +If that does not apply to your application, you can disable it by +setting `mempool.recheck=false`. + +- `mempool.broadcast` + +Setting this to false will stop the mempool from relaying transactions +to other peers until they are included in a block. It means only the +peer you send the tx to will see it until it is included in a block. + +- `consensus.skip_timeout_commit` + +We want `skip_timeout_commit=false` when there is economics on the line +because proposers should wait to hear for more votes. But if you don't +care about that and want the fastest consensus, you can skip it. It will +be kept false by default for public deployments (e.g. [Cosmos +Hub](https://cosmos.network/intro/hub)) while for enterprise +applications, setting it to true is not a problem. + +- `consensus.peer_gossip_sleep_duration` + +You can try to reduce the time your node sleeps before checking if +theres something to send its peers. + +- `consensus.timeout_commit` + +You can also try lowering `timeout_commit` (time we sleep before +proposing the next block). + +- `consensus.max_block_size_txs` + +By default, the maximum number of transactions per a block is 10_000. +Feel free to change it to suit your needs. diff --git a/docs/running-in-production.rst b/docs/running-in-production.rst deleted file mode 100644 index 162dfdd8..00000000 --- a/docs/running-in-production.rst +++ /dev/null @@ -1,203 +0,0 @@ -Running in production -===================== - -Logging -------- - -Default logging level (``main:info,state:info,*:``) should suffice for normal -operation mode. Read `this post -`__ -for details on how to configure ``log_level`` config variable. Some of the -modules can be found `here <./how-to-read-logs.html#list-of-modules>`__. If -you're trying to debug Tendermint or asked to provide logs with debug logging -level, you can do so by running tendermint with ``--log_level="*:debug"``. - -DOS Exposure and Mitigation ---------------------------- - -Validators are supposed to setup `Sentry Node Architecture -`__ -to prevent Denial-of-service attacks. You can read more about it `here -`__. - -P2P -~~~ - -The core of the Tendermint peer-to-peer system is ``MConnection``. Each -connection has ``MaxPacketMsgPayloadSize``, which is the maximum packet size -and bounded send & receive queues. One can impose restrictions on send & -receive rate per connection (``SendRate``, ``RecvRate``). - -RPC -~~~ - -Endpoints returning multiple entries are limited by default to return 30 -elements (100 max). - -Rate-limiting and authentication are another key aspects to help protect -against DOS attacks. While in the future we may implement these features, for -now, validators are supposed to use external tools like `NGINX -`__ or `traefik -`__ to achieve -the same things. - -Debugging Tendermint --------------------- - -If you ever have to debug Tendermint, the first thing you should probably do is -to check out the logs. See `"How to read logs" <./how-to-read-logs.html>`__, -where we explain what certain log statements mean. - -If, after skimming through the logs, things are not clear still, the second -TODO is to query the `/status` RPC endpoint. It provides the necessary info: -whenever the node is syncing or not, what height it is on, etc. - -``` -$ curl http(s)://{ip}:{rpcPort}/status -``` - -`/dump_consensus_state` will give you a detailed overview of the consensus -state (proposer, lastest validators, peers states). From it, you should be able -to figure out why, for example, the network had halted. - -``` -$ curl http(s)://{ip}:{rpcPort}/dump_consensus_state -``` - -There is a reduced version of this endpoint - `/consensus_state`, which -returns just the votes seen at the current height. - -- `Github Issues `__ -- `StackOverflow questions `__ - -Monitoring Tendermint ---------------------- - -Each Tendermint instance has a standard `/health` RPC endpoint, which responds -with 200 (OK) if everything is fine and 500 (or no response) - if something is -wrong. - -Other useful endpoints include mentioned earlier `/status`, `/net_info` and -`/validators`. - -We have a small tool, called tm-monitor, which outputs information from the -endpoints above plus some statistics. The tool can be found `here -`__. - -What happens when my app dies? ------------------------------- - -You are supposed to run Tendermint under a `process supervisor -`__ (like systemd or runit). -It will ensure Tendermint is always running (despite possible errors). - -Getting back to the original question, if your application dies, Tendermint -will panic. After a process supervisor restarts your application, Tendermint -should be able to reconnect successfully. The order of restart does not matter -for it. - -Signal handling ---------------- - -We catch SIGINT and SIGTERM and try to clean up nicely. For other signals we -use the default behaviour in Go: `Default behavior of signals in Go programs -`__. - -Hardware --------- - -Processor and Memory -~~~~~~~~~~~~~~~~~~~~ - -While actual specs vary depending on the load and validators count, minimal requirements are: - -- 1GB RAM -- 25GB of disk space -- 1.4 GHz CPU - -SSD disks are preferable for applications with high transaction throughput. - -Recommended: - -- 2GB RAM -- 100GB SSD -- x64 2.0 GHz 2v CPU - -While for now, Tendermint stores all the history and it may require significant -disk space over time, we are planning to implement state syncing (See `#828 -`__). So, storing all the -past blocks will not be necessary. - -Operating Systems -~~~~~~~~~~~~~~~~~ - -Tendermint can be compiled for a wide range of operating systems thanks to Go -language (the list of $OS/$ARCH pairs can be found `here -`__). - -While we do not favor any operation system, more secure and stable Linux server -distributions (like Centos) should be preferred over desktop operation systems -(like Mac OS). - -Misc. -~~~~~ - -NOTE: if you are going to use Tendermint in a public domain, make sure you read -`hardware recommendations (see "4. Hardware") -`__ for a validator in the Cosmos network. - -Configuration parameters ------------------------- - -- ``p2p.flush_throttle_timeout`` - ``p2p.max_packet_msg_payload_size`` - ``p2p.send_rate`` - ``p2p.recv_rate`` - -If you are going to use Tendermint in a private domain and you have a private -high-speed network among your peers, it makes sense to lower flush throttle -timeout and increase other params. - -:: - - [p2p] - - send_rate=20000000 # 2MB/s - recv_rate=20000000 # 2MB/s - flush_throttle_timeout=10 - max_packet_msg_payload_size=10240 # 10KB - -- ``mempool.recheck`` - -After every block, Tendermint rechecks every transaction left in the mempool to -see if transactions committed in that block affected the application state, so -some of the transactions left may become invalid. If that does not apply to -your application, you can disable it by setting ``mempool.recheck=false``. - -- ``mempool.broadcast`` - -Setting this to false will stop the mempool from relaying transactions to other -peers until they are included in a block. It means only the peer you send the -tx to will see it until it is included in a block. - -- ``consensus.skip_timeout_commit`` - -We want skip_timeout_commit=false when there is economics on the line because -proposers should wait to hear for more votes. But if you don't care about that -and want the fastest consensus, you can skip it. It will be kept false by -default for public deployments (e.g. `Cosmos Hub -`__) while for enterprise applications, -setting it to true is not a problem. - -- ``consensus.peer_gossip_sleep_duration`` - -You can try to reduce the time your node sleeps before checking if theres something to send its peers. - -- ``consensus.timeout_commit`` - -You can also try lowering ``timeout_commit`` (time we sleep before proposing the next block). - -- ``consensus.max_block_size_txs`` - -By default, the maximum number of transactions per a block is 10_000. Feel free -to change it to suit your needs. diff --git a/docs/subscribing-to-events-via-websocket.md b/docs/subscribing-to-events-via-websocket.md new file mode 100644 index 00000000..43d3f776 --- /dev/null +++ b/docs/subscribing-to-events-via-websocket.md @@ -0,0 +1,26 @@ +# Subscribing to events via Websocket + +Tendermint emits different events, to which you can subscribe via +[Websocket](https://en.wikipedia.org/wiki/WebSocket). This can be useful +for third-party applications (for analysys) or inspecting state. + +[List of events](https://godoc.org/github.com/tendermint/tendermint/types#pkg-constants) + +You can subscribe to any of the events above by calling `subscribe` RPC +method via Websocket. + + { + "jsonrpc": "2.0", + "method": "subscribe", + "id": "0", + "params": { + "query": "tm.event='NewBlock'" + } + } + +Check out [API docs](https://tendermint.github.io/slate/#subscribe) for +more information on query syntax and other options. + +You can also use tags, given you had included them into DeliverTx +response, to query transaction results. See [Indexing +transactions](./indexing-transactions.md) for details. diff --git a/docs/subscribing-to-events-via-websocket.rst b/docs/subscribing-to-events-via-websocket.rst deleted file mode 100644 index f99d94b6..00000000 --- a/docs/subscribing-to-events-via-websocket.rst +++ /dev/null @@ -1,28 +0,0 @@ -Subscribing to events via Websocket -=================================== - -Tendermint emits different events, to which you can subscribe via `Websocket -`__. This can be useful for -third-party applications (for analysys) or inspecting state. - -`List of events `__ - -You can subscribe to any of the events above by calling ``subscribe`` RPC method via Websocket. - -:: - - { - "jsonrpc": "2.0", - "method": "subscribe", - "id": "0", - "params": { - "query": "tm.event='NewBlock'" - } - } - -Check out `API docs `__ for more -information on query syntax and other options. - -You can also use tags, given you had included them into DeliverTx response, to -query transaction results. See `Indexing transactions -<./indexing-transactions.html>`__ for details. diff --git a/docs/terraform-and-ansible.md b/docs/terraform-and-ansible.md new file mode 100644 index 00000000..0e34b6bd --- /dev/null +++ b/docs/terraform-and-ansible.md @@ -0,0 +1,147 @@ +# Terraform & Ansible + +Automated deployments are done using +[Terraform](https://www.terraform.io/) to create servers on Digital +Ocean then [Ansible](http://www.ansible.com/) to create and manage +testnets on those servers. + +## Install + +NOTE: see the [integration bash +script](https://github.com/tendermint/tendermint/blob/develop/networks/remote/integration.sh) +that can be run on a fresh DO droplet and will automatically spin up a 4 +node testnet. The script more or less does everything described below. + +- Install [Terraform](https://www.terraform.io/downloads.html) and + [Ansible](http://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) + on a Linux machine. +- Create a [DigitalOcean API + token](https://cloud.digitalocean.com/settings/api/tokens) with read + and write capability. +- Install the python dopy package (`pip install dopy`) +- Create SSH keys (`ssh-keygen`) +- Set environment variables: + +``` +export DO_API_TOKEN="abcdef01234567890abcdef01234567890" +export SSH_KEY_FILE="$HOME/.ssh/id_rsa.pub" +``` + +These will be used by both `terraform` and `ansible`. + +### Terraform + +This step will create four Digital Ocean droplets. First, go to the +correct directory: + + cd $GOPATH/src/github.com/tendermint/tendermint/networks/remote/terraform + +then: + + terraform init + terraform apply -var DO_API_TOKEN="$DO_API_TOKEN" -var SSH_KEY_FILE="$SSH_KEY_FILE" + +and you will get a list of IP addresses that belong to your droplets. + +With the droplets created and running, let's setup Ansible. + +### Ansible + +The playbooks in [the ansible +directory](https://github.com/tendermint/tendermint/tree/master/networks/remote/ansible) +run ansible roles to configure the sentry node architecture. You must +switch to this directory to run ansible +(`cd $GOPATH/src/github.com/tendermint/tendermint/networks/remote/ansible`). + +There are several roles that are self-explanatory: + +First, we configure our droplets by specifying the paths for tendermint +(`BINARY`) and the node files (`CONFIGDIR`). The latter expects any +number of directories named `node0, node1, ...` and so on (equal to the +number of droplets created). For this example, we use pre-created files +from [this +directory](https://github.com/tendermint/tendermint/tree/master/docs/examples). +To create your own files, use either the `tendermint testnet` command or +review [manual deployments](./deploy-testnets.md). + +Here's the command to run: + + ansible-playbook -i inventory/digital_ocean.py -l sentrynet config.yml -e BINARY=$GOPATH/src/github.com/tendermint/tendermint/build/tendermint -e CONFIGDIR=$GOPATH/src/github.com/tendermint/tendermint/docs/examples + +Voila! All your droplets now have the `tendermint` binary and required +configuration files to run a testnet. + +Next, we run the install role: + + ansible-playbook -i inventory/digital_ocean.py -l sentrynet install.yml + +which as you'll see below, executes +`tendermint node --proxy_app=kvstore` on all droplets. Although we'll +soon be modifying this role and running it again, this first execution +allows us to get each `node_info.id` that corresponds to each +`node_info.listen_addr`. (This part will be automated in the future). In +your browser (or using `curl`), for every droplet, go to IP:46657/status +and note the two just mentioned `node_info` fields. Notice that blocks +aren't being created (`latest_block_height` should be zero and not +increasing). + +Next, open `roles/install/templates/systemd.service.j2` and look for the +line `ExecStart` which should look something like: + + ExecStart=/usr/bin/tendermint node --proxy_app=kvstore + +and add the `--p2p.persistent_peers` flag with the relevant information +for each node. The resulting file should look something like: + + [Unit] + Description={{service}} + Requires=network-online.target + After=network-online.target + + [Service] + Restart=on-failure + User={{service}} + Group={{service}} + PermissionsStartOnly=true + ExecStart=/usr/bin/tendermint node --proxy_app=kvstore --p2p.persistent_peers=167b80242c300bf0ccfb3ced3dec60dc2a81776e@165.227.41.206:46656,3c7a5920811550c04bf7a0b2f1e02ab52317b5e6@165.227.43.146:46656,303a1a4312c30525c99ba66522dd81cca56a361a@159.89.115.32:46656,b686c2a7f4b1b46dca96af3a0f31a6a7beae0be4@159.89.119.125:46656 + ExecReload=/bin/kill -HUP $MAINPID + KillSignal=SIGTERM + + [Install] + WantedBy=multi-user.target + +Then, stop the nodes: + + ansible-playbook -i inventory/digital_ocean.py -l sentrynet stop.yml + +Finally, we run the install role again: + + ansible-playbook -i inventory/digital_ocean.py -l sentrynet install.yml + +to re-run `tendermint node` with the new flag, on all droplets. The +`latest_block_hash` should now be changing and `latest_block_height` +increasing. Your testnet is now up and running :) + +Peek at the logs with the status role: + + ansible-playbook -i inventory/digital_ocean.py -l sentrynet status.yml + +### Logging + +The crudest way is the status role described above. You can also ship +logs to Logz.io, an Elastic stack (Elastic search, Logstash and Kibana) +service provider. You can set up your nodes to log there automatically. +Create an account and get your API key from the notes on [this +page](https://app.logz.io/#/dashboard/data-sources/Filebeat), then: + + yum install systemd-devel || echo "This will only work on RHEL-based systems." + apt-get install libsystemd-dev || echo "This will only work on Debian-based systems." + + go get github.com/mheese/journalbeat + ansible-playbook -i inventory/digital_ocean.py -l sentrynet logzio.yml -e LOGZIO_TOKEN=ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 + +### Cleanup + +To remove your droplets, run: + + terraform destroy -var DO_API_TOKEN="$DO_API_TOKEN" -var SSH_KEY_FILE="$SSH_KEY_FILE" diff --git a/docs/terraform-and-ansible.rst b/docs/terraform-and-ansible.rst deleted file mode 100644 index c47de9d4..00000000 --- a/docs/terraform-and-ansible.rst +++ /dev/null @@ -1,138 +0,0 @@ -Terraform & Ansible -=================== - -Automated deployments are done using `Terraform `__ to create servers on Digital Ocean then -`Ansible `__ to create and manage testnets on those servers. - -Install -------- - -NOTE: see the `integration bash script `__ that can be run on a fresh DO droplet and will automatically spin up a 4 node testnet. The script more or less does everything described below. - -- Install `Terraform `__ and `Ansible `__ on a Linux machine. -- Create a `DigitalOcean API token `__ with read and write capability. -- Install the python dopy package (``pip install dopy``) -- Create SSH keys (``ssh-keygen``) -- Set environment variables: - -:: - - export DO_API_TOKEN="abcdef01234567890abcdef01234567890" - export SSH_KEY_FILE="$HOME/.ssh/id_rsa.pub" - -These will be used by both ``terraform`` and ``ansible``. - -Terraform ---------- - -This step will create four Digital Ocean droplets. First, go to the correct directory: - -:: - - cd $GOPATH/src/github.com/tendermint/tendermint/networks/remote/terraform - -then: - -:: - - terraform init - terraform apply -var DO_API_TOKEN="$DO_API_TOKEN" -var SSH_KEY_FILE="$SSH_KEY_FILE" - -and you will get a list of IP addresses that belong to your droplets. - -With the droplets created and running, let's setup Ansible. - -Using Ansible -------------- - -The playbooks in `the ansible directory `__ -run ansible roles to configure the sentry node architecture. You must switch to this directory to run ansible (``cd $GOPATH/src/github.com/tendermint/tendermint/networks/remote/ansible``). - -There are several roles that are self-explanatory: - -First, we configure our droplets by specifying the paths for tendermint (``BINARY``) and the node files (``CONFIGDIR``). The latter expects any number of directories named ``node0, node1, ...`` and so on (equal to the number of droplets created). For this example, we use pre-created files from `this directory `__. To create your own files, use either the ``tendermint testnet`` command or review `manual deployments <./deploy-testnets.html>`__. - -Here's the command to run: - -:: - - ansible-playbook -i inventory/digital_ocean.py -l sentrynet config.yml -e BINARY=$GOPATH/src/github.com/tendermint/tendermint/build/tendermint -e CONFIGDIR=$GOPATH/src/github.com/tendermint/tendermint/docs/examples - -Voila! All your droplets now have the ``tendermint`` binary and required configuration files to run a testnet. - -Next, we run the install role: - -:: - - ansible-playbook -i inventory/digital_ocean.py -l sentrynet install.yml - -which as you'll see below, executes ``tendermint node --proxy_app=kvstore`` on all droplets. Although we'll soon be modifying this role and running it again, this first execution allows us to get each ``node_info.id`` that corresponds to each ``node_info.listen_addr``. (This part will be automated in the future). In your browser (or using ``curl``), for every droplet, go to IP:46657/status and note the two just mentioned ``node_info`` fields. Notice that blocks aren't being created (``latest_block_height`` should be zero and not increasing). - -Next, open ``roles/install/templates/systemd.service.j2`` and look for the line ``ExecStart`` which should look something like: - -:: - - ExecStart=/usr/bin/tendermint node --proxy_app=kvstore - -and add the ``--p2p.persistent_peers`` flag with the relevant information for each node. The resulting file should look something like: - -:: - - [Unit] - Description={{service}} - Requires=network-online.target - After=network-online.target - - [Service] - Restart=on-failure - User={{service}} - Group={{service}} - PermissionsStartOnly=true - ExecStart=/usr/bin/tendermint node --proxy_app=kvstore --p2p.persistent_peers=167b80242c300bf0ccfb3ced3dec60dc2a81776e@165.227.41.206:46656,3c7a5920811550c04bf7a0b2f1e02ab52317b5e6@165.227.43.146:46656,303a1a4312c30525c99ba66522dd81cca56a361a@159.89.115.32:46656,b686c2a7f4b1b46dca96af3a0f31a6a7beae0be4@159.89.119.125:46656 - ExecReload=/bin/kill -HUP $MAINPID - KillSignal=SIGTERM - - [Install] - WantedBy=multi-user.target - -Then, stop the nodes: - -:: - - ansible-playbook -i inventory/digital_ocean.py -l sentrynet stop.yml - -Finally, we run the install role again: - -:: - - ansible-playbook -i inventory/digital_ocean.py -l sentrynet install.yml - -to re-run ``tendermint node`` with the new flag, on all droplets. The ``latest_block_hash`` should now be changing and ``latest_block_height`` increasing. Your testnet is now up and running :) - -Peek at the logs with the status role: - -:: - - ansible-playbook -i inventory/digital_ocean.py -l sentrynet status.yml - -Logging -------- - -The crudest way is the status role described above. You can also ship logs to Logz.io, an Elastic stack (Elastic search, Logstash and Kibana) service provider. You can set up your nodes to log there automatically. Create an account and get your API key from the notes on `this page `__, then: - -:: - - yum install systemd-devel || echo "This will only work on RHEL-based systems." - apt-get install libsystemd-dev || echo "This will only work on Debian-based systems." - - go get github.com/mheese/journalbeat - ansible-playbook -i inventory/digital_ocean.py -l sentrynet logzio.yml -e LOGZIO_TOKEN=ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 - -Cleanup -------- - -To remove your droplets, run: - -:: - - terraform destroy -var DO_API_TOKEN="$DO_API_TOKEN" -var SSH_KEY_FILE="$SSH_KEY_FILE" diff --git a/docs/transactional-semantics.md b/docs/transactional-semantics.md new file mode 100644 index 00000000..bab1864e --- /dev/null +++ b/docs/transactional-semantics.md @@ -0,0 +1,25 @@ +# Transactional Semantics + +In [Using Tendermint](./using-tendermint.md#broadcast-api) we +discussed different API endpoints for sending transactions and +differences between them. + +What we have not yet covered is transactional semantics. + +When you send a transaction using one of the available methods, it first +goes to the mempool. Currently, it does not provide strong guarantees +like "if the transaction were accepted, it would be eventually included +in a block (given CheckTx passes)." + +For instance a tx could enter the mempool, but before it can be sent to +peers the node crashes. + +We are planning to provide such guarantees by using a WAL and replaying +transactions (See +[this issue](https://github.com/tendermint/tendermint/issues/248)), but +it's non-trivial to do this all efficiently. + +The temporary solution is for clients to monitor the node and resubmit +transaction(s) and/or send them to more nodes at once, so the +probability of all of them crashing at the same time and losing the msg +decreases substantially. diff --git a/docs/transactional-semantics.rst b/docs/transactional-semantics.rst deleted file mode 100644 index 988ac682..00000000 --- a/docs/transactional-semantics.rst +++ /dev/null @@ -1,27 +0,0 @@ -Transactional Semantics -======================= - -In `Using -Tendermint <./using-tendermint.html#broadcast-api>`__ we -discussed different API endpoints for sending transactions and -differences between them. - -What we have not yet covered is transactional semantics. - -When you send a transaction using one of the available methods, it -first goes to the mempool. Currently, it does not provide strong -guarantees like "if the transaction were accepted, it would be -eventually included in a block (given CheckTx passes)." - -For instance a tx could enter the mempool, but before it can be sent -to peers the node crashes. - -We are planning to provide such guarantees by using a WAL and -replaying transactions (See -`GH#248 `__), but -it's non-trivial to do this all efficiently. - -The temporary solution is for clients to monitor the node and resubmit -transaction(s) or/and send them to more nodes at once, so the -probability of all of them crashing at the same time and losing the -msg decreases substantially. diff --git a/docs/using-tendermint.md b/docs/using-tendermint.md new file mode 100644 index 00000000..d4eef479 --- /dev/null +++ b/docs/using-tendermint.md @@ -0,0 +1,399 @@ +# 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. + +## 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 (e.g., 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. diff --git a/docs/using-tendermint.rst b/docs/using-tendermint.rst deleted file mode 100644 index 56790fea..00000000 --- a/docs/using-tendermint.rst +++ /dev/null @@ -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 `__. 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 `__ tool written by `@hxzqlh `__ if -you are keen to preserve the state of your chain when upgrading to newer versions.