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.

685 lines
30 KiB

  1. ---
  2. order: 2
  3. title: Applications
  4. ---
  5. # Applications
  6. Please ensure you've first read the spec for [ABCI Methods and Types](abci.md)
  7. Here we cover the following components of ABCI applications:
  8. - [Connection State](#connection-state) - the interplay between ABCI connections and application state
  9. and the differences between `CheckTx` and `DeliverTx`.
  10. - [Transaction Results](#transaction-results) - rules around transaction
  11. results and validity
  12. - [Validator Set Updates](#validator-updates) - how validator sets are
  13. changed during `InitChain` and `EndBlock`
  14. - [Query](#query) - standards for using the `Query` method and proofs about the
  15. application state
  16. - [Crash Recovery](#crash-recovery) - handshake protocol to synchronize
  17. Tendermint and the application on startup.
  18. - [State Sync](#state-sync) - rapid bootstrapping of new nodes by restoring state machine snapshots
  19. ## Connection State
  20. Since Tendermint maintains four concurrent ABCI connections, it is typical
  21. for an application to maintain a distinct state for each, and for the states to
  22. be synchronized during `Commit`.
  23. ### Concurrency
  24. In principle, each of the four ABCI connections operate concurrently with one
  25. another. This means applications need to ensure access to state is
  26. thread safe. In practice, both the
  27. [default in-process ABCI client](https://github.com/tendermint/tendermint/blob/v0.34.4/abci/client/local_client.go#L18)
  28. and the
  29. [default Go ABCI
  30. server](https://github.com/tendermint/tendermint/blob/v0.34.4/abci/server/socket_server.go#L32)
  31. use global locks across all connections, so they are not
  32. concurrent at all. This means if your app is written in Go, and compiled in-process with Tendermint
  33. using the default `NewLocalClient`, or run out-of-process using the default `SocketServer`,
  34. ABCI messages from all connections will be linearizable (received one at a
  35. time).
  36. The existence of this global mutex means Go application developers can get
  37. thread safety for application state by routing *all* reads and writes through the ABCI
  38. system. Thus it may be *unsafe* to expose application state directly to an RPC
  39. interface, and unless explicit measures are taken, all queries should be routed through the ABCI Query method.
  40. ### BeginBlock
  41. The BeginBlock request can be used to run some code at the beginning of
  42. every block. It also allows Tendermint to send the current block hash
  43. and header to the application, before it sends any of the transactions.
  44. The app should remember the latest height and header (ie. from which it
  45. has run a successful Commit) so that it can tell Tendermint where to
  46. pick up from when it restarts. See information on the Handshake, below.
  47. ### Commit
  48. Application state should only be persisted to disk during `Commit`.
  49. Before `Commit` is called, Tendermint locks and flushes the mempool so that no new messages will
  50. be received on the mempool connection. This provides an opportunity to safely update all four connection
  51. states to the latest committed state at once.
  52. When `Commit` completes, it unlocks the mempool.
  53. WARNING: if the ABCI app logic processing the `Commit` message sends a
  54. `/broadcast_tx_sync` or `/broadcast_tx_commit` and waits for the response
  55. before proceeding, it will deadlock. Executing those `broadcast_tx` calls
  56. involves acquiring a lock that is held during the `Commit` call, so it's not
  57. possible. If you make the call to the `broadcast_tx` endpoints concurrently,
  58. that's no problem, it just can't be part of the sequential logic of the
  59. `Commit` function.
  60. ### Consensus Connection
  61. The Consensus Connection should maintain a `DeliverTxState` - the working state
  62. for block execution. It should be updated by the calls to `BeginBlock`, `DeliverTx`,
  63. and `EndBlock` during block execution and committed to disk as the "latest
  64. committed state" during `Commit`.
  65. Updates made to the `DeliverTxState` by each method call must be readable by each subsequent method -
  66. ie. the updates are linearizable.
  67. ### Mempool Connection
  68. The mempool Connection should maintain a `CheckTxState`
  69. to sequentially process pending transactions in the mempool that have
  70. not yet been committed. It should be initialized to the latest committed state
  71. at the end of every `Commit`.
  72. Before calling `Commit`, Tendermint will lock and flush the mempool connection,
  73. ensuring that all existing CheckTx are responded to and no new ones can begin.
  74. The `CheckTxState` may be updated concurrently with the `DeliverTxState`, as
  75. messages may be sent concurrently on the Consensus and Mempool connections.
  76. After `Commit`, while still holding the mempool lock, CheckTx is run again on all transactions that remain in the
  77. node's local mempool after filtering those included in the block.
  78. An additional `Type` parameter is made available to the CheckTx function that
  79. indicates whether an incoming transaction is new (`CheckTxType_New`), or a
  80. recheck (`CheckTxType_Recheck`).
  81. Finally, after re-checking transactions in the mempool, Tendermint will unlock
  82. the mempool connection. New transactions are once again able to be processed through CheckTx.
  83. Note that CheckTx is just a weak filter to keep invalid transactions out of the block chain.
  84. CheckTx doesn't have to check everything that affects transaction validity; the
  85. expensive things can be skipped. It's weak because a Byzantine node doesn't
  86. care about CheckTx; it can propose a block full of invalid transactions if it wants.
  87. #### Replay Protection
  88. To prevent old transactions from being replayed, CheckTx must implement
  89. replay protection.
  90. It is possible for old transactions to be sent to the application. So
  91. it is important CheckTx implements some logic to handle them.
  92. ### Query Connection
  93. The Info Connection should maintain a `QueryState` for answering queries from the user,
  94. and for initialization when Tendermint first starts up (both described further
  95. below).
  96. It should always contain the latest committed state associated with the
  97. latest committed block.
  98. `QueryState` should be set to the latest `DeliverTxState` at the end of every `Commit`,
  99. after the full block has been processed and the state committed to disk.
  100. Otherwise it should never be modified.
  101. Tendermint Core currently uses the Query connection to filter peers upon
  102. connecting, according to IP address or node ID. For instance,
  103. returning non-OK ABCI response to either of the following queries will
  104. cause Tendermint to not connect to the corresponding peer:
  105. - `p2p/filter/addr/<ip addr>`, where `<ip addr>` is an IP address.
  106. - `p2p/filter/id/<id>`, where `<is>` is the hex-encoded node ID (the hash of
  107. the node's p2p pubkey).
  108. Note: these query formats are subject to change!
  109. ### Snapshot Connection
  110. The Snapshot Connection is optional, and is only used to serve state sync snapshots for other nodes
  111. and/or restore state sync snapshots to a local node being bootstrapped.
  112. For more information, see [the state sync section of this document](#state-sync).
  113. ## Transaction Results
  114. The `Info` and `Log` fields are non-deterministic values for debugging/convenience purposes
  115. that are otherwise ignored.
  116. The `Data` field must be strictly deterministic, but can be arbitrary data.
  117. ### Gas
  118. Ethereum introduced the notion of `gas` as an abstract representation of the
  119. cost of resources used by nodes when processing transactions. Every operation in the
  120. Ethereum Virtual Machine uses some amount of gas, and gas can be accepted at a market-variable price.
  121. Users propose a maximum amount of gas for their transaction; if the tx uses less, they get
  122. the difference credited back. Tendermint adopts a similar abstraction,
  123. though uses it only optionally and weakly, allowing applications to define
  124. their own sense of the cost of execution.
  125. In Tendermint, the
  126. [ConsensusParams.Block.MaxGas](../../proto/tendermint/types/params.proto)
  127. limits the amount of `gas` that can be used in a block. The default value is
  128. `-1`, meaning no limit, or that the concept of gas is meaningless.
  129. Responses contain a `GasWanted` and `GasUsed` field. The former is the maximum
  130. amount of gas the sender of a tx is willing to use, and the later is how much it actually
  131. used. Applications should enforce that `GasUsed <= GasWanted` - ie. tx execution
  132. should halt before it can use more resources than it requested.
  133. When `MaxGas > -1`, Tendermint enforces the following rules:
  134. - `GasWanted <= MaxGas` for all txs in the mempool
  135. - `(sum of GasWanted in a block) <= MaxGas` when proposing a block
  136. If `MaxGas == -1`, no rules about gas are enforced.
  137. Note that Tendermint does not currently enforce anything about Gas in the consensus, only the mempool.
  138. This means it does not guarantee that committed blocks satisfy these rules!
  139. It is the application's responsibility to return non-zero response codes when gas limits are exceeded.
  140. The `GasUsed` field is ignored completely by Tendermint. That said, applications should enforce:
  141. - `GasUsed <= GasWanted` for any given transaction
  142. - `(sum of GasUsed in a block) <= MaxGas` for every block
  143. In the future, we intend to add a `Priority` field to the responses that can be
  144. used to explicitly prioritize txs in the mempool for inclusion in a block
  145. proposal. See [#1861](https://github.com/tendermint/tendermint/issues/1861).
  146. ### CheckTx
  147. If `Code != 0`, it will be rejected from the mempool and hence
  148. not broadcasted to other peers and not included in a proposal block.
  149. `Data` contains the result of the CheckTx transaction execution, if any. It is
  150. semantically meaningless to Tendermint.
  151. `Events` include any events for the execution, though since the transaction has not
  152. been committed yet, they are effectively ignored by Tendermint.
  153. ### DeliverTx
  154. DeliverTx is the workhorse of the blockchain. Tendermint sends the
  155. DeliverTx requests asynchronously but in order, and relies on the
  156. underlying socket protocol (ie. TCP) to ensure they are received by the
  157. app in order. They have already been ordered in the global consensus by
  158. the Tendermint protocol.
  159. If DeliverTx returns `Code != 0`, the transaction will be considered invalid,
  160. though it is still included in the block.
  161. DeliverTx also returns a [Code, Data, and Log](../../proto/tendermint/abci/types.proto#L189-L191).
  162. `Data` contains the result of the CheckTx transaction execution, if any. It is
  163. semantically meaningless to Tendermint.
  164. Both the `Code` and `Data` are included in a structure that is hashed into the
  165. `LastResultsHash` of the next block header.
  166. `Events` include any events for the execution, which Tendermint will use to index
  167. the transaction by. This allows transactions to be queried according to what
  168. events took place during their execution.
  169. ## Updating the Validator Set
  170. The application may set the validator set during InitChain, and may update it during
  171. EndBlock.
  172. Note that the maximum total power of the validator set is bounded by
  173. `MaxTotalVotingPower = MaxInt64 / 8`. Applications are responsible for ensuring
  174. they do not make changes to the validator set that cause it to exceed this
  175. limit.
  176. Additionally, applications must ensure that a single set of updates does not contain any duplicates -
  177. a given public key can only appear once within a given update. If an update includes
  178. duplicates, the block execution will fail irrecoverably.
  179. ### InitChain
  180. The `InitChain` method can return a list of validators.
  181. If the list is empty, Tendermint will use the validators loaded in the genesis
  182. file.
  183. If the list returned by `InitChain` is not empty, Tendermint will use its contents as the validator set.
  184. This way the application can set the initial validator set for the
  185. blockchain.
  186. ### EndBlock
  187. Updates to the Tendermint validator set can be made by returning
  188. `ValidatorUpdate` objects in the `ResponseEndBlock`:
  189. ```protobuf
  190. message ValidatorUpdate {
  191. tendermint.crypto.keys.PublicKey pub_key
  192. int64 power
  193. }
  194. message PublicKey {
  195. oneof {
  196. ed25519 bytes = 1;
  197. }
  198. ```
  199. The `pub_key` currently supports only one type:
  200. - `type = "ed25519"`
  201. The `power` is the new voting power for the validator, with the
  202. following rules:
  203. - power must be non-negative
  204. - if power is 0, the validator must already exist, and will be removed from the
  205. validator set
  206. - if power is non-0:
  207. - if the validator does not already exist, it will be added to the validator
  208. set with the given power
  209. - if the validator does already exist, its power will be adjusted to the given power
  210. - the total power of the new validator set must not exceed MaxTotalVotingPower
  211. Note the updates returned in block `H` will only take effect at block `H+2`.
  212. ## Consensus Parameters
  213. ConsensusParams enforce certain limits in the blockchain, like the maximum size
  214. of blocks, amount of gas used in a block, and the maximum acceptable age of
  215. evidence. They can be set in InitChain and updated in EndBlock.
  216. ### BlockParams.MaxBytes
  217. The maximum size of a complete Protobuf encoded block.
  218. This is enforced by Tendermint consensus.
  219. This implies a maximum transaction size that is this MaxBytes, less the expected size of
  220. the header, the validator set, and any included evidence in the block.
  221. Must have `0 < MaxBytes < 100 MB`.
  222. ### BlockParams.MaxGas
  223. The maximum of the sum of `GasWanted` that will be allowed in a proposed block.
  224. This is *not* enforced by Tendermint consensus.
  225. It is left to the app to enforce (ie. if txs are included past the
  226. limit, they should return non-zero codes). It is used by Tendermint to limit the
  227. txs included in a proposed block.
  228. Must have `MaxGas >= -1`.
  229. If `MaxGas == -1`, no limit is enforced.
  230. ### EvidenceParams.MaxAgeDuration
  231. This is the maximum age of evidence in time units.
  232. This is enforced by Tendermint consensus.
  233. If a block includes evidence older than this (AND the evidence was created more
  234. than `MaxAgeNumBlocks` ago), the block will be rejected (validators won't vote
  235. for it).
  236. Must have `MaxAgeDuration > 0`.
  237. ### EvidenceParams.MaxAgeNumBlocks
  238. This is the maximum age of evidence in blocks.
  239. This is enforced by Tendermint consensus.
  240. If a block includes evidence older than this (AND the evidence was created more
  241. than `MaxAgeDuration` ago), the block will be rejected (validators won't vote
  242. for it).
  243. Must have `MaxAgeNumBlocks > 0`.
  244. ### EvidenceParams.MaxNum
  245. This is the maximum number of evidence that can be committed to a single block.
  246. The product of this and the `MaxEvidenceBytes` must not exceed the size of
  247. a block minus it's overhead ( ~ `MaxBytes`).
  248. Must have `MaxNum > 0`.
  249. ### SynchronyParams.Precision
  250. `SynchronyParams.Precision` is a parameter of the Proposer-Based Timestamps algorithm.
  251. that configures the acceptable upper-bound of clock drift among
  252. all of the nodes on a Tendermint network. Any two nodes on a Tendermint network
  253. are expected to have clocks that differ by at most `Precision`.
  254. ### SynchronyParams.MessageDelay
  255. `SynchronyParams.MessageDelay` is a parameter of the Proposer-Based Timestamps
  256. algorithm that configures the acceptable upper-bound for transmitting a `Proposal`
  257. message from the proposer to all of the validators on the network.
  258. ### Updates
  259. The application may set the ConsensusParams during InitChain, and update them during
  260. EndBlock. If the ConsensusParams is empty, it will be ignored. Each field
  261. that is not empty will be applied in full. For instance, if updating the
  262. Block.MaxBytes, applications must also set the other Block fields (like
  263. Block.MaxGas), even if they are unchanged, as they will otherwise cause the
  264. value to be updated to 0.
  265. #### InitChain
  266. ResponseInitChain includes a ConsensusParams.
  267. If ConsensusParams is nil, Tendermint will use the params loaded in the genesis
  268. file. If ConsensusParams is not nil, Tendermint will use it.
  269. This way the application can determine the initial consensus params for the
  270. blockchain.
  271. #### EndBlock
  272. ResponseEndBlock includes a ConsensusParams.
  273. If ConsensusParams nil, Tendermint will do nothing.
  274. If ConsensusParam is not nil, Tendermint will use it.
  275. This way the application can update the consensus params over time.
  276. Note the updates returned in block `H` will take effect right away for block
  277. `H+1`.
  278. ## Query
  279. Query is a generic method with lots of flexibility to enable diverse sets
  280. of queries on application state. Tendermint makes use of Query to filter new peers
  281. based on ID and IP, and exposes Query to the user over RPC.
  282. Note that calls to Query are not replicated across nodes, but rather query the
  283. local node's state - hence they may return stale reads. For reads that require
  284. consensus, use a transaction.
  285. The most important use of Query is to return Merkle proofs of the application state at some height
  286. that can be used for efficient application-specific light-clients.
  287. Note Tendermint has technically no requirements from the Query
  288. message for normal operation - that is, the ABCI app developer need not implement
  289. Query functionality if they do not wish too.
  290. ### Query Proofs
  291. The Tendermint block header includes a number of hashes, each providing an
  292. anchor for some type of proof about the blockchain. The `ValidatorsHash` enables
  293. quick verification of the validator set, the `DataHash` gives quick
  294. verification of the transactions included in the block, etc.
  295. The `AppHash` is unique in that it is application specific, and allows for
  296. application-specific Merkle proofs about the state of the application.
  297. While some applications keep all relevant state in the transactions themselves
  298. (like Bitcoin and its UTXOs), others maintain a separated state that is
  299. computed deterministically *from* transactions, but is not contained directly in
  300. the transactions themselves (like Ethereum contracts and accounts).
  301. For such applications, the `AppHash` provides a much more efficient way to verify light-client proofs.
  302. ABCI applications can take advantage of more efficient light-client proofs for
  303. their state as follows:
  304. - return the Merkle root of the deterministic application state in
  305. `ResponseCommit.Data`. This Merkle root will be included as the `AppHash` in the next block.
  306. - return efficient Merkle proofs about that application state in `ResponseQuery.Proof`
  307. that can be verified using the `AppHash` of the corresponding block.
  308. For instance, this allows an application's light-client to verify proofs of
  309. absence in the application state, something which is much less efficient to do using the block hash.
  310. Some applications (eg. Ethereum, Cosmos-SDK) have multiple "levels" of Merkle trees,
  311. where the leaves of one tree are the root hashes of others. To support this, and
  312. the general variability in Merkle proofs, the `ResponseQuery.Proof` has some minimal structure:
  313. ```protobuf
  314. message ProofOps {
  315. repeated ProofOp ops
  316. }
  317. message ProofOp {
  318. string type = 1;
  319. bytes key = 2;
  320. bytes data = 3;
  321. }
  322. ```
  323. Each `ProofOp` contains a proof for a single key in a single Merkle tree, of the specified `type`.
  324. This allows ABCI to support many different kinds of Merkle trees, encoding
  325. formats, and proofs (eg. of presence and absence) just by varying the `type`.
  326. The `data` contains the actual encoded proof, encoded according to the `type`.
  327. When verifying the full proof, the root hash for one ProofOp is the value being
  328. verified for the next ProofOp in the list. The root hash of the final ProofOp in
  329. the list should match the `AppHash` being verified against.
  330. ### Peer Filtering
  331. When Tendermint connects to a peer, it sends two queries to the ABCI application
  332. using the following paths, with no additional data:
  333. - `/p2p/filter/addr/<IP:PORT>`, where `<IP:PORT>` denote the IP address and
  334. the port of the connection
  335. - `p2p/filter/id/<ID>`, where `<ID>` is the peer node ID (ie. the
  336. pubkey.Address() for the peer's PubKey)
  337. If either of these queries return a non-zero ABCI code, Tendermint will refuse
  338. to connect to the peer.
  339. ### Paths
  340. Queries are directed at paths, and may optionally include additional data.
  341. The expectation is for there to be some number of high level paths
  342. differentiating concerns, like `/p2p`, `/store`, and `/app`. Currently,
  343. Tendermint only uses `/p2p`, for filtering peers. For more advanced use, see the
  344. implementation of
  345. [Query in the Cosmos-SDK](https://github.com/cosmos/cosmos-sdk/blob/v0.23.1/baseapp/baseapp.go#L333).
  346. ## Crash Recovery
  347. On startup, Tendermint calls the `Info` method on the Info Connection to get the latest
  348. committed state of the app. The app MUST return information consistent with the
  349. last block it succesfully completed Commit for.
  350. If the app succesfully committed block H, then `last_block_height = H` and `last_block_app_hash = <hash returned by Commit for block H>`. If the app
  351. failed during the Commit of block H, then `last_block_height = H-1` and
  352. `last_block_app_hash = <hash returned by Commit for block H-1, which is the hash in the header of block H>`.
  353. We now distinguish three heights, and describe how Tendermint syncs itself with
  354. the app.
  355. ```md
  356. storeBlockHeight = height of the last block Tendermint saw a commit for
  357. stateBlockHeight = height of the last block for which Tendermint completed all
  358. block processing and saved all ABCI results to disk
  359. appBlockHeight = height of the last block for which ABCI app succesfully
  360. completed Commit
  361. ```
  362. Note we always have `storeBlockHeight >= stateBlockHeight` and `storeBlockHeight >= appBlockHeight`
  363. Note also Tendermint never calls Commit on an ABCI app twice for the same height.
  364. The procedure is as follows.
  365. First, some simple start conditions:
  366. If `appBlockHeight == 0`, then call InitChain.
  367. If `storeBlockHeight == 0`, we're done.
  368. Now, some sanity checks:
  369. If `storeBlockHeight < appBlockHeight`, error
  370. If `storeBlockHeight < stateBlockHeight`, panic
  371. If `storeBlockHeight > stateBlockHeight+1`, panic
  372. Now, the meat:
  373. If `storeBlockHeight == stateBlockHeight && appBlockHeight < storeBlockHeight`,
  374. replay all blocks in full from `appBlockHeight` to `storeBlockHeight`.
  375. This happens if we completed processing the block, but the app forgot its height.
  376. If `storeBlockHeight == stateBlockHeight && appBlockHeight == storeBlockHeight`, we're done.
  377. This happens if we crashed at an opportune spot.
  378. If `storeBlockHeight == stateBlockHeight+1`
  379. This happens if we started processing the block but didn't finish.
  380. If `appBlockHeight < stateBlockHeight`
  381. replay all blocks in full from `appBlockHeight` to `storeBlockHeight-1`,
  382. and replay the block at `storeBlockHeight` using the WAL.
  383. This happens if the app forgot the last block it committed.
  384. If `appBlockHeight == stateBlockHeight`,
  385. replay the last block (storeBlockHeight) in full.
  386. This happens if we crashed before the app finished Commit
  387. If `appBlockHeight == storeBlockHeight`
  388. update the state using the saved ABCI responses but dont run the block against the real app.
  389. This happens if we crashed after the app finished Commit but before Tendermint saved the state.
  390. ## State Sync
  391. A new node joining the network can simply join consensus at the genesis height and replay all
  392. historical blocks until it is caught up. However, for large chains this can take a significant
  393. amount of time, often on the order of days or weeks.
  394. State sync is an alternative mechanism for bootstrapping a new node, where it fetches a snapshot
  395. of the state machine at a given height and restores it. Depending on the application, this can
  396. be several orders of magnitude faster than replaying blocks.
  397. Note that state sync does not currently backfill historical blocks, so the node will have a
  398. truncated block history - users are advised to consider the broader network implications of this in
  399. terms of block availability and auditability. This functionality may be added in the future.
  400. For details on the specific ABCI calls and types, see the [methods and types section](abci.md).
  401. ### Taking Snapshots
  402. Applications that want to support state syncing must take state snapshots at regular intervals. How
  403. this is accomplished is entirely up to the application. A snapshot consists of some metadata and
  404. a set of binary chunks in an arbitrary format:
  405. - `Height (uint64)`: The height at which the snapshot is taken. It must be taken after the given
  406. height has been committed, and must not contain data from any later heights.
  407. - `Format (uint32)`: An arbitrary snapshot format identifier. This can be used to version snapshot
  408. formats, e.g. to switch from Protobuf to MessagePack for serialization. The application can use
  409. this when restoring to choose whether to accept or reject a snapshot.
  410. - `Chunks (uint32)`: The number of chunks in the snapshot. Each chunk contains arbitrary binary
  411. data, and should be less than 16 MB; 10 MB is a good starting point.
  412. - `Hash ([]byte)`: An arbitrary hash of the snapshot. This is used to check whether a snapshot is
  413. the same across nodes when downloading chunks.
  414. - `Metadata ([]byte)`: Arbitrary snapshot metadata, e.g. chunk hashes for verification or any other
  415. necessary info.
  416. For a snapshot to be considered the same across nodes, all of these fields must be identical. When
  417. sent across the network, snapshot metadata messages are limited to 4 MB.
  418. When a new node is running state sync and discovering snapshots, Tendermint will query an existing
  419. application via the ABCI `ListSnapshots` method to discover available snapshots, and load binary
  420. snapshot chunks via `LoadSnapshotChunk`. The application is free to choose how to implement this
  421. and which formats to use, but must provide the following guarantees:
  422. - **Consistent:** A snapshot must be taken at a single isolated height, unaffected by
  423. concurrent writes. This can be accomplished by using a data store that supports ACID
  424. transactions with snapshot isolation.
  425. - **Asynchronous:** Taking a snapshot can be time-consuming, so it must not halt chain progress,
  426. for example by running in a separate thread.
  427. - **Deterministic:** A snapshot taken at the same height in the same format must be identical
  428. (at the byte level) across nodes, including all metadata. This ensures good availability of
  429. chunks, and that they fit together across nodes.
  430. A very basic approach might be to use a datastore with MVCC transactions (such as RocksDB),
  431. start a transaction immediately after block commit, and spawn a new thread which is passed the
  432. transaction handle. This thread can then export all data items, serialize them using e.g.
  433. Protobuf, hash the byte stream, split it into chunks, and store the chunks in the file system
  434. along with some metadata - all while the blockchain is applying new blocks in parallel.
  435. A more advanced approach might include incremental verification of individual chunks against the
  436. chain app hash, parallel or batched exports, compression, and so on.
  437. Old snapshots should be removed after some time - generally only the last two snapshots are needed
  438. (to prevent the last one from being removed while a node is restoring it).
  439. ### Bootstrapping a Node
  440. An empty node can be state synced by setting the configuration option `statesync.enabled =
  441. true`. The node also needs the chain genesis file for basic chain info, and configuration for
  442. light client verification of the restored snapshot: a set of Tendermint RPC servers, and a
  443. trusted header hash and corresponding height from a trusted source, via the `statesync`
  444. configuration section.
  445. Once started, the node will connect to the P2P network and begin discovering snapshots. These
  446. will be offered to the local application via the `OfferSnapshot` ABCI method. Once a snapshot
  447. is accepted Tendermint will fetch and apply the snapshot chunks. After all chunks have been
  448. successfully applied, Tendermint verifies the app's `AppHash` against the chain using the light
  449. client, then switches the node to normal consensus operation.
  450. #### Snapshot Discovery
  451. When the empty node join the P2P network, it asks all peers to report snapshots via the
  452. `ListSnapshots` ABCI call (limited to 10 per node). After some time, the node picks the most
  453. suitable snapshot (generally prioritized by height, format, and number of peers), and offers it
  454. to the application via `OfferSnapshot`. The application can choose a number of responses,
  455. including accepting or rejecting it, rejecting the offered format, rejecting the peer who sent
  456. it, and so on. Tendermint will keep discovering and offering snapshots until one is accepted or
  457. the application aborts.
  458. #### Snapshot Restoration
  459. Once a snapshot has been accepted via `OfferSnapshot`, Tendermint begins downloading chunks from
  460. any peers that have the same snapshot (i.e. that have identical metadata fields). Chunks are
  461. spooled in a temporary directory, and then given to the application in sequential order via
  462. `ApplySnapshotChunk` until all chunks have been accepted.
  463. The method for restoring snapshot chunks is entirely up to the application.
  464. During restoration, the application can respond to `ApplySnapshotChunk` with instructions for how
  465. to continue. This will typically be to accept the chunk and await the next one, but it can also
  466. ask for chunks to be refetched (either the current one or any number of previous ones), P2P peers
  467. to be banned, snapshots to be rejected or retried, and a number of other responses - see the ABCI
  468. reference for details.
  469. If Tendermint fails to fetch a chunk after some time, it will reject the snapshot and try a
  470. different one via `OfferSnapshot` - the application can choose whether it wants to support
  471. restarting restoration, or simply abort with an error.
  472. #### Snapshot Verification
  473. Once all chunks have been accepted, Tendermint issues an `Info` ABCI call to retrieve the
  474. `LastBlockAppHash`. This is compared with the trusted app hash from the chain, retrieved and
  475. verified using the light client. Tendermint also checks that `LastBlockHeight` corresponds to the
  476. height of the snapshot.
  477. This verification ensures that an application is valid before joining the network. However, the
  478. snapshot restoration may take a long time to complete, so applications may want to employ additional
  479. verification during the restore to detect failures early. This might e.g. include incremental
  480. verification of each chunk against the app hash (using bundled Merkle proofs), checksums to
  481. protect against data corruption by the disk or network, and so on. However, it is important to
  482. note that the only trusted information available is the app hash, and all other snapshot metadata
  483. can be spoofed by adversaries.
  484. Apps may also want to consider state sync denial-of-service vectors, where adversaries provide
  485. invalid or harmful snapshots to prevent nodes from joining the network. The application can
  486. counteract this by asking Tendermint to ban peers. As a last resort, node operators can use
  487. P2P configuration options to whitelist a set of trusted peers that can provide valid snapshots.
  488. #### Transition to Consensus
  489. Once the snapshots have all been restored, Tendermint gathers additional information necessary for
  490. bootstrapping the node (e.g. chain ID, consensus parameters, validator sets, and block headers)
  491. from the genesis file and light client RPC servers. It also fetches and records the `AppVersion`
  492. from the ABCI application.
  493. Once the state machine has been restored and Tendermint has gathered this additional
  494. information, it transitions to block sync (if enabled) to fetch any remaining blocks up the chain
  495. head, and then transitions to regular consensus operation. At this point the node operates like
  496. any other node, apart from having a truncated block history at the height of the restored snapshot.