You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
12 KiB

6 years ago
6 years ago
6 years ago
6 years ago
  1. # Applications
  2. Please ensure you've first read the spec for [ABCI Methods and Types](abci.md)
  3. Here we cover the following components of ABCI applications:
  4. - [Connection State](#state) - the interplay between ABCI connections and application state
  5. and the differences between `CheckTx` and `DeliverTx`.
  6. - [Transaction Results](#transaction-results) - rules around transaction
  7. results and validity
  8. - [Validator Set Updates](#validator-updates) - how validator sets are
  9. changed during `InitChain` and `EndBlock`
  10. - [Query](#query) - standards for using the `Query` method and proofs about the
  11. application state
  12. - [Crash Recovery](#crash-recovery) - handshake protocol to synchronize
  13. Tendermint and the application on startup.
  14. ## State
  15. Since Tendermint maintains three concurrent ABCI connections, it is typical
  16. for an application to maintain a distinct state for each, and for the states to
  17. be synchronized during `Commit`.
  18. ### Commit
  19. Application state should only be persisted to disk during `Commit`.
  20. Before `Commit` is called, Tendermint locks and flushes the mempool so that no new messages will
  21. be received on the mempool connection. This provides an opportunity to safely update all three
  22. states to the latest committed state at once.
  23. When `Commit` completes, it unlocks the mempool.
  24. Note that it is not possible to send transactions to Tendermint during `Commit` - if your app
  25. tries to send a `/broadcast_tx` to Tendermint during Commit, it will deadlock.
  26. ### Consensus Connection
  27. The Consensus Connection should maintain a `DeliverTxState` -
  28. the working state for block execution. It should be updated by the calls to
  29. `BeginBlock`, `DeliverTx`, and `EndBlock` during block execution and committed to
  30. disk as the "latest committed state" during `Commit`.
  31. Updates made to the DeliverTxState by each method call must be readable by each subsequent method -
  32. ie. the updates are linearizable.
  33. ### Mempool Connection
  34. The Mempool Connection should maintain a `CheckTxState`
  35. to sequentially process pending transactions in the mempool that have
  36. not yet been committed. It should be initialized to the latest committed state
  37. at the end of every `Commit`.
  38. The CheckTxState may be updated concurrently with the DeliverTxState, as
  39. messages may be sent concurrently on the Consensus and Mempool connections. However,
  40. before calling `Commit`, Tendermint will lock and flush the mempool connection,
  41. ensuring that all existing CheckTx are responded to and no new ones can
  42. begin.
  43. After `Commit`, CheckTx is run again on all transactions that remain in the
  44. node's local mempool after filtering those included in the block. To prevent the
  45. mempool from rechecking all transactions every time a block is committed, set
  46. the configuration option `mempool.recheck=false`.
  47. Finally, the mempool will unlock and new transactions can be processed through CheckTx again.
  48. Note that CheckTx doesn't have to check everything that affects transaction validity; the
  49. expensive things can be skipped. In fact, CheckTx doesn't have to check
  50. anything; it might say that any transaction is a valid transaction.
  51. Unlike DeliverTx, CheckTx is just there as
  52. a sort of weak filter to keep invalid transactions out of the blockchain. It's
  53. weak, because a Byzantine node doesn't care about CheckTx; it can propose a
  54. block full of invalid transactions if it wants.
  55. ### Info Connection
  56. The Info Connection should maintain a `QueryState` for answering queries from the user,
  57. and for initialization when Tendermint first starts up (both described further
  58. below).
  59. It should always contain the latest committed state associated with the
  60. latest committed block.
  61. QueryState should be set to the latest `DeliverTxState` at the end of every `Commit`,
  62. ie. after the full block has been processed and the state committed to disk.
  63. Otherwise it should never be modified.
  64. ## Transaction Results
  65. `ResponseCheckTx` and `ResponseDeliverTx` contain the same fields, though they
  66. have slightly different effects.
  67. In both cases, `Info` and `Log` are non-deterministic values for debugging/convenience purposes
  68. that are otherwise ignored.
  69. In both cases, `GasWanted` and `GasUsed` parameters are currently ignored,
  70. though see issues
  71. [#1861](https://github.com/tendermint/tendermint/issues/1861),
  72. [#2299](https://github.com/tendermint/tendermint/issues/2299) and
  73. [#2310](https://github.com/tendermint/tendermint/issues/2310) for how this may
  74. soon change.
  75. ### CheckTx
  76. If `Code != 0`, it will be rejected from the mempool and hence
  77. not broadcasted to other peers and not included in a proposal block.
  78. `Data` contains the result of the CheckTx transaction execution, if any. It is
  79. semantically meaningless to Tendermint.
  80. `Tags` include any tags for the execution, though since the transaction has not
  81. been committed yet, they are effectively ignored by Tendermint.
  82. ### DeliverTx
  83. If DeliverTx returns `Code != 0`, the transaction will be considered invalid,
  84. though it is still included in the block.
  85. `Data` contains the result of the CheckTx transaction execution, if any. It is
  86. semantically meaningless to Tendermint.
  87. Both the `Code` and `Data` are included in a structure that is hashed into the
  88. `LastResultsHash` of the next block header.
  89. `Tags` include any tags for the execution, which Tendermint will use to index
  90. the transaction by. This allows transactions to be queried according to what
  91. events took place during their execution.
  92. See issue [#1007](https://github.com/tendermint/tendermint/issues/1007) for how
  93. the tags will be hashed into the next block header.
  94. ## Validator Updates
  95. The application may set the validator set during InitChain, and update it during
  96. EndBlock.
  97. ### InitChain
  98. ResponseInitChain can return a list of validators.
  99. If the list is empty, Tendermint will use the validators loaded in the genesis
  100. file.
  101. If the list is not empty, Tendermint will use it for the validator set.
  102. This way the application can determine the initial validator set for the
  103. blockchain.
  104. ResponseInitChain also includes ConsensusParams, but these are presently
  105. ignored.
  106. ### EndBlock
  107. Updates to the Tendermint validator set can be made by returning
  108. `ValidatorUpdate` objects in the `ResponseEndBlock`:
  109. ```
  110. message ValidatorUpdate {
  111. PubKey pub_key
  112. int64 power
  113. }
  114. message PubKey {
  115. string type
  116. bytes data
  117. }
  118. ```
  119. The `pub_key` currently supports only one type:
  120. - `type = "ed25519" and`data = <raw 32-byte public key>`
  121. The `power` is the new voting power for the validator, with the
  122. following rules:
  123. - power must be non-negative
  124. - if power is 0, the validator must already exist, and will be removed from the
  125. validator set
  126. - if power is non-0:
  127. - if the validator does not already exist, it will be added to the validator
  128. set with the given power
  129. - if the validator does already exist, its power will be adjusted to the given power
  130. Note the updates returned in block `H` will only take effect at block `H+2`.
  131. ## Query
  132. Query is a generic method with lots of flexibility to enable diverse sets
  133. of queries on application state. Tendermint makes use of Query to filter new peers
  134. based on ID and IP, and exposes Query to the user over RPC.
  135. Note that calls to Query are not replicated across nodes, but rather query the
  136. local node's state - hence they may provide stale reads. For reads that require
  137. consensus, a transaction is required.
  138. The most important use of Query is to return Merkle proofs of the application state at some height
  139. that can be used for efficient application-specific lite-clients.
  140. Note Tendermint has technically no requirements from the Query
  141. message for normal operation - that is, the ABCI app developer need not implement
  142. Query functionality if they do not wish too.
  143. ### Query Proofs
  144. The Tendermint block header includes a number of hashes, each providing an
  145. anchor for some type of proof about the blockchain. The `ValidatorsHash` enables
  146. quick verification of the validator set, the `DataHash` gives quick
  147. verification of the transactions included in the block, etc.
  148. The `AppHash` is unique in that it is application specific, and allows for
  149. application-specific Merkle proofs about the state of the application.
  150. While some applications keep all relevant state in the transactions themselves
  151. (like Bitcoin and its UTXOs), others maintain a separated state that is
  152. computed deterministically *from* transactions, but is not contained directly in
  153. the transactions themselves (like Ethereum contracts and accounts).
  154. For such applications, the `AppHash` provides a much more efficient way to verify lite-client proofs.
  155. ABCI applications can take advantage of more efficient lite-client proofs for
  156. their state as follows:
  157. - return the Merkle root of the deterministic application state in
  158. `ResponseCommit.Data`.
  159. - it will be included as the `AppHash` in the next block.
  160. - return efficient Merkle proofs about that application state in `ResponseQuery.Proof`
  161. that can be verified using the `AppHash` of the corresponding block.
  162. For instance, this allows an application's lite-client to verify proofs of
  163. absence in the application state, something which is much less efficient to do using the block hash.
  164. ### Peer Filtering
  165. When Tendermint connects to a peer, it sends two queries to the ABCI application
  166. using the following paths, with no additional data:
  167. - `/p2p/filter/addr/<IP:PORT>`, where `<IP:PORT>` denote the IP address and
  168. the port of the connection
  169. - `p2p/filter/id/<ID>`, where `<ID>` is the peer node ID (ie. the
  170. pubkey.Address() for the peer's PubKey)
  171. If either of these queries return a non-zero ABCI code, Tendermint will refuse
  172. to connect to the peer.
  173. ## Crash Recovery
  174. On startup, Tendermint calls the `Info` method on the Info Connection to get the latest
  175. committed state of the app. The app MUST return information consistent with the
  176. last block it succesfully completed Commit for.
  177. If the app succesfully committed block H but not H+1, then `last_block_height = H` and `last_block_app_hash = <hash returned by Commit for block H>`. If the app
  178. failed during the Commit of block H, then `last_block_height = H-1` and
  179. `last_block_app_hash = <hash returned by Commit for block H-1, which is the hash in the header of block H>`.
  180. We now distinguish three heights, and describe how Tendermint syncs itself with
  181. the app.
  182. ```
  183. storeBlockHeight = height of the last block Tendermint saw a commit for
  184. stateBlockHeight = height of the last block for which Tendermint completed all
  185. block processing and saved all ABCI results to disk
  186. appBlockHeight = height of the last block for which ABCI app succesfully
  187. completed Commit
  188. ```
  189. Note we always have `storeBlockHeight >= stateBlockHeight` and `storeBlockHeight >= appBlockHeight`
  190. Note also we never call Commit on an ABCI app twice for the same height.
  191. The procedure is as follows.
  192. First, some simple start conditions:
  193. If `appBlockHeight == 0`, then call InitChain.
  194. If `storeBlockHeight == 0`, we're done.
  195. Now, some sanity checks:
  196. If `storeBlockHeight < appBlockHeight`, error
  197. If `storeBlockHeight < stateBlockHeight`, panic
  198. If `storeBlockHeight > stateBlockHeight+1`, panic
  199. Now, the meat:
  200. If `storeBlockHeight == stateBlockHeight && appBlockHeight < storeBlockHeight`,
  201. replay all blocks in full from `appBlockHeight` to `storeBlockHeight`.
  202. This happens if we completed processing the block, but the app forgot its height.
  203. If `storeBlockHeight == stateBlockHeight && appBlockHeight == storeBlockHeight`, we're done
  204. This happens if we crashed at an opportune spot.
  205. If `storeBlockHeight == stateBlockHeight+1`
  206. This happens if we started processing the block but didn't finish.
  207. If `appBlockHeight < stateBlockHeight`
  208. replay all blocks in full from `appBlockHeight` to `storeBlockHeight-1`,
  209. and replay the block at `storeBlockHeight` using the WAL.
  210. This happens if the app forgot the last block it committed.
  211. If `appBlockHeight == stateBlockHeight`,
  212. replay the last block (storeBlockHeight) in full.
  213. This happens if we crashed before the app finished Commit
  214. If appBlockHeight == storeBlockHeight {
  215. update the state using the saved ABCI responses but dont run the block against the real app.
  216. This happens if we crashed after the app finished Commit but before Tendermint saved the state.