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