--- order: 1 title: Basic concepts and definitions --- # Basic concepts and definitions ## Connections ABCI++ applications can run either within the _same_ process as the Tendermint state-machine replication engine, or as a _separate_ process from the state-machine replication engine. When run within the same process, Tendermint will call the ABCI++ application methods directly as Go method calls. When Tendermint and the ABCI++ application are run as separate processes, Tendermint opens four connections to the application for ABCI++ methods. The connections each handle a subset of the ABCI++ method calls. These subsets are defined as follows: ### **Consensus** connection * Driven by a consensus protocol and is responsible for block execution. * Handles the `InitChain`, `PrepareProposal`, `ProcessProposal`, `ExtendVote`, `VerifyVoteExtension`, and `FinalizeBlock` method calls. ### **Mempool** connection * For validating new transactions, before they're shared or included in a block. * Handles the `CheckTx` calls. ### **Info** connection * For initialization and for queries from the user. * Handles the `Info` and `Query` calls. ### **Snapshot** connection * For serving and restoring [state sync snapshots](../abci/apps.md#state-sync). * Handles the `ListSnapshots`, `LoadSnapshotChunk`, `OfferSnapshot`, and `ApplySnapshotChunk` calls. Additionally, there is a `Flush` method that is called on every connection, and an `Echo` method that is just for debugging. >**TODO** Figure out what to do with this. More details on managing state across connections can be found in the section on [ABCI Applications](../abci/apps.md). ## Errors The `Query`, and `CheckTx` methods include a `Code` field in their `Response*`. The `Code` field is also included in type `TxResult`, used by method `FinalizeBlock`'s `Response*`. Field `Code` is meant to contain an application-specific response code. A response code of `0` indicates no error. Any other response code indicates to Tendermint that an error occurred. These methods also return a `Codespace` string to Tendermint. This field is used to disambiguate `Code` values returned by different domains of the Application. The `Codespace` is a namespace for the `Code`. Methods `Echo`, `Info`, and `InitChain` do not return errors. An error in any of these methods represents a critical issue that Tendermint has no reasonable way to handle. If there is an error in one of these methods, the Application must crash to ensure that the error is safely handled by an operator. Method `FinalizeBlock` is a special case. It contains a number of `Code` and `Codespace` fields as part of type `TxResult`. Each of these codes reports errors related to the transaction it is attached to. However, `FinalizeBlock` does not return errors at the top level, so the same considerations on critical issues made for `Echo`, `Info`, and `InitChain` also apply here. The handling of non-zero response codes by Tendermint is described below ### `CheckTx` The `CheckTx` ABCI++ method controls what transactions are considered for inclusion in a block. When Tendermint receives a `ResponseCheckTx` with a non-zero `Code`, the associated transaction will not be added to Tendermint's mempool or it will be removed if it is already included. ### `TxResult` (as part of `FinalizeBlock`) The `TxResult` type delivers transactions from Tendermint to the Application. When Tendermint receives a `ResponseFinalizeBlock` containing a `TxResult` with a non-zero `Code`, the response code is logged. The transaction was already included in a block, so the `Code` does not influence Tendermint consensus. ### `Query` The `Query` ABCI++ method queries the Application for information about application state. When Tendermint receives a `ResponseQuery` with a non-zero `Code`, this code is returned directly to the client that initiated the query. ## Events Method `CheckTx` includes an `Events` field in its `Response*`. Method `FinalizeBlock` includes an `Events` field at the top level in its `Response*`, and one `events` field per transaction included in the block. Applications may respond to these ABCI++ methods with a set of events. Events allow applications to associate metadata about ABCI++ method execution with the transactions and blocks this metadata relates to. Events returned via these ABCI++ methods do not impact Tendermint consensus in any way and instead exist to power subscriptions and queries of Tendermint state. An `Event` contains a `type` and a list of `EventAttributes`, which are key-value string pairs denoting metadata about what happened during the method's (or transaction's) execution. `Event` values can be used to index transactions and blocks according to what happened during their execution. Each event has a `type` which is meant to categorize the event for a particular `Response*` or `Tx`. A `Response*` or `Tx` may contain multiple events with duplicate `type` values, where each distinct entry is meant to categorize attributes for a particular event. Every key and value in an event's attributes must be UTF-8 encoded strings along with the event type itself. ```protobuf message Event { string type = 1; repeated EventAttribute attributes = 2; } ``` The attributes of an `Event` consist of a `key`, a `value`, and an `index` flag. The index flag notifies the Tendermint indexer to index the attribute. The value of the `index` flag is non-deterministic and may vary across different nodes in the network. ```protobuf message EventAttribute { bytes key = 1; bytes value = 2; bool index = 3; // nondeterministic } ``` Example: ```go abci.ResponseCheckTx{ // ... Events: []abci.Event{ { Type: "validator.provisions", Attributes: []abci.EventAttribute{ abci.EventAttribute{Key: []byte("address"), Value: []byte("..."), Index: true}, abci.EventAttribute{Key: []byte("amount"), Value: []byte("..."), Index: true}, abci.EventAttribute{Key: []byte("balance"), Value: []byte("..."), Index: true}, }, }, { Type: "validator.provisions", Attributes: []abci.EventAttribute{ abci.EventAttribute{Key: []byte("address"), Value: []byte("..."), Index: true}, abci.EventAttribute{Key: []byte("amount"), Value: []byte("..."), Index: false}, abci.EventAttribute{Key: []byte("balance"), Value: []byte("..."), Index: false}, }, }, { Type: "validator.slashed", Attributes: []abci.EventAttribute{ abci.EventAttribute{Key: []byte("address"), Value: []byte("..."), Index: false}, abci.EventAttribute{Key: []byte("amount"), Value: []byte("..."), Index: true}, abci.EventAttribute{Key: []byte("reason"), Value: []byte("..."), Index: true}, }, }, // ... }, } ``` ## EvidenceType Tendermint's security model relies on the use of "evidence". Evidence is proof of malicious behaviour by a network participant. It is the responsibility of Tendermint to detect such malicious behaviour. When malicious behavior is detected, Tendermint will gossip evidence of the behavior to other nodes and commit the evidence to the chain once it is verified by all validators. This evidence will then be passed on to the Application through ABCI++. It is the responsibility of the Application to handle the evidence and exercise punishment. EvidenceType has the following protobuf format: ```protobuf enum EvidenceType { UNKNOWN = 0; DUPLICATE_VOTE = 1; LIGHT_CLIENT_ATTACK = 2; } ``` There are two forms of evidence: Duplicate Vote and Light Client Attack. More information can be found in either [data structures](../core/data_structures.md) or [accountability](../light-client/accountability/) ## Vote Extensions According to the Tendermint algorithm, a proposed block needs at least a predefined number of precommit votes in order to be decided. Tendermint gathers all the valid precommit votes for the decided block that it receives before the block is decided, and then includes these votes in the proposed block for the next height whenever the local process is the proposer of the round. When Tendermint's consensus is about to send a non-`nil` precommit message, it calls method `ExtendVote`, which gives the Application the opportunity to include non-deterministic data, opaque to Tendermint, that will be attached to the precommit message. The data, called _vote extension_, will also be made available to the application in the next height, along with the vote it is extending, in the rounds where the local process is the proposer. The vote extension data is split into two parts, one signed by Tendermint as part of the vote data structure, and the other (optionally) signed by the Application. The Application may also choose not to include any vote extension. When another process receives a precommit message with a vote extension, it calls method `VerifyVoteExtension` so that the Application can validate the data received. If the validation fails, the precommit message will be deemed invalid and ignored by Tendermint. This has negative impact on Tendermint's liveness, i.e., if repeatedly vote extensions by correct validators cannot be verified by correct validators, Tendermint may not be able to finalize a block even if sufficiently many (+2/3) of the validators send precommit votes for that block. Thus, `VerifyVoteExtension` should only be used with special care. As a general rule, an Application that detects an invalid vote extension SHOULD accept it in `ResponseVerifyVoteExtension` and ignore it in its own logic. ## Determinism ABCI++ applications must implement deterministic finite-state machines to be securely replicated by the Tendermint consensus engine. This means block execution over the Consensus Connection must be strictly deterministic: given the same ordered set of requests, all nodes will compute identical responses, for all successive `FinalizeBlock` calls. This is critical, because the responses are included in the header of the next block, either via a Merkle root or directly, so all nodes must agree on exactly what they are. For this reason, it is recommended that applications not be exposed to any external user or process except via the ABCI connections to a consensus engine like Tendermint Core. The Application must only change its state based on input from block execution (`FinalizeBlock` calls), and not through any other kind of request. This is the only way to ensure all nodes see the same transactions and compute the same results. Some Applications may choose to execute the blocks that are about to be proposed (via `PrepareProposal`), or those that the Application is asked to validate (via `Processproposal`). However the state changes caused by processing those proposed blocks must never replace the previous state until `FinalizeBlock` confirms the block decided. Additionally, vote extensions or the validation thereof (via `ExtendVote` or `VerifyVoteExtension`) must _never_ have side effects on the current state. They can only be used when their data is included in a block. If there is some non-determinism in the state machine, consensus will eventually fail as nodes disagree over the correct values for the block header. The non-determinism must be fixed and the nodes restarted. Sources of non-determinism in applications may include: * Hardware failures * Cosmic rays, overheating, etc. * Node-dependent state * Random numbers * Time * Underspecification * Library version changes * Race conditions * Floating point numbers * JSON or protobuf serialization * Iterating through hash-tables/maps/dictionaries * External Sources * Filesystem * Network calls (eg. some external REST API service) See [#56](https://github.com/tendermint/abci/issues/56) for original discussion. Note that some methods (`Query, CheckTx, FinalizeBlock`) return explicitly non-deterministic data in the form of `Info` and `Log` fields. The `Log` is intended for the literal output from the Application's logger, while the `Info` is any additional info that should be returned. These are the only fields that are not included in block header computations, so we don't need agreement on them. All other fields in the `Response*` must be strictly deterministic. ## Block Execution The first time a new blockchain is started, Tendermint calls `InitChain`. From then on, method `FinalizeBlock` is executed at the end of each block, resulting in an updated Application state. During consensus execution of a block height, before method `FinalizeBlock` is called, methods `PrepareProposal`, `ProcessProposal`, `ExtendVote`, and `VerifyVoteExtension` may be called a number of times. See [Tendermint's expected behavior](abci++_tmint_expected_behavior_002_draft.md) for details on the possible call sequences of these methods. Method `PrepareProposal` is called every time Tendermint is about to send a proposal message, but no previous proposal has been locked at Tendermint level. Tendermint gathers outstanding transactions from the mempool (see [PrepareProposal](#PrepareProposal)), generates a block header and uses them to create a block to propose. Then, it calls `RequestPrepareProposal` with the newly created proposal, called _raw proposal_. The Application can make changes to the raw proposal, such as modifying transactions, and returns the (potentially) modified proposal, called _prepared proposal_ in the `Response*` call. The logic modifying the raw proposal can be non-deterministic. When Tendermint receives a prepared proposal it uses method `ProcessProposal` to inform the Application of the proposal just received. The Application cannot modify the proposal at this point but can reject it if it realises it is invalid. If that is the case, Tendermint will prevote `nil` on the proposal, which has strong liveness implications for Tendermint. As a general rule, the Application SHOULD accept a prepared proposal passed via `ProcessProposal`, even if a part of the proposal is invalid (e.g., an invalid transaction); the Application can later ignore the invalid part of the prepared proposal at block execution time. Cryptographic commitments to the block and transaction results, via the corresponding parameters in `FinalizeBlockResponse` are included in the header of the next block. ## Next-block execution and same-block execution With ABCI++ predecessor, ABCI, the only moment when the Application had access to a block was when it was decided. This led to a block execution model, called _next-block execution_, where some fields hashed in a block header refer to the execution of the previous block, namely: * the merkle root of the Application's state * the transaction results * the consensus parameter updates * the validator updates With ABCI++, an Application may decide to keep using the next-block execution model; however the new methods introduced, `PrepareProposal` and `ProcessProposal` allow for a new execution model, called _same-block execution_. An Application implementing this execution model, upon receiving a raw proposal via `RequestPrepareProposal` and potentially modifying its transaction list, fully executes the resulting prepared proposal as though it was the decided block. The results of the block execution are used as follows: * the Application keeps the events generated and provides them if `FinalizeBlock` is finally called on this prepared proposal. * the merkle root resulting from executing the prepared proposal is provided in `ResponsePrepareProposal` and thus refers to the **current block**. Tendermint will use it in the prepared proposal's header. * likewise, the transaction results from executing the prepared proposal are provided in `ResponsePrepareProposal` and refer to the transactions in the **current block**. Tendermint will use them to calculate the results hash in the prepared proposal's header. * the consensus parameter updates and validator updates are also provided in `ResponsePrepareProposal` and reflect the result of the prepared proposal's execution. They come into force in height H+1 (as opposed to the H+2 rule in next-block execution model). If the Application decides to keep the next-block execution model, it will not provide any data in `ResponsePrepareProposal`, other than an optionally modified transaction list. In the long term, the execution model will be set in a new boolean parameter *same_block* in `ConsensusParams`. It should **not** be changed once the blockchain has started, unless the Application developers _really_ know what they are doing. However, modifying `ConsensusParams` structure cannot be done lightly if we are to preserve blockchain compatibility. Therefore we need an interim solution until soft upgrades are specified and implemented in Tendermint. This somewhat _unsafe_ solution consists in Tendermint assuming same-block execution if the Application fills the above mentioned fields in `ResponsePrepareProposal`. ## Tendermint timeouts in same-block execution The new same-block execution mode requires the Application to fully execute the prepared block at `PrepareProposal` time. This execution is synchronous, so Tendermint cannot make progress until the Application returns from `PrepareProposal`. This stands on Tendermint's critical path: if the Application takes a long time executing the block, the default value of _TimeoutPropose_ might not be sufficient to accomodate the long block execution time and non-proposer processes might time out and prevote `nil`, thus starting a further round unnecessarily. The Application is the best suited to provide a value for _TimeoutPropose_ so that the block execution time upon `PrepareProposal` fits well in the propose timeout interval. Currently, the Application can override the value of _TimeoutPropose_ via the `config.toml` file. In the future, `ConsensusParams` may have an extra field with the current _TimeoutPropose_ value so that the Application has the possibility to adapt it at every height. ## State Sync State sync allows new nodes to rapidly bootstrap by discovering, fetching, and applying state machine snapshots instead of replaying historical blocks. For more details, see the [state sync section](../p2p/messages/state-sync.md). New nodes will discover and request snapshots from other nodes in the P2P network. A Tendermint node that receives a request for snapshots from a peer will call `ListSnapshots` on its Application to retrieve any local state snapshots. After receiving snapshots from peers, the new node will offer each snapshot received from a peer to its local Application via the `OfferSnapshot` method. Snapshots may be quite large and are thus broken into smaller "chunks" that can be assembled into the whole snapshot. Once the Application accepts a snapshot and begins restoring it, Tendermint will fetch snapshot "chunks" from existing nodes. The node providing "chunks" will fetch them from its local Application using the `LoadSnapshotChunk` method. As the new node receives "chunks" it will apply them sequentially to the local application with `ApplySnapshotChunk`. When all chunks have been applied, the Application's `AppHash` is retrieved via an `Info` query. The `AppHash` is then compared to the blockchain's `AppHash` which is verified via [light client verification](../light-client/verification/README.md).