diff --git a/Vagrantfile b/Vagrantfile index 320f3b1c329..515a4879118 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -34,6 +34,10 @@ Vagrant.configure("2") do |config| mv go /usr/local rm -f go1.11.linux-amd64.tar.gz + # install nodejs (for docs) + curl -sL https://deb.nodesource.com/setup_11.x | bash - + apt-get install -y nodejs + # cleanup apt-get autoremove -y diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index fb3620e3451..0b54d201148 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -63,7 +63,8 @@ module.exports = { "/tendermint-core/light-client-protocol", "/tendermint-core/metrics", "/tendermint-core/secure-p2p", - "/tendermint-core/validators" + "/tendermint-core/validators", + "/tendermint-core/mempool" ] }, { diff --git a/docs/DOCS_README.md b/docs/DOCS_README.md index c91d0391173..49c2030a279 100644 --- a/docs/DOCS_README.md +++ b/docs/DOCS_README.md @@ -66,11 +66,12 @@ To build and serve the documentation locally, run: ``` # from this directory -npm install npm install -g vuepress ``` -then change the following line in the `config.js`: +NOTE: the command may require `sudo`. + +then change the following line in the `.vuepress/config.js`: ``` base: "/docs/", diff --git a/docs/spec/reactors/mempool/functionality.md b/docs/spec/reactors/mempool/functionality.md index 4064def0b63..ea902225db2 100644 --- a/docs/spec/reactors/mempool/functionality.md +++ b/docs/spec/reactors/mempool/functionality.md @@ -40,4 +40,4 @@ However, we only store valid txs in the cache, not invalid ones. This is because invalid txs could become good later. Txs that are included in a block aren't removed from the cache, as they still may be getting received over the p2p network. -These txs are stored in the cache by their hash, to mitigate memory concerns. \ No newline at end of file +These txs are stored in the cache by their hash, to mitigate memory concerns. diff --git a/docs/tendermint-core/configuration.md b/docs/tendermint-core/configuration.md index f753d212334..4e188aae75d 100644 --- a/docs/tendermint-core/configuration.md +++ b/docs/tendermint-core/configuration.md @@ -268,3 +268,74 @@ max_open_connections = 3 # Instrumentation namespace namespace = "tendermint" ``` + +## Empty blocks VS no empty blocks + +**create_empty_blocks = true** + +If `create_empty_blocks` is set to `true` in your config, blocks will be +created ~ every second (with default consensus parameters). You can regulate +the delay between blocks by changing the `timeout_commit`. E.g. `timeout_commit += "10s"` should result in ~ 10 second blocks. + +**create_empty_blocks = false** + +In this setting, blocks are created when transactions received. + +Note after the block H, Tendermint creates something we call a "proof block" +(only if the application hash changed) H+1. The reason for this is to support +proofs. If you have a transaction in block H that changes the state to X, the +new application hash will only be included in block H+1. If after your +transaction is committed, you want to get a lite-client proof for the new state +(X), you need the new block to be committed in order to do that because the new +block has the new application hash for the state X. That's why we make a new +(empty) block if the application hash changes. Otherwise, you won't be able to +make a proof for the new state. + +Plus, if you set `create_empty_blocks_interval` to something other than the +default (`0`), Tendermint will be creating empty blocks even in the absence of +transactions every `create_empty_blocks_interval`. For instance, with +`create_empty_blocks = false` and `create_empty_blocks_interval = "30s"`, +Tendermint will only create blocks if there are transactions, or after waiting +30 seconds without receiving any transactions. + +## Consensus timeouts explained + +There's a variety of information about timeouts in [Running in +production](./running-in-production.html) + +You can also find more detailed technical explanation in the spec: [The latest +gossip on BFT consensus](https://arxiv.org/abs/1807.04938). + +``` +[consensus] +... + +timeout_propose = "3s" +timeout_propose_delta = "500ms" +timeout_prevote = "1s" +timeout_prevote_delta = "500ms" +timeout_precommit = "1s" +timeout_precommit_delta = "500ms" +timeout_commit = "1s" +``` + +Note that in a successful round, the only timeout that we absolutely wait no +matter what is `timeout_commit`. + +Here's a brief summary of the timeouts: + +- `timeout_propose` = how long we wait for a proposal block before prevoting + nil +- `timeout_propose_delta` = how much timeout_propose increases with each round +- `timeout_prevote` = how long we wait after receiving +2/3 prevotes for + anything (ie. not a single block or nil) +- `timeout_prevote_delta` = how much the timeout_prevote increases with each + round +- `timeout_precommit` = how long we wait after receiving +2/3 precommits for + anything (ie. not a single block or nil) +- `timeout_precommit_delta` = how much the timeout_precommit increases with + each round +- `timeout_commit` = how long we wait after committing a block, before starting + on the new height (this gives us a chance to receive some more precommits, + even though we already have +2/3) diff --git a/docs/tendermint-core/mempool.md b/docs/tendermint-core/mempool.md new file mode 100644 index 00000000000..883853ace7c --- /dev/null +++ b/docs/tendermint-core/mempool.md @@ -0,0 +1,41 @@ +# Mempool + +## Transaction ordering + +Currently, there's no ordering of transactions other than the order they've +arrived (via RPC or from other nodes). + +So the only way to specify the order is to send them to a single node. + +valA: + - tx1 + - tx2 + - tx3 + +If the transactions are split up across different nodes, there's no way to +ensure they are processed in the expected order. + +valA: + - tx1 + - tx2 + +valB: + - tx3 + +If valB is the proposer, the order might be: + + - tx3 + - tx1 + - tx2 + +If valA is the proposer, the order might be: + + - tx1 + - tx2 + - tx3 + +That said, if the transactions contain some internal value, like an +order/nonce/sequence number, the application can reject transactions that are +out of order. So if a node receives tx3, then tx1, it can reject tx3 and then +accept tx1. The sender can then retry sending tx3, which should probably be +rejected until the node has seen tx2. diff --git a/rpc/core/mempool.go b/rpc/core/mempool.go index d4993074d3e..42aa56afd02 100644 --- a/rpc/core/mempool.go +++ b/rpc/core/mempool.go @@ -16,7 +16,13 @@ import ( //----------------------------------------------------------------------------- // NOTE: tx should be signed, but this is only checked at the app level (not by Tendermint!) -// Returns right away, with no response +// Returns right away, with no response. Does not wait for CheckTx nor +// DeliverTx results. +// +// Please refer to +// https://tendermint.com/docs/tendermint-core/using-tendermint.html#formatting +// for formatting/encoding rules. +// // // ```shell // curl 'localhost:26657/broadcast_tx_async?tx="123"' @@ -61,7 +67,11 @@ func BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) { return &ctypes.ResultBroadcastTx{Hash: tx.Hash()}, nil } -// Returns with the response from CheckTx. +// Returns with the response from CheckTx. Does not wait for DeliverTx result. +// +// Please refer to +// https://tendermint.com/docs/tendermint-core/using-tendermint.html#formatting +// for formatting/encoding rules. // // ```shell // curl 'localhost:26657/broadcast_tx_sync?tx="456"' @@ -116,12 +126,19 @@ func BroadcastTxSync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) { }, nil } +// Returns with the responses from CheckTx and DeliverTx. +// // CONTRACT: only returns error if mempool.CheckTx() errs or if we timeout // waiting for tx to commit. // // If CheckTx or DeliverTx fail, no error will be returned, but the returned result // will contain a non-OK ABCI code. // +// Please refer to +// https://tendermint.com/docs/tendermint-core/using-tendermint.html#formatting +// for formatting/encoding rules. +// +// // ```shell // curl 'localhost:26657/broadcast_tx_commit?tx="789"' // ```