spec: abci++ cleanup for v0.37 (#9288)

* v0.36 abci++ spec

* Basic concepts cleanup

* Resurrected beginBlock to EndBlock sequence

* Global Lock in Concurrency

* ResponseProcessProposal returns list of bytes

* Fixed broken links; added ExtendedCommitInfo and ExtendedVoteInfo

* Replace spec/abci with abci++ content

* Removed spec/abci

Co-authored-by: Sergio Mena <sergio@informal.systems>
Co-authored-by: Thane Thomson <connect@thanethomson.com>
This commit is contained in:
Jasmina Malicevic
2022-09-02 09:58:10 +02:00
committed by GitHub
parent b055535397
commit 6371f02810
9 changed files with 2841 additions and 1581 deletions

View File

@@ -1,29 +1,39 @@
---
order: 1
parent:
title: ABCI
order: 2
title: ABCI++
order: 3
---
# ABCI
# ABCI++
ABCI stands for "**A**pplication **B**lock**c**hain **I**nterface".
ABCI is the interface between Tendermint (a state-machine replication engine)
and your application (the actual state machine). It consists of a set of
_methods_, each with a corresponding `Request` and `Response`message type.
To perform state-machine replication, Tendermint calls the ABCI methods on the
ABCI application by sending the `Request*` messages and receiving the `Response*` messages in return.
## Introduction
All ABCI messages and methods are defined in [protocol
buffers](https://github.com/tendermint/tendermint/blob/main/proto/tendermint/abci/types.proto).
This allows Tendermint to run with applications written in many programming
languages.
ABCI++ is a major evolution of ABCI (**A**pplication **B**lock**c**hain **I**nterface).
Like its predecessor, ABCI++ is the interface between Tendermint (a state-machine
replication engine) and the actual state machine being replicated (i.e., the Application).
The API consists of a set of _methods_, each with a corresponding `Request` and `Response`
message type.
The methods are always initiated by Tendermint. The Application implements its logic
for handling all ABCI++ methods.
Thus, Tendermint always sends the `Request*` messages and receives the `Response*` messages
in return.
All ABCI++ messages and methods are defined in [protocol buffers](../../proto/tendermint/abci/types.proto).
This allows Tendermint to run with applications written in many programming languages.
This specification is split as follows:
- [Methods and Types](./abci.md) - complete details on all ABCI methods and
message types
- [Applications](./apps.md) - how to manage ABCI application state and other
details about building ABCI applications
- [Client and Server](./client-server.md) - for those looking to implement their
- [Overview and basic concepts](./abci++_basic_concepts.md) - interface's overview and concepts
needed to understand other parts of this specification.
- [Methods](./abci++_methods.md) - complete details on all ABCI++ methods
and message types.
- [Requirements for the Application](./abci++_app_requirements.md) - formal requirements
on the Application's logic to ensure Tendermint properties such as liveness. These requirements define what
Tendermint expects from the Application; second part on managing ABCI application state and related topics.
- [Tendermint's expected behavior](./abci++_tmint_expected_behavior.md) - specification of
how the different ABCI++ methods may be called by Tendermint. This explains what the Application
is to expect from Tendermint.
- [Client and Server](abci++_client_server.md) - for those looking to implement their
own ABCI application servers

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,451 @@
---
order: 1
title: Overview and basic concepts
---
## Outline
- [Overview and basic concepts](#overview-and-basic-concepts)
- [ABCI++ vs. ABCI](#abci-vs-abci)
- [Method overview](#method-overview)
- [Consensus/block execution methods](#consensusblock-execution-methods)
- [Mempool methods](#mempool-methods)
- [Info methods](#info-methods)
- [State-sync methods](#state-sync-methods)
- [Other methods](#other-methods)
- [Tendermint proposal timeout](#tendermint-proposal-timeout)
- [Deterministic State-Machine Replication](#deterministic-state-machine-replication)
- [Events](#events)
- [Evidence](#evidence)
- [Errors](#errors)
- [`CheckTx`](#checktx)
- [`DeliverTx`](#delivertx)
- [`Query`](#query)
# Overview and basic concepts
## ABCI++ vs. ABCI
[&uparrow; Back to Outline](#outline)
The Application's main role is to execute blocks decided (a.k.a. finalized) by consensus. The
decided blocks are the consensus's main ouput to the (replicated) Application. With ABCI, the
application only interacts with consensus at *decision* time. This restricted mode of interaction
prevents numerous features for the Application, including many scalability improvements that are
now better understood than when ABCI was first written. For example, many ideas proposed to improve
scalability can be boiled down to "make the block proposers do work, so the network does not have
to". This includes optimizations such as transaction level signature aggregation, state transition
proofs, etc. Furthermore, many new security properties cannot be achieved in the current paradigm,
as the Application cannot require validators to do more than executing the transactions contained in
finalized blocks. This includes features such as threshold cryptography, and guaranteed IBC
connection attempts.
ABCI++ addresses these limitations by allowing the application to intervene at two key places of
consensus execution: (a) at the moment a new proposal is to be created and (b) at the moment a
proposal is to be validated. The new interface allows block proposers to perform application-dependent
work in a block through the `PrepareProposal` method (a); and validators to perform application-dependent work
and checks in a proposed block through the `ProcessProposal` method (b).
<!-- Furthermore, ABCI++ coalesces {`BeginBlock`, [`DeliverTx`], `EndBlock`} into `FinalizeBlock`, as a
simplified, efficient way to deliver a decided block to the Application. -->
We plan to extend this to allow applications to intervene at the moment a (precommit) vote is sent/received.
The applications could then require their validators to do more than just validating blocks through the `ExtendVote`
and `VerifyVoteExtension` methods.
## Method overview
[&uparrow; Back to Outline](#outline)
Methods can be classified into four categories: *consensus*, *mempool*, *info*, and *state-sync*.
### Consensus/block execution methods
The first time a new blockchain is started, Tendermint calls `InitChain`. From then on, methods `BeginBlock`,
`DeliverTx` and `EndBlock` are executed upon the decision of each block, resulting in an updated Application
state. One `DeliverTx` is called for each transaction in the block. The result is an updated application state.
Cryptographic commitments to the results of `DeliverTx`, and an application-provided hash in `Commit` are included in the header of the next block. During the execution of an instance of consensus, which decides the block for a given
height, and before method `BeginBlock` is called, methods `PrepareProposal` and `ProcessProposal`,
may be called several times. See
[Tendermint's expected behavior](abci++_tmint_expected_behavior.md) for details on the possible
call sequences of these methods.
- [**InitChain:**](./abci++_methods.md#initchain) This method initializes the blockchain.
Tendermint calls it once upon genesis.
- [**PrepareProposal:**](./abci++_methods.md#prepareproposal) It allows the block
proposer to perform application-dependent work in a block before proposing it.
This enables, for instance, batch optimizations to a block, which has been empirically
demonstrated to be a key component for improved performance. Method `PrepareProposal` is called
every time Tendermint is about to broadcast a Proposal message, but no previous proposal has
been locked at Tendermint level. Tendermint gathers outstanding transactions from the
mempool, 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 `ResponsePrepareProposal`
call. The logic modifying the raw proposal can be non-deterministic.
- [**ProcessProposal:**](./abci++_methods.md#processproposal) It allows a validator to
perform application-dependent work in a proposed block. This enables features such as immediate
block execution, and allows the Application to reject invalid blocks.
Tendermint calls it when it receives a proposal and the Tendermint algorithm has not locked on a
value. The Application cannot modify the proposal at this point but can reject it if 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
ignore the invalid part of the prepared proposal at block execution time.
- [**BeginBlock:**](./abci++_methods.md#beginblock) Is called exactly once after a block has been decided
and executes once before all `DeliverTx` method calls.
- [**DeliverTx**](./abci++_methods.md#delivertx) Upon completion of `BeginBlock`,
`DeliverTx` is called once
for each of the transactions within the block. The application defines further checks to confirm their
validity - for example a key-value store might verify that the key does not already exist. Note that
even if a transaction does not pass the check in `DeliverTx`, it will still be part of the block as the
block has already been voted on (unlike with `CheckTx` which would dismiss such a transaction). The responses
returned by `DeliverTx` are included in the header of the next block.
- [**EndBlock**](./abci++_methods.md#endblock) It is executed once all transactions have been processed via
`DeliverTx` to inform the application that the block can now be committed and inform it of potential changes such
as a new validator set to be proposed in the next round. As with `DeliverTx`, cryptographic commitments of the responses returned
are included in the header of the next block.
<!--
- [**ExtendVote:**](./abci++_methods.md#extendvote) It allows applications to force their
validators to do more than just validate within consensus. `ExtendVote` allows applications to
include non-deterministic data, opaque to Tendermint, to precommit messages (the final round of
voting). The data, called *vote extension*, will be broadcast and received together with the
vote it is extending, and will be made available to the Application in the next height,
in the rounds where the local process is the proposer.
Tendermint calls `ExtendVote` when it is about to send a non-`nil` precommit message.
If the Application does not have vote extension information to provide at that time, it returns
a 0-length byte array as its vote extension.
- [**VerifyVoteExtension:**](./abci++_methods.md#verifyvoteextension) It allows
validators to validate the vote extension data attached to a precommit message. If the validation
fails, the whole precommit message will be deemed invalid and ignored by Tendermint.
This has a negative impact on Tendermint's liveness, i.e., if vote extensions repeatedly cannot be
verified by correct validators, Tendermint may not be able to finalize a block even if sufficiently
many (+2/3) validators send precommit votes for that block. Thus, `VerifyVoteExtension`
should 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. Tendermint calls it when
a process receives a precommit message with a (possibly empty) vote extension.
-->
<!---
- [**FinalizeBlock:**](./abci++_methods.md#finalizeblock) It delivers a decided block to the
Application. The Application must execute the transactions in the block deterministically and
update its state accordingly. Cryptographic commitments to the block and transaction results,
returned via the corresponding parameters in `ResponseFinalizeBlock`, are included in the header
of the next block. Tendermint calls it when a new block is decided.
-->
- [**Commit:**](./abci++_methods.md#commit) Instructs the Application to persist its
state. It is a fundamental part of Tendermint's crash-recovery mechanism that ensures the
synchronization between Tendermint and the Applicatin upon recovery. Tendermint calls it just after
having persisted the data returned by calls to `DeliverTx` and `EndBlock` . The Application can now discard
any state or data except the one resulting from executing the transactions in the decided block.
### Mempool methods
- [**CheckTx:**](./abci++_methods.md#checktx) This method allows the Application to validate
transactions. Validation can be stateless (e.g., checking signatures ) or stateful
(e.g., account balances). The type of validation performed is up to the application. If a
transaction passes the validation, then Tendermint adds it to the mempool; otherwise the
transaction is discarded.
Tendermint calls it when it receives a new transaction either coming from an external
user (e.g., a client) or another node. Furthermore, Tendermint can be configured to call
re-`CheckTx` on all outstanding transactions in the mempool after calling `Commit` for a block.
### Info methods
- [**Info:**](./abci++_methods.md#info) Used to sync Tendermint with the Application during a
handshake that happens upon recovery, or on startup when state-sync is used.
- [**Query:**](./abci++_methods.md#query) This method can be used to query the Application for
information about the application state.
### State-sync methods
State sync allows new nodes to rapidly bootstrap by discovering, fetching, and applying
state machine (application) snapshots instead of replaying historical blocks. For more details, see the
[state sync documentation](../p2p/messages/state-sync.md).
New nodes 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. The Application returns the list of locally available
snapshots.
Note that the list does not contain the actual snapshots but metadata about them: height at which
the snapshot was taken, application-specific verification data and more (see
[snapshot data type](./abci++_methods.md#snapshot) for more details). After receiving a
list of available snapshots from a peer, the new node can offer any of the snapshots in the list to
its local Application via the `OfferSnapshot` method. The Application can check at this point the
validity of the snapshot metadata.
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.
To ensure that the sync proceeded correctly, Tendermint compares the local Application's `AppHash`
to the `AppHash` stored on the blockchain (verified via
[light client verification](../light-client/verification/README.md)).
In summary:
- [**ListSnapshots:**](./abci++_methods.md#listsnapshots) Used by nodes to discover available
snapshots on peers.
- [**OfferSnapshot:**](./abci++_methods.md#offersnapshot) When a node receives a snapshot from a
peer, Tendermint uses this method to offer the snapshot to the Application.
- [**LoadSnapshotChunk:**](./abci++_methods.md#loadsnapshotchunk) Used by Tendermint to retrieve
snapshot chunks from the Application to send to peers.
- [**ApplySnapshotChunk:**](./abci++_methods.md#applysnapshotchunk) Used by Tendermint to hand
snapshot chunks to the Application.
### Other methods
Additionally, there is a [**Flush**](./abci++_methods.md#flush) method that is called on every connection,
and an [**Echo**](./abci++_methods.md#echo) method that is used for debugging.
More details on managing state across connections can be found in the section on
[Managing Application State](./abci%2B%2B_app_requirements.md#managing-the-application-state-and-related-topics).
## Tendermint proposal timeout
Immediate execution requires the Application to fully execute the prepared block
before returning from `PrepareProposal`, this means that Tendermint cannot make progress
during the block execution.
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 accommodate the long block execution time and non-proposer nodes might time
out and prevote `nil`. The proposal, in this case, will probably be rejected and a new round will be necessary.
Operators will need to adjust the default value of *TimeoutPropose* in Tendermint's configuration file,
in order to suit the needs of the particular application being deployed.
## Deterministic State-Machine Replication
[&uparrow; Back to Outline](#outline)
ABCI++ applications must implement deterministic finite-state machines to be
securely replicated by the Tendermint consensus engine. This means block execution
must be strictly deterministic: given the same
ordered set of transactions, all nodes will compute identical responses, for all
successive `BeginBlock`, `DeliverTx`, `EndBlock`, and `Commit` 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 application state is not 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 (`BeginBlock`, `DeliverTx`, `EndBlock`, and `Commit` 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 implement immediate execution, which entails executing the blocks
that are about to be proposed (via `PrepareProposal`), and 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 the block execution calls confirm
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 provided in a `RequestPrepareProposal` call.
-->
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 the original discussion.
Note that some methods (`Query, DeliverTx`) return 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.
## Events
[&uparrow; Back to Outline](#outline)
Methods `BeginBlock, DeliverTx` and `EndBlock ` include an `events` field in their
`Response*`.
Applications may respond to this ABCI++ method with an event list for each executed
transaction, and a general event list for the block itself.
Events allow applications to associate metadata with transactions and blocks.
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 {
string key = 1;
string value = 2;
bool index = 3; // nondeterministic
}
```
Example:
```go
abci.ResponseDeliverTx{
// ...
Events: []abci.Event{
{
Type: "validator.provisions",
Attributes: []abci.EventAttribute{
abci.EventAttribute{Key: "address", Value: "...", Index: true},
abci.EventAttribute{Key: "amount", Value: "...", Index: true},
abci.EventAttribute{Key: "balance", Value: "...", Index: true},
},
},
{
Type: "validator.provisions",
Attributes: []abci.EventAttribute{
abci.EventAttribute{Key: "address", Value: "...", Index: true},
abci.EventAttribute{Key: "amount", Value: "...", Index: false},
abci.EventAttribute{Key: "balance", Value: "...", Index: false},
},
},
{
Type: "validator.slashed",
Attributes: []abci.EventAttribute{
abci.EventAttribute{Key: "address", Value: "...", Index: false},
abci.EventAttribute{Key: "amount", Value: "...", Index: true},
abci.EventAttribute{Key: "reason", Value: "...", Index: true},
},
},
// ...
},
}
```
## Evidence
[&uparrow; Back to Outline](#outline)
Tendermint's security model relies on the use of evidences of misbehavior. An evidence is an
irrefutable proof of malicious behavior by a network participant. It is the responsibility of
Tendermint to detect such malicious behavior. When malicious behavior is detected, Tendermint
will gossip evidences of misbehavior to other nodes and commit the evidences to
the chain once they are verified by a subset of validators. These evidences will then be
passed on to the Application through ABCI++. It is the responsibility of the
Application to handle evidence of misbehavior and exercise punishment.
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/).
EvidenceType has the following protobuf format:
```protobuf
enum EvidenceType {
UNKNOWN = 0;
DUPLICATE_VOTE = 1;
LIGHT_CLIENT_ATTACK = 2;
}
```
## Errors
[&uparrow; Back to Outline](#outline)
The `Query`, `CheckTx` and `DeliverTx` methods include a `Code` field in their `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`, `BeginBlock`, `EndBlock`, `Commit` 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 `ExecTxResult`. 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`
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.
### `DeliverTx`
The `DeliverTx` ABCI method delivers transactions from Tendermint to the application.
When Tendermint receives a `ResponseDeliverTx` 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.
<!--
The `ExecTxResult` type delivers transaction results from the Application to Tendermint. When
Tendermint receives a `ResponseFinalizeBlock` containing an `ExecTxResult` with a non-zero `Code`,
the response code is logged. Past `Code` values can be queried by clients. As the transaction was
part of a decided block, the `Code` does not influence Tendermint consensus.
-->
### `Query`
When Tendermint receives a `ResponseQuery` with a non-zero `Code`, this code is
returned directly to the client that initiated the query.

View File

@@ -0,0 +1,94 @@
---
order: 5
title: Client and Server
---
# Client and Server
This section is for those looking to implement their own ABCI Server, perhaps in
a new programming language.
You are expected to have read all previous sections of ABCI++ specification, namely
[Basic Concepts](./abci%2B%2B_basic_concepts.md),
[Methods](./abci%2B%2B_methods.md),
[Application Requirements](./abci%2B%2B_app_requirements.md), and
[Expected Behavior](./abci%2B%2B_tmint_expected_behavior.md).
## Message Protocol and Synchrony
The message protocol consists of pairs of requests and responses defined in the
[protobuf file](../../proto/tendermint/abci/types.proto).
Some messages have no fields, while others may include byte-arrays, strings, integers,
or custom protobuf types.
For more details on protobuf, see the [documentation](https://developers.google.com/protocol-buffers/docs/overview).
<!--
As of v0.36 requests are synchronous. For each of ABCI++'s four connections (see
[Connections](./abci%2B%2B_app_requirements.md)), when Tendermint issues a request to the
Application, it will wait for the response before continuing execution. As a side effect,
requests and responses are ordered for each connection, but not necessarily across connections.
-->
## Server Implementations
To use ABCI in your programming language of choice, there must be an ABCI
server in that language. Tendermint supports four implementations of the ABCI server:
- in Tendermint's repository:
- In-process
- ABCI-socket
- GRPC
- [tendermint-rs](https://github.com/informalsystems/tendermint-rs)
- [tower-abci](https://github.com/penumbra-zone/tower-abci)
The implementations in Tendermint's repository can be tested using `abci-cli` by setting
the `--abci` flag appropriately.
See examples, in various stages of maintenance, in
[Go](https://github.com/tendermint/tendermint/tree/master/abci/server),
[JavaScript](https://github.com/tendermint/js-abci),
[C++](https://github.com/mdyring/cpp-tmsp), and
[Java](https://github.com/jTendermint/jabci).
### In Process
The simplest implementation uses function calls in Golang.
This means ABCI applications written in Golang can be linked with Tendermint Core and run as a single binary.
### GRPC
If you are not using Golang,
but [GRPC](https://grpc.io/) is available in your language, this is the easiest approach,
though it will have significant performance overhead.
Please check GRPC's documentation to know to set up the Application as an
ABCI GRPC server.
### Socket
The Tendermint Socket Protocol is an asynchronous, raw socket server protocol which provides ordered
message passing over Unix or TCP sockets. Messages are serialized using Protobuf3 and length-prefixed
with an [unsigned varint](https://developers.google.com/protocol-buffers/docs/encoding?csw=1#varints)
If gRPC is not available in your language, or you require higher performance, or
otherwise enjoy programming, you may implement your own ABCI server using the
Tendermint Socket Protocol. The first step is still to auto-generate the
relevant data types and codec in your language using `protoc`, and then you need to
ensure you handle the unsigned `varint`-based message length encoding scheme
when reading and writing messages to the socket.
Note that our length prefixing scheme does not apply to gRPC.
Also note that your ABCI server must be able to handle multiple connections,
as Tendermint uses four connections.
## Client
There are currently two use-cases for an ABCI client. One is testing
tools that allow ABCI requests to be sent to the actual application via
command line. An example of this is `abci-cli`, which accepts CLI commands
to send corresponding ABCI requests.
The other is a consensus engine, such as Tendermint Core,
which makes ABCI requests to the application as prescribed by the consensus
algorithm used.

995
spec/abci/abci++_methods.md Normal file
View File

@@ -0,0 +1,995 @@
---
order: 2
title: Methods
---
# Methods
## Methods existing in ABCI
### Echo
* **Request**:
* `Message (string)`: A string to echo back
* **Response**:
* `Message (string)`: The input string
* **Usage**:
* Echo a string to test an abci client/server implementation
### Flush
* **Usage**:
* Signals that messages queued on the client should be flushed to
the server. It is called periodically by the client
implementation to ensure asynchronous requests are actually
sent, and is called immediately to make a synchronous request,
which returns when the Flush response comes back.
### Info
* **Request**:
| Name | Type | Description | Field Number |
|---------------|--------|------------------------------------------|--------------|
| version | string | The Tendermint software semantic version | 1 |
| block_version | uint64 | The Tendermint Block Protocol version | 2 |
| p2p_version | uint64 | The Tendermint P2P Protocol version | 3 |
| abci_version | string | The Tendermint ABCI semantic version | 4 |
* **Response**:
| Name | Type | Description | Field Number |
|---------------------|--------|-----------------------------------------------------|--------------|
| data | string | Some arbitrary information | 1 |
| version | string | The application software semantic version | 2 |
| app_version | uint64 | The application protocol version | 3 |
| last_block_height | int64 | Latest height for which the app persisted its state | 4 |
| last_block_app_hash | bytes | Latest AppHash returned by `FinalizeBlock` | 5 |
* **Usage**:
* Return information about the application state.
* Used to sync Tendermint with the application during a handshake
that happens on startup or on recovery.
* The returned `app_version` will be included in the Header of every block.
* Tendermint expects `last_block_app_hash` and `last_block_height` to
be updated during `FinalizeBlock` and persisted during `Commit`.
> Note: Semantic version is a reference to [semantic versioning](https://semver.org/). Semantic versions in info will be displayed as X.X.x.
### InitChain
* **Request**:
| Name | Type | Description | Field Number |
|------------------|-------------------------------------------------|-----------------------------------------------------|--------------|
| time | [google.protobuf.Timestamp][protobuf-timestamp] | Genesis time | 1 |
| chain_id | string | ID of the blockchain. | 2 |
| consensus_params | [ConsensusParams](#consensusparams) | Initial consensus-critical parameters. | 3 |
| validators | repeated [ValidatorUpdate](#validatorupdate) | Initial genesis validators, sorted by voting power. | 4 |
| app_state_bytes | bytes | Serialized initial application state. JSON bytes. | 5 |
| initial_height | int64 | Height of the initial block (typically `1`). | 6 |
* **Response**:
| Name | Type | Description | Field Number |
|------------------|----------------------------------------------|--------------------------------------------------|--------------|
| consensus_params | [ConsensusParams](#consensusparams) | Initial consensus-critical parameters (optional) | 1 |
| validators | repeated [ValidatorUpdate](#validatorupdate) | Initial validator set (optional). | 2 |
| app_hash | bytes | Initial application hash. | 3 |
* **Usage**:
* Called once upon genesis.
* If `ResponseInitChain.Validators` is empty, the initial validator set will be the `RequestInitChain.Validators`
* If `ResponseInitChain.Validators` is not empty, it will be the initial
validator set (regardless of what is in `RequestInitChain.Validators`).
* This allows the app to decide if it wants to accept the initial validator
set proposed by Tendermint (ie. in the genesis file), or if it wants to use
a different one (perhaps computed based on some application specific
information in the genesis file).
* Both `RequestInitChain.Validators` and `ResponseInitChain.Validators` are [ValidatorUpdate](#validatorupdate) structs.
So, technically, they both are _updating_ the set of validators from the empty set.
### Query
* **Request**:
| Name | Type | Description | Field Number |
|--------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| data | bytes | Raw query bytes. Can be used with or in lieu of Path. | 1 |
| path | string | Path field of the request URI. Can be used with or in lieu of `data`. Apps MUST interpret `/store` as a query by key on the underlying store. The key SHOULD be specified in the `data` field. Apps SHOULD allow queries over specific types like `/accounts/...` or `/votes/...` | 2 |
| height | int64 | The block height for which you want the query (default=0 returns data for the latest committed block). Note that this is the height of the block containing the application's Merkle root hash, which represents the state as it was after committing the block at Height-1 | 3 |
| prove | bool | Return Merkle proof with response if possible | 4 |
* **Response**:
| Name | Type | Description | Field Number |
|-----------|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| code | uint32 | Response code. | 1 |
| log | string | The output of the application's logger. **May be non-deterministic.** | 3 |
| info | string | Additional information. **May be non-deterministic.** | 4 |
| index | int64 | The index of the key in the tree. | 5 |
| key | bytes | The key of the matching data. | 6 |
| value | bytes | The value of the matching data. | 7 |
| proof_ops | [ProofOps](#proofops) | Serialized proof for the value data, if requested, to be verified against the `app_hash` for the given Height. | 8 |
| height | int64 | The block height from which data was derived. Note that this is the height of the block containing the application's Merkle root hash, which represents the state as it was after committing the block at Height-1 | 9 |
| codespace | string | Namespace for the `code`. | 10 |
* **Usage**:
* Query for data from the application at current or past height.
* Optionally return Merkle proof.
* Merkle proof includes self-describing `type` field to support many types
of Merkle trees and encoding formats.
### CheckTx
* **Request**:
| Name | Type | Description | Field Number |
|------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| tx | bytes | The request transaction bytes | 1 |
| type | CheckTxType | One of `CheckTx_New` or `CheckTx_Recheck`. `CheckTx_New` is the default and means that a full check of the tranasaction is required. `CheckTx_Recheck` types are used when the mempool is initiating a normal recheck of a transaction. | 2 |
* **Response**:
| Name | Type | Description | Field Number |
|------------|-------------------------------------------------------------|-----------------------------------------------------------------------|--------------|
| code | uint32 | Response code. | 1 |
| data | bytes | Result bytes, if any. | 2 |
| gas_wanted | int64 | Amount of gas requested for transaction. | 5 |
| codespace | string | Namespace for the `code`. | 8 |
| sender | string | The transaction's sender (e.g. the signer) | 9 |
| priority | int64 | The transaction's priority (for mempool ordering) | 10 |
* **Usage**:
* Technically optional - not involved in processing blocks.
* Guardian of the mempool: every node runs `CheckTx` before letting a
transaction into its local mempool.
* The transaction may come from an external user or another node
* `CheckTx` validates the transaction against the current state of the application,
for example, checking signatures and account balances, but does not apply any
of the state changes described in the transaction.
* Transactions where `ResponseCheckTx.Code != 0` will be rejected - they will not be broadcast
to other nodes or included in a proposal block.
Tendermint attributes no other value to the response code.
### BeginBlock
* **Request**:
| Name | Type | Description | Field Number |
|----------------------|---------------------------------------------|-------------------------------------------------------------------------------------------------------------------|--------------|
| hash | bytes | The block's hash. This can be derived from the block header. | 1 |
| header | [Header](../core/data_structures.md#header) | The block header. | 2 |
| last_commit_info | [CommitInfo](#commitinfo) | Info about the last commit, including the round, and the list of validators and which ones signed the last block. | 3 |
| byzantine_validators | repeated [Evidence](abci++_basic_concepts.md#evidence) | List of evidence of validators that acted maliciously. | 4 |
* **Response**:
| Name | Type | Description | Field Number |
|--------|---------------------------|-------------------------------------|--------------|
| events | repeated [Event](abci++_basic_concepts.md#events) | type & Key-Value events for indexing | 1 |
* **Usage**:
* Signals the beginning of a new block.
* Called prior to any `DeliverTx` method calls.
* The header contains the height, timestamp, and more - it exactly matches the
Tendermint block header. We may seek to generalize this in the future.
* The `CommitInfo` and `ByzantineValidators` can be used to determine
rewards and punishments for the validators.
### DeliverTx
* **Request**:
| Name | Type | Description | Field Number |
|------|-------|--------------------------------|--------------|
| tx | bytes | The request transaction bytes. | 1 |
* **Response**:
| Name | Type | Description | Field Number |
|------------|---------------------------|-----------------------------------------------------------------------|--------------|
| code | uint32 | Response code. | 1 |
| data | bytes | Result bytes, if any. | 2 |
| log | string | The output of the application's logger. **May be non-deterministic.** | 3 |
| info | string | Additional information. **May be non-deterministic.** | 4 |
| gas_wanted | int64 | Amount of gas requested for transaction. | 5 |
| gas_used | int64 | Amount of gas consumed by transaction. | 6 |
| events | repeated [Event](abci++_basic_concepts.md#events) | Type & Key-Value events for indexing transactions (eg. by account). | 7 |
| codespace | string | Namespace for the `code`. | 8 |
* **Usage**:
* [**Required**] The core method of the application.
* `DeliverTx` is called once for each transaction in the block.
* When `DeliverTx` is called, the application must execute the transaction deterministically
in full before returning control to Tendermint.
* Alternatively, the application can apply a candidate state corresponding
to the same block previously executed via `PrepareProposal` or `ProcessProposal` any time between the calls to `BeginBlock`, the various
calls to `DeliverTx` and `EndBlock`.
* `ResponseDeliverTx.Code == 0` only if the transaction is fully valid.
### EndBlock
* **Request**:
| Name | Type | Description | Field Number |
|--------|-------|------------------------------------|--------------|
| height | int64 | Height of the block just executed. | 1 |
* **Response**:
| Name | Type | Description | Field Number |
|-------------------------|----------------------------------------------|-----------------------------------------------------------------|--------------|
| validator_updates | repeated [ValidatorUpdate](#validatorupdate) | Changes to validator set (set voting power to 0 to remove). | 1 |
| consensus_param_updates | [ConsensusParams](#consensusparams) | Changes to consensus-critical time, size, and other parameters. | 2 |
| events | repeated [Event](abci++_basic_concepts.md#events) | Type & Key-Value events for indexing | 3 |
* **Usage**:
* Signals the end of a block.
* Called after all the transactions for the current block have been delivered, prior to the block's `Commit` message.
* Optional `validator_updates` triggered by block `H`. These updates affect validation
for blocks `H+1`, `H+2`, and `H+3`.
* Heights following a validator update are affected in the following way:
* `H+1`: `NextValidatorsHash` includes the new `validator_updates` value.
* `H+2`: The validator set change takes effect and `ValidatorsHash` is updated.
* `H+3`: `last_commit_info (BeginBlock)` is changed to include the altered validator set and `*_last_commit` fields in `PrepareProposal`, `ProcessProposal` now include the altered validator set.
* `consensus_param_updates` returned for block `H` apply to the consensus
params for block `H+1`. For more information on the consensus parameters,
see the [application spec entry on consensus parameters](abci++_app_requirements.md#consensus-parameters).
* `validator_updates` and `consensus_param_updates` may be empty. In this case, Tendermint will keep the current values.
### Commit
* **Request**:
| Name | Type | Description | Field Number |
|--------|-------|------------------------------------|--------------|
Commit signals the application to persist application state. It takes no parameters.
* **Response**:
| Name | Type | Description | Field Number |
|---------------|-------|------------------------------------------------------------------------|--------------|
| data | bytes | The Merkle root hash of the application state. | 2 |
| retain_height | int64 | Blocks below this height may be removed. Defaults to `0` (retain all). | 3 |
* **Usage**:
* Signal the application to persist the application state.
* Return an (optional) Merkle root hash of the application state
* `ResponseCommit.Data` is included as the `Header.AppHash` in the next block
* It may be empty or hard-coded, but MUST be **deterministic** - it must not be a function of anything that did not come from the parameters of the execution calls (` BeginBlock/DeliverTx/EndBlock methods`) and the previous committed state.
* Later calls to `Query` can return proofs about the application state anchored
in this Merkle root hash
* Use `RetainHeight` with caution! If all nodes in the network remove historical
blocks then this data is permanently lost, and no new nodes will be able to
join the network and bootstrap. Historical blocks may also be required for
other purposes, e.g. auditing, replay of non-persisted heights, light client
verification, and so on.
### ListSnapshots
* **Request**:
| Name | Type | Description | Field Number |
|--------|-------|------------------------------------|--------------|
Empty request asking the application for a list of snapshots.
* **Response**:
| Name | Type | Description | Field Number |
|-----------|--------------------------------|--------------------------------|--------------|
| snapshots | repeated [Snapshot](#snapshot) | List of local state snapshots. | 1 |
* **Usage**:
* Used during state sync to discover available snapshots on peers.
* See `Snapshot` data type for details.
### LoadSnapshotChunk
* **Request**:
| Name | Type | Description | Field Number |
|--------|--------|-----------------------------------------------------------------------|--------------|
| height | uint64 | The height of the snapshot the chunk belongs to. | 1 |
| format | uint32 | The application-specific format of the snapshot the chunk belongs to. | 2 |
| chunk | uint32 | The chunk index, starting from `0` for the initial chunk. | 3 |
* **Response**:
| Name | Type | Description | Field Number |
|-------|-------|-------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| chunk | bytes | The binary chunk contents, in an arbitray format. Chunk messages cannot be larger than 16 MB _including metadata_, so 10 MB is a good starting point. | 1 |
* **Usage**:
* Used during state sync to retrieve snapshot chunks from peers.
### OfferSnapshot
* **Request**:
| Name | Type | Description | Field Number |
|----------|-----------------------|--------------------------------------------------------------------------|--------------|
| snapshot | [Snapshot](#snapshot) | The snapshot offered for restoration. | 1 |
| app_hash | bytes | The light client-verified app hash for this height, from the blockchain. | 2 |
* **Response**:
| Name | Type | Description | Field Number |
|--------|-------------------|-----------------------------------|--------------|
| result | [Result](#result) | The result of the snapshot offer. | 1 |
#### Result
```protobuf
enum Result {
UNKNOWN = 0; // Unknown result, abort all snapshot restoration
ACCEPT = 1; // Snapshot is accepted, start applying chunks.
ABORT = 2; // Abort snapshot restoration, and don't try any other snapshots.
REJECT = 3; // Reject this specific snapshot, try others.
REJECT_FORMAT = 4; // Reject all snapshots with this `format`, try others.
REJECT_SENDER = 5; // Reject all snapshots from all senders of this snapshot, try others.
}
```
* **Usage**:
* `OfferSnapshot` is called when bootstrapping a node using state sync. The application may
accept or reject snapshots as appropriate. Upon accepting, Tendermint will retrieve and
apply snapshot chunks via `ApplySnapshotChunk`. The application may also choose to reject a
snapshot in the chunk response, in which case it should be prepared to accept further
`OfferSnapshot` calls.
* Only `AppHash` can be trusted, as it has been verified by the light client. Any other data
can be spoofed by adversaries, so applications should employ additional verification schemes
to avoid denial-of-service attacks. The verified `AppHash` is automatically checked against
the restored application at the end of snapshot restoration.
* For more information, see the `Snapshot` data type or the [state sync section](../p2p/messages/state-sync.md).
### ApplySnapshotChunk
* **Request**:
| Name | Type | Description | Field Number |
|--------|--------|-----------------------------------------------------------------------------|--------------|
| index | uint32 | The chunk index, starting from `0`. Tendermint applies chunks sequentially. | 1 |
| chunk | bytes | The binary chunk contents, as returned by `LoadSnapshotChunk`. | 2 |
| sender | string | The P2P ID of the node who sent this chunk. | 3 |
* **Response**:
| Name | Type | Description | Field Number |
|----------------|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| result | Result (see below) | The result of applying this chunk. | 1 |
| refetch_chunks | repeated uint32 | Refetch and reapply the given chunks, regardless of `result`. Only the listed chunks will be refetched, and reapplied in sequential order. | 2 |
| reject_senders | repeated string | Reject the given P2P senders, regardless of `Result`. Any chunks already applied will not be refetched unless explicitly requested, but queued chunks from these senders will be discarded, and new chunks or other snapshots rejected. | 3 |
```proto
enum Result {
UNKNOWN = 0; // Unknown result, abort all snapshot restoration
ACCEPT = 1; // The chunk was accepted.
ABORT = 2; // Abort snapshot restoration, and don't try any other snapshots.
RETRY = 3; // Reapply this chunk, combine with `RefetchChunks` and `RejectSenders` as appropriate.
RETRY_SNAPSHOT = 4; // Restart this snapshot from `OfferSnapshot`, reusing chunks unless instructed otherwise.
REJECT_SNAPSHOT = 5; // Reject this snapshot, try a different one.
}
```
* **Usage**:
* The application can choose to refetch chunks and/or ban P2P peers as appropriate. Tendermint
will not do this unless instructed by the application.
* The application may want to verify each chunk, e.g. by attaching chunk hashes in
`Snapshot.Metadata` and/or incrementally verifying contents against `AppHash`.
* When all chunks have been accepted, Tendermint will make an ABCI `Info` call to verify that
`LastBlockAppHash` and `LastBlockHeight` matches the expected values, and record the
`AppVersion` in the node state. It then switches to block sync or consensus and joins the
network.
* If Tendermint is unable to retrieve the next chunk after some time (e.g. because no suitable
peers are available), it will reject the snapshot and try a different one via `OfferSnapshot`.
The application should be prepared to reset and accept it or abort as appropriate.
## New methods introduced in ABCI++
### PrepareProposal
#### Parameters and Types
* **Request**:
| Name | Type | Description | Field Number |
|----------------------|-------------------------------------------------|-----------------------------------------------------------------------------------------------|--------------|
| max_tx_bytes | int64 | Currently configured maximum size in bytes taken by the modified transactions. | 1 |
| txs | repeated bytes | Preliminary list of transactions that have been picked as part of the block to propose. | 2 |
| local_last_commit | [ExtendedCommitInfo](#extendedcommitinfo) | Info about the last commit, obtained locally from Tendermint's data structures. | 3 |
| misbehavior | repeated [Misbehavior](#misbehavior) | List of information about validators that misbehaved. | 4 |
| height | int64 | The height of the block that will be proposed. | 5 |
| time | [google.protobuf.Timestamp][protobuf-timestamp] | Timestamp of the block that that will be proposed. | 6 |
| next_validators_hash | bytes | Merkle root of the next validator set. | 7 |
| proposer_address | bytes | [Address](../core/data_structures.md#address) of the validator that is creating the proposal. | 8 |
* **Response**:
| Name | Type | Description | Field Number |
|-------------------------|--------------------------------------------------|---------------------------------------------------------------------------------------------|--------------|
| txs | repeated bytes | Possibly modified list of transactions that have been picked as part of the proposed block. | 2 |
* **Usage**:
* `RequestPrepareProposal`'s parameters `txs`, `misbehavior`, `height`, `time`,
`next_validators_hash`, and `proposer_address` are the same as in `RequestProcessProposal`.
* `RequestPrepareProposal.local_last_commit` is a set of the precommit votes that allowed the
decision of the previous block.
* The `height`, `time`, and `proposer_address` values match the values from the header of the
proposed block.
* `RequestPrepareProposal` contains a preliminary set of transactions `txs` that Tendermint
retrieved from the mempool, called _raw proposal_. The Application can modify this
set and return a modified set of transactions via `ResponsePrepareProposal.txs` .
* The Application _can_ modify the raw proposal: it can reorder, remove or add transactions.
Let `tx` be a transaction in `txs` (set of transactions within `RequestPrepareProposal`):
* If the Application considers that `tx` should not be proposed in this block, e.g.,
there are other transactions with higher priority, then it should not include it in
`ResponsePrepareProposal.txs`. However, this will not remove `tx` from the mempool.
* If the Application wants to add a new transaction to the proposed block, then the
Application includes it in `ResponsePrepareProposal.txs`. In this case, Tendermint
will also add the transaction to the mempool.
* The Application should be aware that removing and adding transactions may compromise
_traceability_.
> Consider the following example: the Application transforms a client-submitted
transaction `t1` into a second transaction `t2`, i.e., the Application asks Tendermint
to remove `t1` from the block and add `t2` to the block. If a client wants to eventually check what
happened to `t1`, it will discover that `t1` is not in a
committed block (assuming a _re-CheckTx_ evited it from the mempool), getting the wrong idea that `t1` did not make it into a block. Note
that `t2` _will be_ in a committed block, but unless the Application tracks this
information, no component will be aware of it. Thus, if the Application wants
traceability, it is its responsability to support it. For instance, the Application
could attach to a transformed transaction a list with the hashes of the transactions it
derives from.
* Tendermint MAY include a list of transactions in `RequestPrepareProposal.txs` whose total
size in bytes exceeds `RequestPrepareProposal.max_tx_bytes`.
Therefore, if the size of `RequestPrepareProposal.txs` is greater than
`RequestPrepareProposal.max_tx_bytes`, the Application MUST remove transactions to ensure
that the `RequestPrepareProposal.max_tx_bytes` limit is respected by those transactions
returned in `ResponsePrepareProposal.txs` .
* As a result of executing the prepared proposal, the Application may produce block events or transaction events.
The Application must keep those events until a block is decided. It will then forward the events to the `BeginBlock-DeliverTx-EndBlock` functions depending on where each event should be placed, thereby returning the events to Tendermint.
* Tendermint does NOT provide any additional validity checks (such as checking for duplicate
transactions).
<!--
As a sanity check, Tendermint will check the returned parameters for validity if the Application modified them.
In particular, `ResponsePrepareProposal.txs` will be deemed invalid if there are duplicate transactions in the list.
-->
* If Tendermint fails to validate the `ResponsePrepareProposal`, Tendermint will assume the
Application is faulty and crash.
* The implementation of `PrepareProposal` can be non-deterministic.
#### When does Tendermint call `PrepareProposal`?
When a validator _p_ enters Tendermint consensus round _r_, height _h_, in which _p_ is the proposer,
and _p_'s _validValue_ is `nil`:
1. Tendermint collects outstanding transactions from _p_'s mempool
* the transactions will be collected in order of priority
* _p_'s Tendermint creates a block header.
2. _p_'s Tendermint calls `RequestPrepareProposal` with the newly generated block, the local
commit of the previous height (with vote extensions), and any outstanding evidence of
misbehavior. The call is synchronous: Tendermint's execution will block until the Application
returns from the call.
3. The Application uses the information received (transactions, commit info, misbehavior, time) to
(potentially) modify the proposal.
* the Application MAY fully execute the block and produce a candidate state &mdash; immediate
execution
* the Application can manipulate transactions:
* leave transactions untouched
* add new transactions (not present initially) to the proposal
* remove transactions from the proposal (but not from the mempool thus effectively _delaying_ them) - the
Application does not include the transaction in `ResponsePrepareProposal.txs`.
* modify transactions (e.g. aggregate them). As explained above, this compromises client traceability, unless
it is implemented at the Application level.
* reorder transactions - the Application reorders transactions in the list
4. The Application includes the transaction list (whether modified or not) in the return parameters
(see the rules in section _Usage_), and returns from the call.
5. _p_'s Tendermint uses the (possibly) modified block as _p_'s proposal in round _r_, height _h_.
Note that, if _p_ has a non-`nil` _validValue_ in round _r_, height _h_, Tendermint will use it as
proposal and will not call `RequestPrepareProposal`.
### ProcessProposal
#### Parameters and Types
* **Request**:
| Name | Type | Description | Field Number |
|----------------------|-------------------------------------------------|-------------------------------------------------------------------------------------------|--------------|
| txs | repeated bytes | List of transactions of the proposed block. | 1 |
| proposed_last_commit | [CommitInfo](#commitinfo) | Info about the last commit, obtained from the information in the proposed block. | 2 |
| misbehavior | repeated [Misbehavior](#misbehavior) | List of information about validators that misbehaved. | 3 |
| hash | bytes | The hash of the proposed block. | 4 |
| height | int64 | The height of the proposed block. | 5 |
| time | [google.protobuf.Timestamp][protobuf-timestamp] | Timestamp of the proposed block. | 6 |
| next_validators_hash | bytes | Merkle root of the next validator set. | 7 |
| proposer_address | bytes | [Address](../core/data_structures.md#address) of the validator that created the proposal. | 8 |
* **Response**:
| Name | Type | Description | Field Number |
|-------------------------|--------------------------------------------------|-----------------------------------------------------------------------------------|--------------|
| status | [ProposalStatus](#proposalstatus) | `enum` that signals if the application finds the proposal valid. | 1 |
* **Usage**:
* Contains all information on the proposed block needed to fully execute it.
* The Application may fully execute the block as though it was handling the calls to `BeginBlock-DeliverTx-EndBlock`.
* However, any resulting state changes must be kept as _candidate state_,
and the Application should be ready to discard it in case another block is decided.
* `RequestProcessProposal` is also called at the proposer of a round. The reason for this is to
inform the Application of the block header's hash, which cannot be done at `PrepareProposal`
time. In this case, the call to `RequestProcessProposal` occurs right after the call to
`RequestPrepareProposal`.
* The height and time values match the values from the header of the proposed block.
* If `ResponseProcessProposal.status` is `REJECT`, Tendermint assumes the proposal received
is not valid.
* The Application MAY fully execute the block &mdash; immediate execution
* The implementation of `ProcessProposal` MUST be deterministic. Moreover, the value of
`ResponseProcessProposal.status` MUST **exclusively** depend on the parameters passed in
the call to `RequestProcessProposal`, and the last committed Application state
(see [Requirements](./abci++_app_requirements.md) section).
* Moreover, application implementors SHOULD always set `ResponseProcessProposal.status` to `ACCEPT`,
unless they _really_ know what the potential liveness implications of returning `REJECT` are.
#### When does Tendermint call `ProcessProposal`?
When a validator _p_ enters Tendermint consensus round _r_, height _h_, in which _q_ is the proposer (possibly _p_ = _q_):
1. _p_ sets up timer `ProposeTimeout`.
2. If _p_ is the proposer, _p_ executes steps 1-6 in [PrepareProposal](#prepareproposal).
3. Upon reception of Proposal message (which contains the header) for round _r_, height _h_ from
_q_, _p_'s Tendermint verifies the block header.
4. Upon reception of Proposal message, along with all the block parts, for round _r_, height _h_
from _q_, _p_'s Tendermint follows its algorithm to check whether it should prevote for the
proposed block, or `nil`.
5. If Tendermint should prevote for the proposed block:
1. Tendermint calls `RequestProcessProposal` with the block. The call is synchronous.
2. The Application checks/processes the proposed block, which is read-only, and returns
`ACCEPT` or `REJECT` in the `ResponseProcessProposal.status` field.
* The Application, depending on its needs, may call `ResponseProcessProposal`
* either after it has completely processed the block (immediate execution),
* or after doing some basic checks, and process the block asynchronously. In this case the
Application will not be able to reject the block, or force prevote/precommit `nil`
afterwards.
3. If the returned value is
* `ACCEPT`: Tendermint prevotes on this proposal for round _r_, height _h_.
* `REJECT`: Tendermint prevotes `nil`.
<!--
### ExtendVote
#### Parameters and Types
* **Request**:
| Name | Type | Description | Field Number |
|--------|-------|-------------------------------------------------------------------------------|--------------|
| hash | bytes | The header hash of the proposed block that the vote extension is to refer to. | 1 |
| height | int64 | Height of the proposed block (for sanity check). | 2 |
* **Response**:
| Name | Type | Description | Field Number |
|-------------------|-------|---------------------------------------------------------|--------------|
| vote_extension | bytes | Information signed by by Tendermint. Can have 0 length. | 1 |
* **Usage**:
* `ResponseExtendVote.vote_extension` is application-generated information that will be signed
by Tendermint and attached to the Precommit message.
* The Application may choose to use an empty vote extension (0 length).
* `RequestExtendVote.hash` corresponds to the hash of a proposed block that was made available
to the Application in a previous call to `ProcessProposal` for the current height.
* `ResponseExtendVote.vote_extension` will only be attached to a non-`nil` Precommit message. If Tendermint is to
precommit `nil`, it will not call `RequestExtendVote`.
* The Application logic that creates the extension can be non-deterministic.
#### When does Tendermint call `ExtendVote`?
When a validator _p_ is in Tendermint consensus state _prevote_ of round _r_, height _h_, in which _q_ is the proposer; and _p_ has received
* the Proposal message _v_ for round _r_, height _h_, along with all the block parts, from _q_,
* `Prevote` messages from _2f + 1_ validators' voting power for round _r_, height _h_, prevoting for the same block _id(v)_,
then _p_'s Tendermint locks _v_ and sends a Precommit message in the following way
1. _p_'s Tendermint sets _lockedValue_ and _validValue_ to _v_, and sets _lockedRound_ and _validRound_ to _r_
2. _p_'s Tendermint calls `RequestExtendVote` with _id(v)_ (`RequestExtendVote.hash`). The call is synchronous.
3. The Application returns an array of bytes, `ResponseExtendVote.extension`, which is not interpreted by Tendermint.
4. _p_'s Tendermint includes `ResponseExtendVote.extension` in a field of type [CanonicalVoteExtension](#canonicalvoteextension),
it then populates the other fields in [CanonicalVoteExtension](#canonicalvoteextension), and signs the populated
data structure.
5. _p_'s Tendermint constructs and signs the [CanonicalVote](../core/data_structures.md#canonicalvote) structure.
6. _p_'s Tendermint constructs the Precommit message (i.e. [Vote](../core/data_structures.md#vote) structure)
using [CanonicalVoteExtension](#canonicalvoteextension) and [CanonicalVote](../core/data_structures.md#canonicalvote).
7. _p_'s Tendermint broadcasts the Precommit message.
In the cases when _p_'s Tendermint is to broadcast `precommit nil` messages (either _2f+1_ `prevote nil` messages received,
or _timeoutPrevote_ triggered), _p_'s Tendermint does **not** call `RequestExtendVote` and will not include
a [CanonicalVoteExtension](#canonicalvoteextension) field in the `precommit nil` message.
### VerifyVoteExtension
#### Parameters and Types
* **Request**:
| Name | Type | Description | Field Number |
|-------------------|-------|-------------------------------------------------------------------------------------------|--------------|
| hash | bytes | The hash of the proposed block that the vote extension refers to. | 1 |
| validator_address | bytes | [Address](../core/data_structures.md#address) of the validator that signed the extension. | 2 |
| height | int64 | Height of the block (for sanity check). | 3 |
| vote_extension | bytes | Application-specific information signed by Tendermint. Can have 0 length. | 4 |
* **Response**:
| Name | Type | Description | Field Number |
|--------|-------------------------------|----------------------------------------------------------------|--------------|
| status | [VerifyStatus](#verifystatus) | `enum` signaling if the application accepts the vote extension | 1 |
* **Usage**:
* `RequestVerifyVoteExtension.vote_extension` can be an empty byte array. The Application's
interpretation of it should be
that the Application running at the process that sent the vote chose not to extend it.
Tendermint will always call `RequestVerifyVoteExtension`, even for 0 length vote extensions.
* `RequestVerifyVoteExtension` is not called for precommit votes sent by the local process.
* `RequestVerifyVoteExtension.hash` refers to a proposed block. There is not guarantee that
this proposed block has previously been exposed to the Application via `ProcessProposal`.
* If `ResponseVerifyVoteExtension.status` is `REJECT`, Tendermint will reject the whole received vote.
See the [Requirements](./abci++_app_requirements.md) section to understand the potential
liveness implications of this.
* The implementation of `VerifyVoteExtension` MUST be deterministic. Moreover, the value of
`ResponseVerifyVoteExtension.status` MUST **exclusively** depend on the parameters passed in
the call to `RequestVerifyVoteExtension`, and the last committed Application state
(see [Requirements](./abci++_app_requirements.md) section).
* Moreover, application implementers SHOULD always set `ResponseVerifyVoteExtension.status` to `ACCEPT`,
unless they _really_ know what the potential liveness implications of returning `REJECT` are.
#### When does Tendermint call `VerifyVoteExtension`?
When a node _p_ is in Tendermint consensus round _r_, height _h_, and _p_ receives a Precommit
message for round _r_, height _h_ from validator _q_ (_q_ &ne; _p_):
1. If the Precommit message does not contain a vote extension with a valid signature, Tendermint
discards the Precommit message as invalid.
* a 0-length vote extension is valid as long as its accompanying signature is also valid.
2. Else, _p_'s Tendermint calls `RequestVerifyVoteExtension`.
3. The Application returns `ACCEPT` or `REJECT` via `ResponseVerifyVoteExtension.status`.
4. If the Application returns
* `ACCEPT`, _p_'s Tendermint will keep the received vote, together with its corresponding
vote extension in its internal data structures. It will be used to populate the [ExtendedCommitInfo](#extendedcommitinfo)
structure in calls to `RequestPrepareProposal`, in rounds of height _h + 1_ where _p_ is the proposer.
* `REJECT`, _p_'s Tendermint will deem the Precommit message invalid and discard it.
-->
<!--
### FinalizeBlock
#### Parameters and Types
* **Request**:
| Name | Type | Description | Field Number |
|----------------------|-------------------------------------------------|-------------------------------------------------------------------------------------------|--------------|
| txs | repeated bytes | List of transactions committed as part of the block. | 1 |
| decided_last_commit | [CommitInfo](#commitinfo) | Info about the last commit, obtained from the block that was just decided. | 2 |
| misbehavior | repeated [Misbehavior](#misbehavior) | List of information about validators that misbehaved. | 3 |
| hash | bytes | The block's hash. | 4 |
| height | int64 | The height of the finalized block. | 5 |
| time | [google.protobuf.Timestamp][protobuf-timestamp] | Timestamp of the finalized block. | 6 |
| next_validators_hash | bytes | Merkle root of the next validator set. | 7 |
| proposer_address | bytes | [Address](../core/data_structures.md#address) of the validator that created the proposal. | 8 |
* **Response**:
| Name | Type | Description | Field Number |
|-------------------------|-------------------------------------------------------------|----------------------------------------------------------------------------------|--------------|
| events | repeated [Event](abci++_basic_concepts.md#events) | Type & Key-Value events for indexing | 1 |
| tx_results | repeated [ExecTxResult](#exectxresult) | List of structures containing the data resulting from executing the transactions | 2 |
| validator_updates | repeated [ValidatorUpdate](#validatorupdate) | Changes to validator set (set voting power to 0 to remove). | 3 |
| consensus_param_updates | [ConsensusParams](#consensusparams) | Changes to gas, size, and other consensus-related parameters. | 4 |
| app_hash | bytes | The Merkle root hash of the application state. | 5 |
* **Usage**:
* Contains the fields of the newly decided block.
* This method is equivalent to the call sequence `BeginBlock`, [`DeliverTx`],
and `EndBlock` in the previous version of ABCI.
* The height and time values match the values from the header of the proposed block.
* The Application can use `RequestFinalizeBlock.decided_last_commit` and `RequestFinalizeBlock.misbehavior`
to determine rewards and punishments for the validators.
* The Application executes the transactions in `RequestFinalizeBlock.txs` deterministically,
according to the rules set up by the Application, before returning control to Tendermint.
Alternatively, it can apply the candidate state corresponding to the same block previously
executed via `PrepareProposal` or `ProcessProposal`.
* `ResponseFinalizeBlock.tx_results[i].Code == 0` only if the _i_-th transaction is fully valid.
* The Application must provide values for `ResponseFinalizeBlock.app_hash`,
`ResponseFinalizeBlock.tx_results`, `ResponseFinalizeBlock.validator_updates`, and
`ResponseFinalizeBlock.consensus_param_updates` as a result of executing the block.
* The values for `ResponseFinalizeBlock.validator_updates`, or
`ResponseFinalizeBlock.consensus_param_updates` may be empty. In this case, Tendermint will keep
the current values.
* `ResponseFinalizeBlock.validator_updates`, triggered by block `H`, affect validation
for blocks `H+1`, `H+2`, and `H+3`. Heights following a validator update are affected in the following way:
* Height `H+1`: `NextValidatorsHash` includes the new `validator_updates` value.
* Height `H+2`: The validator set change takes effect and `ValidatorsHash` is updated.
* Height `H+3`: `*_last_commit` fields in `PrepareProposal`, `ProcessProposal`, and
`FinalizeBlock` now include the altered validator set.
* `ResponseFinalizeBlock.consensus_param_updates` returned for block `H` apply to the consensus
params for block `H+1`. For more information on the consensus parameters,
see the [consensus parameters](./abci%2B%2B_app_requirements.md#consensus-parameters)
section.
* `ResponseFinalizeBlock.app_hash` contains an (optional) Merkle root hash of the application state.
* `ResponseFinalizeBlock.app_hash` is included as the `Header.AppHash` in the next block.
* `ResponseFinalizeBlock.app_hash` may also be empty or hard-coded, but MUST be
**deterministic** - it must not be a function of anything that did not come from the parameters
of `RequestFinalizeBlock` and the previous committed state.
* Later calls to `Query` can return proofs about the application state anchored
in this Merkle root hash.
* The implementation of `FinalizeBlock` MUST be deterministic, since it is
making the Application's state evolve in the context of state machine replication.
* Currently, Tendermint will fill up all fields in `RequestFinalizeBlock`, even if they were
already passed on to the Application via `RequestPrepareProposal` or `RequestProcessProposal`.
#### When does Tendermint call `FinalizeBlock`?
When a node _p_ is in Tendermint consensus height _h_, and _p_ receives
* the Proposal message with block _v_ for a round _r_, along with all its block parts, from _q_,
which is the proposer of round _r_, height _h_,
* `Precommit` messages from _2f + 1_ validators' voting power for round _r_, height _h_,
precommitting the same block _id(v)_,
then _p_'s Tendermint decides block _v_ and finalizes consensus for height _h_ in the following way
1. _p_'s Tendermint persists _v_ as the decision for height _h_.
2. _p_'s Tendermint calls `RequestFinalizeBlock` with _v_'s data. The call is synchronous.
3. _p_'s Application executes block _v_.
4. _p_'s Application calculates and returns the _AppHash_, along with a list containing
the outputs of each of the transactions executed.
5. _p_'s Tendermint hashes all the transaction outputs and stores it in _ResultHash_.
6. _p_'s Tendermint persists the transaction outputs, _AppHash_, and _ResultsHash_.
7. _p_'s Tendermint locks the mempool &mdash; no calls to `CheckTx` on new transactions.
8. _p_'s Tendermint calls `RequestCommit` to instruct the Application to persist its state.
9. _p_'s Tendermint, optionally, re-checks all outstanding transactions in the mempool
against the newly persisted Application state.
10. _p_'s Tendermint unlocks the mempool &mdash; newly received transactions can now be checked.
11. _p_'s starts consensus for height _h+1_, round 0
-->
## Data Types existing in ABCI
Most of the data structures used in ABCI are shared [common data structures](../core/data_structures.md). In certain cases, ABCI uses different data structures which are documented here:
### Validator
* **Fields**:
| Name | Type | Description | Field Number |
|---------|-------|---------------------------------------------------------------------|--------------|
| address | bytes | [Address](../core/data_structures.md#address) of validator | 1 |
| power | int64 | Voting power of the validator | 3 |
* **Usage**:
* Validator identified by address
* Used in RequestBeginBlock as part of VoteInfo
* Does not include PubKey to avoid sending potentially large quantum pubkeys
over the ABCI
### ValidatorUpdate
* **Fields**:
| Name | Type | Description | Field Number |
|---------|--------------------------------------------------|-------------------------------|--------------|
| pub_key | [Public Key](../core/data_structures.md#pub_key) | Public key of the validator | 1 |
| power | int64 | Voting power of the validator | 2 |
* **Usage**:
* Validator identified by PubKey
* Used to tell Tendermint to update the validator set
### Misbehavior
* **Fields**:
| Name | Type | Description | Field Number |
|--------------------|-------------------------------------------------|------------------------------------------------------------------------------|--------------|
| type | [MisbehaviorType](#misbehaviortype) | Type of the misbehavior. An enum of possible misbehaviors. | 1 |
| validator | [Validator](#validator) | The offending validator | 2 |
| height | int64 | Height when the offense occurred | 3 |
| time | [google.protobuf.Timestamp][protobuf-timestamp] | Timestamp of the block that was committed at height `height` | 4 |
| total_voting_power | int64 | Total voting power of the validator set at height `height` | 5 |
#### MisbehaviorType
* **Fields**
MisbehaviorType is an enum with the listed fields:
| Name | Field Number |
|---------------------|--------------|
| UNKNOWN | 0 |
| DUPLICATE_VOTE | 1 |
| LIGHT_CLIENT_ATTACK | 2 |
### ConsensusParams
* **Fields**:
| Name | Type | Description | Field Number |
|-----------|---------------------------------------------------------------|------------------------------------------------------------------------------|--------------|
| block | [BlockParams](../core/data_structures.md#blockparams) | Parameters limiting the size of a block and time between consecutive blocks. | 1 |
| evidence | [EvidenceParams](../core/data_structures.md#evidenceparams) | Parameters limiting the validity of evidence of byzantine behaviour. | 2 |
| validator | [ValidatorParams](../core/data_structures.md#validatorparams) | Parameters limiting the types of public keys validators can use. | 3 |
| version | [VersionsParams](../core/data_structures.md#versionparams) | The ABCI application version. | 4 |
### ProofOps
* **Fields**:
| Name | Type | Description | Field Number |
|------|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| ops | repeated [ProofOp](#proofop) | List of chained Merkle proofs, of possibly different types. The Merkle root of one op is the value being proven in the next op. The Merkle root of the final op should equal the ultimate root hash being verified against.. | 1 |
### ProofOp
* **Fields**:
| Name | Type | Description | Field Number |
|------|--------|------------------------------------------------|--------------|
| type | string | Type of Merkle proof and how it's encoded. | 1 |
| key | bytes | Key in the Merkle tree that this proof is for. | 2 |
| data | bytes | Encoded Merkle proof for the key. | 3 |
### Snapshot
* **Fields**:
| Name | Type | Description | Field Number |
|----------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| height | uint64 | The height at which the snapshot was taken (after commit). | 1 |
| format | uint32 | An application-specific snapshot format, allowing applications to version their snapshot data format and make backwards-incompatible changes. Tendermint does not interpret this. | 2 |
| chunks | uint32 | The number of chunks in the snapshot. Must be at least 1 (even if empty). | 3 |
| hash | bytes | An arbitrary snapshot hash. Must be equal only for identical snapshots across nodes. Tendermint does not interpret the hash, it only compares them. | 4 |
| metadata | bytes | Arbitrary application metadata, for example chunk hashes or other verification data. | 5 |
* **Usage**:
* Used for state sync snapshots, see the [state sync section](../p2p/messages/state-sync.md) for details.
* A snapshot is considered identical across nodes only if _all_ fields are equal (including
`Metadata`). Chunks may be retrieved from all nodes that have the same snapshot.
* When sent across the network, a snapshot message can be at most 4 MB.
## Data types introduced or modified in ABCI++
### VoteInfo
* **Fields**:
| Name | Type | Description | Field Number |
|-----------------------------|-------------------------|----------------------------------------------------------------|--------------|
| validator | [Validator](#validator) | The validator that sent the vote. | 1 |
| signed_last_block | bool | Indicates whether or not the validator signed the last block. | 2 |
* **Usage**:
* Indicates whether a validator signed the last block, allowing for rewards based on validator availability.
* This information is typically extracted from a proposed or decided block.
### ExtendedVoteInfo
* **Fields**:
| Name | Type | Description | Field Number |
|-------------------|-------------------------|------------------------------------------------------------------------------|--------------|
| validator | [Validator](#validator) | The validator that sent the vote. | 1 |
| signed_last_block | bool | Indicates whether or not the validator signed the last block. | 2 |
| vote_extension | bytes | Reserved for future use. | 3 |
* **Usage**:
* Indicates whether a validator signed the last block, allowing for rewards based on validator availability.
* This information is extracted from Tendermint's data structures in the local process.
* `vote_extension` is reserved for future use when vote extensions are added. Currently, this field is always set to `nil`.
### CommitInfo
* **Fields**:
| Name | Type | Description | Field Number |
|-------|--------------------------------|----------------------------------------------------------------------------------------------|--------------|
| round | int32 | Commit round. Reflects the round at which the block proposer decided in the previous height. | 1 |
| votes | repeated [VoteInfo](#voteinfo) | List of validators' addresses in the last validator set with their voting information. | 2 |
### ExtendedCommitInfo
* **Fields**:
| Name | Type | Description | Field Number |
|-------|------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|--------------|
| round | int32 | Commit round. Reflects the round at which the block proposer decided in the previous height. | 1 |
| votes | repeated [ExtendedVoteInfo](#extendedvoteinfo) | List of validators' addresses in the last validator set with their voting information, including vote extensions. | 2 |
<!--
### ExecTxResult
* **Fields**:
| Name | Type | Description | Field Number |
|------------|-------------------------------------------------------------|-----------------------------------------------------------------------|--------------|
| code | uint32 | Response code. | 1 |
| data | bytes | Result bytes, if any. | 2 |
| log | string | The output of the application's logger. **May be non-deterministic.** | 3 |
| info | string | Additional information. **May be non-deterministic.** | 4 |
| gas_wanted | int64 | Amount of gas requested for transaction. | 5 |
| gas_used | int64 | Amount of gas consumed by transaction. | 6 |
| events | repeated [Event](abci++_basic_concepts.md#events) | Type & Key-Value events for indexing transactions (e.g. by account). | 7 |
| codespace | string | Namespace for the `code`. | 8 |
-->
### ProposalStatus
```proto
enum ProposalStatus {
UNKNOWN = 0; // Unknown status. Returning this from the application is always an error.
ACCEPT = 1; // Status that signals that the application finds the proposal valid.
REJECT = 2; // Status that signals that the application finds the proposal invalid.
}
```
* **Usage**:
* Used within the [ProcessProposal](#processproposal) response.
* If `Status` is `UNKNOWN`, a problem happened in the Application. Tendermint will assume the application is faulty and crash.
* If `Status` is `ACCEPT`, Tendermint accepts the proposal and will issue a Prevote message for it.
* If `Status` is `REJECT`, Tendermint rejects the proposal and will issue a Prevote for `nil` instead.
<!--
### VerifyStatus
```proto
enum VerifyStatus {
UNKNOWN = 0; // Unknown status. Returning this from the application is always an error.
ACCEPT = 1; // Status that signals that the application finds the vote extension valid.
REJECT = 2; // Status that signals that the application finds the vote extension invalid.
}
```
* **Usage**:
* Used within the [VerifyVoteExtension](#verifyvoteextension) response.
* If `Status` is `UNKNOWN`, a problem happened in the Application. Tendermint will assume the application is faulty and crash.
* If `Status` is `ACCEPT`, Tendermint will accept the vote as valid.
* If `Status` is `REJECT`, Tendermint will reject the vote as invalid.
### CanonicalVoteExtension
>**TODO**: This protobuf message definition is not part of the ABCI++ interface, but rather belongs to the
> Precommit message which is broadcast via P2P. So it is to be moved to the relevant section of the spec.
* **Fields**:
| Name | Type | Description | Field Number |
|-----------|--------|--------------------------------------------------------------------------------------------|--------------|
| extension | bytes | Vote extension provided by the Application. | 1 |
| height | int64 | Height in which the extension was provided. | 2 |
| round | int32 | Round in which the extension was provided. | 3 |
| chain_id | string | ID of the blockchain running consensus. | 4 |
| address | bytes | [Address](../core/data_structures.md#address) of the validator that provided the extension | 5 |
* **Usage**:
* Tendermint is to sign the whole data structure and attach it to a Precommit message
* Upon reception, Tendermint validates the sender's signature and sanity-checks the values of `height`, `round`, and `chain_id`.
Then it sends `extension` to the Application via `RequestVerifyVoteExtension` for verification.
-->
[protobuf-timestamp]: https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp

View File

@@ -0,0 +1,243 @@
---
order: 4
title: Tendermint's expected behavior
---
# Tendermint's expected behavior
## Valid method call sequences
This section describes what the Application can expect from Tendermint.
The Tendermint consensus algorithm is designed to protect safety under any network conditions, as long as
less than 1/3 of validators' voting power is byzantine. Most of the time, though, the network will behave
synchronously, no process will fall behind, and there will be no byzantine process. The following describes
what will happen during a block height _h_ in these frequent, benign conditions:
* Tendermint will decide in round 0, for height _h_;
* `PrepareProposal` will be called exactly once at the proposer process of round 0, height _h_;
* `ProcessProposal` will be called exactly once at all processes, and
will return _accept_ in its `Response*`;
<!--
* `ExtendVote` will be called exactly once at all processes;
* `VerifyVoteExtension` will be called exactly _n-1_ times at each validator process, where _n_ is
the number of validators, and will always return _accept_ in its `Response*`;
-->
* `BeginBlock` will be called exactly once at all processes, conveying the same prepared
block header that all calls to `PrepareProposal` and `ProcessProposal` had previously reported for
height _h_; and
* `DeliverTx` will be called exactly once for each transaction within the block.
* `EndBlock` will be called exactly once after `DeliverTx` has been executed for all transactions and marks
the end of processing for the block.
* `Commit` will finally be called exactly once at all processes at the end of height _h_.
However, the Application logic must be ready to cope with any possible run of Tendermint for a given
height, including bad periods (byzantine proposers, network being asynchronous).
In these cases, the sequence of calls to ABCI++ methods may not be so straighforward, but
the Application should still be able to handle them, e.g., without crashing.
The purpose of this section is to define what these sequences look like in a precise way.
As mentioned in the [Basic Concepts](./abci%2B%2B_basic_concepts.md) section, Tendermint
acts as a client of ABCI++ and the Application acts as a server. Thus, it is up to Tendermint to
determine when and in which order the different ABCI++ methods will be called. A well-written
Application design should consider _any_ of these possible sequences.
The following grammar, written in case-sensitive Augmented BackusNaur form (ABNF, specified
in [IETF rfc7405](https://datatracker.ietf.org/doc/html/rfc7405)), specifies all possible
sequences of calls to ABCI++, taken by a correct process, across all heights from the genesis block,
including recovery runs, from the point of view of the Application.
```abnf
start = clean-start / recovery
clean-start = init-chain [state-sync] consensus-exec
state-sync = *state-sync-attempt success-sync info
state-sync-attempt = offer-snapshot *apply-chunk
success-sync = offer-snapshot 1*apply-chunk
recovery = info consensus-exec
consensus-exec = (inf)consensus-height
consensus-height = *consensus-round decide commit
consensus-round = proposer / non-proposer
proposer = prepare-proposal process-proposal
non-proposer = [process-proposal]
decide = begin-block *deliver-txs end-block
init-chain = %s"<InitChain>"
offer-snapshot = %s"<OfferSnapshot>"
apply-chunk = %s"<ApplySnapshotChunk>"
info = %s"<Info>"
prepare-proposal = %s"<PrepareProposal>"
process-proposal = %s"<ProcessProposal>"
begin-block = %s"<BeginBlock>"
deliver-txs = %s"<DeliverTx>"
end-block = %s"<EndBlock>"
commit = %s"<Commit>"
```
<!--
extend-vote = %s"<ExtendVote>"
got-vote = %s"<VerifyVoteExtension>"
decide = %s"<FinalizeBlock>"
-->
We have kept some ABCI methods out of the grammar, in order to keep it as clear and concise as possible.
A common reason for keeping all these methods out is that they all can be called at any point in a sequence defined
by the grammar above. Other reasons depend on the method in question:
* `Echo` and `Flush` are only used for debugging purposes. Further, their handling by the Application should be trivial.
* `CheckTx` is detached from the main method call sequence that drives block execution.
* `Query` provides read-only access to the current Application state, so handling it should also be independent from
block execution.
* Similarly, `ListSnapshots` and `LoadSnapshotChunk` provide read-only access to the Application's previously created
snapshots (if any), and help populate the parameters of `OfferSnapshot` and `ApplySnapshotChunk` at a process performing
state-sync while bootstrapping. Unlike `ListSnapshots` and `LoadSnapshotChunk`, both `OfferSnapshot`
and `ApplySnapshotChunk` _are_ included in the grammar.
Finally, method `Info` is a special case. The method's purpose is three-fold, it can be used
1. as part of handling an RPC call from an external client,
2. as a handshake between Tendermint and the Application upon recovery to check whether any blocks need
to be replayed, and
3. at the end of _state-sync_ to verify that the correct state has been reached.
We have left `Info`'s first purpose out of the grammar for the same reasons as all the others: it can happen
at any time, and has nothing to do with the block execution sequence. The second and third purposes, on the other
hand, are present in the grammar.
Let us now examine the grammar line by line, providing further details.
* When a process starts, it may do so for the first time or after a crash (it is recovering).
>```abnf
>start = clean-start / recovery
>```
* If the process is starting from scratch, Tendermint first calls `InitChain`, then it may optionally
start a _state-sync_ mechanism to catch up with other processes. Finally, it enters normal
consensus execution.
>```abnf
>clean-start = init-chain [state-sync] consensus-exec
>```
* In _state-sync_ mode, Tendermint makes one or more attempts at synchronizing the Application's state.
At the beginning of each attempt, it offers the Application a snapshot found at another process.
If the Application accepts the snapshot, a sequence of calls to `ApplySnapshotChunk` method follow
to provide the Application with all the snapshots needed, in order to reconstruct the state locally.
A successful attempt must provide at least one chunk via `ApplySnapshotChunk`.
At the end of a successful attempt, Tendermint calls `Info` to make sure the recontructed state's
_AppHash_ matches the one in the block header at the corresponding height.
>```abnf
>state-sync = *state-sync-attempt success-sync info
>state-sync-attempt = offer-snapshot *apply-chunk
>success-sync = offer-snapshot 1*apply-chunk
>```
* In recovery mode, Tendermint first calls `Info` to know from which height it needs to replay decisions
to the Application. After this, Tendermint enters nomal consensus execution.
>```abnf
>recovery = info consensus-exec
>```
* The non-terminal `consensus-exec` is a key point in this grammar. It is an infinite sequence of
consensus heights. The grammar is thus an
[omega-grammar](https://dl.acm.org/doi/10.5555/2361476.2361481), since it produces infinite
sequences of terminals (i.e., the API calls).
>```abnf
>consensus-exec = (inf)consensus-height
>```
* A consensus height consists of zero or more rounds before deciding and executing via a call to
`BeginBlock-DeliverTx-EndBlock`, followed by a call to `Commit`. In each round, the sequence of method calls
depends on whether the local process is the proposer or not. Note that, if a height contains zero
rounds, this means the process is replaying an already decided value (catch-up mode).
>```abnf
>consensus-height = *consensus-round decide commit
>consensus-round = proposer / non-proposer
>```
* For every round, if the local process is the proposer of the current round, Tendermint starts by
calling `PrepareProposal`, followed by `ProcessProposal`.
<!--
Then, optionally, the Application is
asked to extend its vote for that round. Calls to `VerifyVoteExtension` can come at any time: the
local process may be slightly late in the current round, or votes may come from a future round
of this height.
-->
>```abnf
>proposer = prepare-proposal process-proposal
>```
* Also for every round, if the local process is _not_ the proposer of the current round, Tendermint
will call `ProcessProposal` at most once.
<!--
At most one call to `ExtendVote` may occur only after
`ProcessProposal` is called. A number of calls to `VerifyVoteExtension` can occur in any order
with respect to `ProcessProposal` and `ExtendVote` throughout the round. The reasons are the same
as above, namely, the process running slightly late in the current round, or votes from future
rounds of this height received.
-->
>```abnf
>non-proposer = [process-proposal]
>```
* Finally, the grammar describes all its terminal symbols, which denote the different ABCI++ method calls that
may appear in a sequence.
>```abnf
>init-chain = %s"<InitChain>"
>offer-snapshot = %s"<OfferSnapshot>"
>apply-chunk = %s"<ApplySnapshotChunk>"
>info = %s"<Info>"
>prepare-proposal = %s"<PrepareProposal>"
>process-proposal = %s"<ProcessProposal>"
>begin-block = %s"<BeginBlock>"
>deliver-txs = %s"<DeliverTx>"
>end-block = %s"<EndBlock>"
>commit = %s"<Commit>"
>```
## Adapting existing Applications that use ABCI
In some cases, an existing Application using the legacy ABCI may need to be adapted to work with ABCI++
with as minimal changes as possible. In this case, of course, ABCI++ will not provide any advange with respect
to the existing implementation, but will keep the same guarantees already provided by ABCI.
Here is how ABCI++ methods should be implemented.
First of all, all the methods that did not change from ABCI to ABCI++, namely `Echo`, `Flush`, `Info`, `InitChain`,
`BeginBlock`, `DerliverTx`, `EndBlock`, `Commit`, `Query`, `CheckTx`, `ListSnapshots`, `LoadSnapshotChunk`, `OfferSnapshot`,
and `ApplySnapshotChunk`, do not need to undergo any changes in their implementation.
As for the new methods:
* `PrepareProposal` must create a list of [transactions](./abci++_methods.md#prepareproposal)
by copying over the transaction list passed in `RequestPrepareProposal.txs`, in the same order.
The Application must check whether the size of all transactions exceeds the byte limit
(`RequestPrepareProposal.max_tx_bytes`). If so, the Application must remove transactions at the
end of the list until the total byte size is at or below the limit.
* `ProcessProposal` must set `ResponseProcessProposal.status` to _accept_ and return.
<!--
* `ExtendVote` is to set `ResponseExtendVote.extension` to an empty byte array and return.
* `VerifyVoteExtension` must set `ResponseVerifyVoteExtension.accept` to _true_ if the extension is
an empty byte array and _false_ otherwise, then return.
-->
<!--
* `FinalizeBlock` is to coalesce the implementation of methods `BeginBlock`, `DeliverTx`, and
`EndBlock`. Legacy applications looking to reuse old code that implemented `DeliverTx` should
wrap the legacy `DeliverTx` logic in a loop that executes one transaction iteration per
transaction in `RequestFinalizeBlock.tx`.
-->
<!--
Finally, `Commit`, which is kept in ABCI++, no longer returns the `AppHash`. It is now up to
`FinalizeBlock` to do so. Thus, a slight refactoring of the old `Commit` implementation will be
needed to move the return of `AppHash` to `FinalizeBlock`.
-->

View File

@@ -1,775 +0,0 @@
---
order: 1
title: Method and Types
---
# Methods and Types
## 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`, `BeginBlock`, `DeliverTx`, `EndBlock`, and `Commit` 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](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.
More details on managing state across connections can be found in the section on
[ABCI Applications](apps.md).
## Errors
The `Query`, `CheckTx` and `DeliverTx` methods include a `Code` field in their `Response*`.
This field 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`.
The `Echo`, `Info`, `InitChain`, `BeginBlock`, `EndBlock`, `Commit` methods
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.
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 be not be added to Tendermint's mempool or it will be removed if
it is already included.
### DeliverTx
The `DeliverTx` ABCI method delivers transactions from Tendermint to the application.
When Tendermint recieves a `ResponseDeliverTx` 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 query 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
The `CheckTx`, `BeginBlock`, `DeliverTx`, `EndBlock` methods include an `Events`
field in their `Response*`. 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 execution.
`Event` values can be used to index transactions and blocks according to what happened
during their execution. Note that the set of events returned for a block from
`BeginBlock` and `EndBlock` are merged. In case both methods return the same
key, only the value defined in `EndBlock` is used.
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.ResponseDeliverTx{
// ...
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 behavior by a network participant. It is the responsibility of Tendermint
to detect such malicious behavior. 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 it on to the application through the ABCI. It is the responsibility of the
application to handle the evidence and exercise punishment.
EvidenceType has the following protobuf format:
```proto
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](https://github.com/tendermint/tendermint/blob/main/spec/core/data_structures.md)
or [accountability](https://github.com/tendermint/tendermint/blob/main/spec/light-client/accountability/)
## 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
BeginBlock, DeliverTx, EndBlock, and Commit. 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 (BeginBlock, DeliverTx, EndBlock, Commit), 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.
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 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, DeliverTx`) 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, the following sequence of methods is executed for each
block:
`BeginBlock, [DeliverTx], EndBlock, Commit`
where one `DeliverTx` is called for each transaction in the block.
The result is an updated application state.
Cryptographic commitments to the results of DeliverTx, EndBlock, and
Commit are included in the header of the next block.
## 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](../spec/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
`AppHash` is retrieved via an `Info` query. The `AppHash` is then compared to
the blockchain's `AppHash` which is verified via [light client verification](../spec/light-client/verification/README.md).
## Messages
### Echo
* **Request**:
* `Message (string)`: A string to echo back
* **Response**:
* `Message (string)`: The input string
* **Usage**:
* Echo a string to test an abci client/server implementation
### Flush
* **Usage**:
* Signals that messages queued on the client should be flushed to
the server. It is called periodically by the client
implementation to ensure asynchronous requests are actually
sent, and is called immediately to make a synchronous request,
which returns when the Flush response comes back.
### Info
* **Request**:
| Name | Type | Description | Field Number |
|---------------|--------|------------------------------------------|--------------|
| version | string | The Tendermint software semantic version | 1 |
| block_version | uint64 | The Tendermint Block Protocol version | 2 |
| p2p_version | uint64 | The Tendermint P2P Protocol version | 3 |
| abci_version | string | The Tendermint ABCI semantic version | 4 |
* **Response**:
| Name | Type | Description | Field Number |
|---------------------|--------|--------------------------------------------------|--------------|
| data | string | Some arbitrary information | 1 |
| version | string | The application software semantic version | 2 |
| app_version | uint64 | The application protocol version | 3 |
| last_block_height | int64 | Latest block for which the app has called Commit | 4 |
| last_block_app_hash | bytes | Latest result of Commit | 5 |
* **Usage**:
* Return information about the application state.
* Used to sync Tendermint with the application during a handshake
that happens on startup.
* The returned `app_version` will be included in the Header of every block.
* Tendermint expects `last_block_app_hash` and `last_block_height` to
be updated during `Commit`, ensuring that `Commit` is never
called twice for the same block height.
> Note: Semantic version is a reference to [semantic versioning](https://semver.org/). Semantic versions in info will be displayed as X.X.x.
### InitChain
* **Request**:
| Name | Type | Description | Field Number |
|------------------|--------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------|--------------|
| time | [google.protobuf.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp) | Genesis time | 1 |
| chain_id | string | ID of the blockchain. | 2 |
| consensus_params | [ConsensusParams](#consensusparams) | Initial consensus-critical parameters. | 3 |
| validators | repeated [ValidatorUpdate](#validatorupdate) | Initial genesis validators, sorted by voting power. | 4 |
| app_state_bytes | bytes | Serialized initial application state. JSON bytes. | 5 |
| initial_height | int64 | Height of the initial block (typically `1`). | 6 |
* **Response**:
| Name | Type | Description | Field Number |
|------------------|----------------------------------------------|-------------------------------------------------|--------------|
| consensus_params | [ConsensusParams](#consensusparams) | Initial consensus-critical parameters (optional | 1 |
| validators | repeated [ValidatorUpdate](#validatorupdate) | Initial validator set (optional). | 2 |
| app_hash | bytes | Initial application hash. | 3 |
* **Usage**:
* Called once upon genesis.
* If ResponseInitChain.Validators is empty, the initial validator set will be the RequestInitChain.Validators
* If ResponseInitChain.Validators is not empty, it will be the initial
validator set (regardless of what is in RequestInitChain.Validators).
* This allows the app to decide if it wants to accept the initial validator
set proposed by tendermint (ie. in the genesis file), or if it wants to use
a different one (perhaps computed based on some application specific
information in the genesis file).
### Query
* **Request**:
| Name | Type | Description | Field Number |
|--------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| data | bytes | Raw query bytes. Can be used with or in lieu of Path. | 1 |
| path | string | Path field of the request URI. Can be used with or in lieu of `data`. Apps MUST interpret `/store` as a query by key on the underlying store. The key SHOULD be specified in the `data` field. Apps SHOULD allow queries over specific types like `/accounts/...` or `/votes/...` | 2 |
| height | int64 | The block height for which you want the query (default=0 returns data for the latest committed block). Note that this is the height of the block containing the application's Merkle root hash, which represents the state as it was after committing the block at Height-1 | 3 |
| prove | bool | Return Merkle proof with response if possible | 4 |
* **Response**:
| Name | Type | Description | Field Number |
|-----------|-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| code | uint32 | Response code. | 1 |
| log | string | The output of the application's logger. **May be non-deterministic.** | 3 |
| info | string | Additional information. **May be non-deterministic.** | 4 |
| index | int64 | The index of the key in the tree. | 5 |
| key | bytes | The key of the matching data. | 6 |
| value | bytes | The value of the matching data. | 7 |
| proof_ops | [ProofOps](#proofops) | Serialized proof for the value data, if requested, to be verified against the `app_hash` for the given Height. | 8 |
| height | int64 | The block height from which data was derived. Note that this is the height of the block containing the application's Merkle root hash, which represents the state as it was after committing the block at Height-1 | 9 |
| codespace | string | Namespace for the `code`. | 10 |
* **Usage**:
* Query for data from the application at current or past height.
* Optionally return Merkle proof.
* Merkle proof includes self-describing `type` field to support many types
of Merkle trees and encoding formats.
### BeginBlock
* **Request**:
| Name | Type | Description | Field Number |
|----------------------|---------------------------------------------|-------------------------------------------------------------------------------------------------------------------|--------------|
| hash | bytes | The block's hash. This can be derived from the block header. | 1 |
| header | [Header](../core/data_structures.md#header) | The block header. | 2 |
| last_commit_info | [LastCommitInfo](#lastcommitinfo) | Info about the last commit, including the round, and the list of validators and which ones signed the last block. | 3 |
| byzantine_validators | repeated [Evidence](#evidence) | List of evidence of validators that acted maliciously. | 4 |
* **Response**:
| Name | Type | Description | Field Number |
|--------|---------------------------|-------------------------------------|--------------|
| events | repeated [Event](#events) | type & Key-Value events for indexing | 1 |
* **Usage**:
* Signals the beginning of a new block.
* Called prior to any `DeliverTx` method calls.
* The header contains the height, timestamp, and more - it exactly matches the
Tendermint block header. We may seek to generalize this in the future.
* The `LastCommitInfo` and `ByzantineValidators` can be used to determine
rewards and punishments for the validators.
### CheckTx
* **Request**:
| Name | Type | Description | Field Number |
|------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| tx | bytes | The request transaction bytes | 1 |
| type | CheckTxType | One of `CheckTx_New` or `CheckTx_Recheck`. `CheckTx_New` is the default and means that a full check of the tranasaction is required. `CheckTx_Recheck` types are used when the mempool is initiating a normal recheck of a transaction. | 2 |
* **Response**:
| Name | Type | Description | Field Number |
|------------|---------------------------|-----------------------------------------------------------------------|--------------|
| code | uint32 | Response code. | 1 |
| data | bytes | Result bytes, if any. | 2 |
| log | string | The output of the application's logger. **May be non-deterministic.** | 3 |
| info | string | Additional information. **May be non-deterministic.** | 4 |
| gas_wanted | int64 | Amount of gas requested for transaction. | 5 |
| gas_used | int64 | Amount of gas consumed by transaction. | 6 |
| events | repeated [Event](#events) | Type & Key-Value events for indexing transactions (eg. by account). | 7 |
| codespace | string | Namespace for the `code`. | 8 |
| sender | string | The transaction's sender (e.g. the signer) | 9 |
| priority | int64 | The transaction's priority (for mempool ordering) | 10 |
* **Usage**:
* Technically optional - not involved in processing blocks.
* Guardian of the mempool: every node runs `CheckTx` before letting a
transaction into its local mempool.
* The transaction may come from an external user or another node
* `CheckTx` validates the transaction against the current state of the application,
for example, checking signatures and account balances, but does not apply any
of the state changes described in the transaction.
not running code in a virtual machine.
* Transactions where `ResponseCheckTx.Code != 0` will be rejected - they will not be broadcast to
other nodes or included in a proposal block.
* Tendermint attributes no other value to the response code
### DeliverTx
* **Request**:
| Name | Type | Description | Field Number |
|------|-------|--------------------------------|--------------|
| tx | bytes | The request transaction bytes. | 1 |
* **Response**:
| Name | Type | Description | Field Number |
|------------|---------------------------|-----------------------------------------------------------------------|--------------|
| code | uint32 | Response code. | 1 |
| data | bytes | Result bytes, if any. | 2 |
| log | string | The output of the application's logger. **May be non-deterministic.** | 3 |
| info | string | Additional information. **May be non-deterministic.** | 4 |
| gas_wanted | int64 | Amount of gas requested for transaction. | 5 |
| gas_used | int64 | Amount of gas consumed by transaction. | 6 |
| events | repeated [Event](#events) | Type & Key-Value events for indexing transactions (eg. by account). | 7 |
| codespace | string | Namespace for the `code`. | 8 |
* **Usage**:
* [**Required**] The core method of the application.
* When `DeliverTx` is called, the application must execute the transaction in full before returning control to Tendermint.
* `ResponseDeliverTx.Code == 0` only if the transaction is fully valid.
### EndBlock
* **Request**:
| Name | Type | Description | Field Number |
|--------|-------|------------------------------------|--------------|
| height | int64 | Height of the block just executed. | 1 |
* **Response**:
| Name | Type | Description | Field Number |
|-------------------------|----------------------------------------------|-----------------------------------------------------------------|--------------|
| validator_updates | repeated [ValidatorUpdate](#validatorupdate) | Changes to validator set (set voting power to 0 to remove). | 1 |
| consensus_param_updates | [ConsensusParams](#consensusparams) | Changes to consensus-critical time, size, and other parameters. | 2 |
| events | repeated [Event](#events) | Type & Key-Value events for indexing | 3 |
* **Usage**:
* Signals the end of a block.
* Called after all the transactions for the current block have been delivered, prior to the block's `Commit` message.
* Optional `validator_updates` triggered by block `H`. These updates affect validation
for blocks `H+1`, `H+2`, and `H+3`.
* Heights following a validator update are affected in the following way:
* `H+1`: `NextValidatorsHash` includes the new `validator_updates` value.
* `H+2`: The validator set change takes effect and `ValidatorsHash` is updated.
* `H+3`: `LastCommitInfo` is changed to include the altered validator set.
* `consensus_param_updates` returned for block `H` apply to the consensus
params for block `H+1`. For more information on the consensus parameters,
see the [application spec entry on consensus parameters](../spec/abci/apps.md#consensus-parameters).
### Commit
* **Request**:
| Name | Type | Description | Field Number |
|--------|-------|------------------------------------|--------------|
Commit signals the application to persist application state. It takes no parameters.
* **Response**:
| Name | Type | Description | Field Number |
|---------------|-------|------------------------------------------------------------------------|--------------|
| data | bytes | The Merkle root hash of the application state. | 2 |
| retain_height | int64 | Blocks below this height may be removed. Defaults to `0` (retain all). | 3 |
* **Usage**:
* Signal the application to persist the application state.
* Return an (optional) Merkle root hash of the application state
* `ResponseCommit.Data` is included as the `Header.AppHash` in the next block
* it may be empty
* Later calls to `Query` can return proofs about the application state anchored
in this Merkle root hash
* Note developers can return whatever they want here (could be nothing, or a
constant string, etc.), so long as it is deterministic - it must not be a
function of anything that did not come from the
BeginBlock/DeliverTx/EndBlock methods.
* Use `RetainHeight` with caution! If all nodes in the network remove historical
blocks then this data is permanently lost, and no new nodes will be able to
join the network and bootstrap. Historical blocks may also be required for
other purposes, e.g. auditing, replay of non-persisted heights, light client
verification, and so on.
### ListSnapshots
* **Request**:
| Name | Type | Description | Field Number |
|--------|-------|------------------------------------|--------------|
Empty request asking the application for a list of snapshots.
* **Response**:
| Name | Type | Description | Field Number |
|-----------|--------------------------------|--------------------------------|--------------|
| snapshots | repeated [Snapshot](#snapshot) | List of local state snapshots. | 1 |
* **Usage**:
* Used during state sync to discover available snapshots on peers.
* See `Snapshot` data type for details.
### LoadSnapshotChunk
* **Request**:
| Name | Type | Description | Field Number |
|--------|--------|-----------------------------------------------------------------------|--------------|
| height | uint64 | The height of the snapshot the chunks belongs to. | 1 |
| format | uint32 | The application-specific format of the snapshot the chunk belongs to. | 2 |
| chunk | uint32 | The chunk index, starting from `0` for the initial chunk. | 3 |
* **Response**:
| Name | Type | Description | Field Number |
|-------|-------|-------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| chunk | bytes | The binary chunk contents, in an arbitray format. Chunk messages cannot be larger than 16 MB _including metadata_, so 10 MB is a good starting point. | 1 |
* **Usage**:
* Used during state sync to retrieve snapshot chunks from peers.
### OfferSnapshot
* **Request**:
| Name | Type | Description | Field Number |
|----------|-----------------------|--------------------------------------------------------------------------|--------------|
| snapshot | [Snapshot](#snapshot) | The snapshot offered for restoration. | 1 |
| app_hash | bytes | The light client-verified app hash for this height, from the blockchain. | 2 |
* **Response**:
| Name | Type | Description | Field Number |
|--------|-------------------|-----------------------------------|--------------|
| result | [Result](#result) | The result of the snapshot offer. | 1 |
#### Result
```proto
enum Result {
UNKNOWN = 0; // Unknown result, abort all snapshot restoration
ACCEPT = 1; // Snapshot is accepted, start applying chunks.
ABORT = 2; // Abort snapshot restoration, and don't try any other snapshots.
REJECT = 3; // Reject this specific snapshot, try others.
REJECT_FORMAT = 4; // Reject all snapshots with this `format`, try others.
REJECT_SENDER = 5; // Reject all snapshots from all senders of this snapshot, try others.
}
```
* **Usage**:
* `OfferSnapshot` is called when bootstrapping a node using state sync. The application may
accept or reject snapshots as appropriate. Upon accepting, Tendermint will retrieve and
apply snapshot chunks via `ApplySnapshotChunk`. The application may also choose to reject a
snapshot in the chunk response, in which case it should be prepared to accept further
`OfferSnapshot` calls.
* Only `AppHash` can be trusted, as it has been verified by the light client. Any other data
can be spoofed by adversaries, so applications should employ additional verification schemes
to avoid denial-of-service attacks. The verified `AppHash` is automatically checked against
the restored application at the end of snapshot restoration.
* For more information, see the `Snapshot` data type or the [state sync section](../spec/p2p/messages/state-sync.md).
### ApplySnapshotChunk
* **Request**:
| Name | Type | Description | Field Number |
|--------|--------|-----------------------------------------------------------------------------|--------------|
| index | uint32 | The chunk index, starting from `0`. Tendermint applies chunks sequentially. | 1 |
| chunk | bytes | The binary chunk contents, as returned by `LoadSnapshotChunk`. | 2 |
| sender | string | The P2P ID of the node who sent this chunk. | 3 |
* **Response**:
| Name | Type | Description | Field Number |
|----------------|---------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| result | Result (see below) | The result of applying this chunk. | 1 |
| refetch_chunks | repeated uint32 | Refetch and reapply the given chunks, regardless of `result`. Only the listed chunks will be refetched, and reapplied in sequential order. | 2 |
| reject_senders | repeated string | Reject the given P2P senders, regardless of `Result`. Any chunks already applied will not be refetched unless explicitly requested, but queued chunks from these senders will be discarded, and new chunks or other snapshots rejected. | 3 |
```proto
enum Result {
UNKNOWN = 0; // Unknown result, abort all snapshot restoration
ACCEPT = 1; // The chunk was accepted.
ABORT = 2; // Abort snapshot restoration, and don't try any other snapshots.
RETRY = 3; // Reapply this chunk, combine with `RefetchChunks` and `RejectSenders` as appropriate.
RETRY_SNAPSHOT = 4; // Restart this snapshot from `OfferSnapshot`, reusing chunks unless instructed otherwise.
REJECT_SNAPSHOT = 5; // Reject this snapshot, try a different one.
}
```
* **Usage**:
* The application can choose to refetch chunks and/or ban P2P peers as appropriate. Tendermint
will not do this unless instructed by the application.
* The application may want to verify each chunk, e.g. by attaching chunk hashes in
`Snapshot.Metadata` and/or incrementally verifying contents against `AppHash`.
* When all chunks have been accepted, Tendermint will make an ABCI `Info` call to verify that
`LastBlockAppHash` and `LastBlockHeight` matches the expected values, and record the
`AppVersion` in the node state. It then switches to block sync or consensus and joins the
network.
* If Tendermint is unable to retrieve the next chunk after some time (e.g. because no suitable
peers are available), it will reject the snapshot and try a different one via `OfferSnapshot`.
The application should be prepared to reset and accept it or abort as appropriate.
## Data Types
Most of the data structures used in ABCI are shared [common data structures](../spec/core/data_structures.md). In certain cases, ABCI uses different data structures which are documented here:
### Validator
* **Fields**:
| Name | Type | Description | Field Number |
|---------|-------|---------------------------------------------------------------------|--------------|
| address | bytes | [Address](../core/data_structures.md#address) of validator | 1 |
| power | int64 | Voting power of the validator | 3 |
* **Usage**:
* Validator identified by address
* Used in RequestBeginBlock as part of VoteInfo
* Does not include PubKey to avoid sending potentially large quantum pubkeys
over the ABCI
### ValidatorUpdate
* **Fields**:
| Name | Type | Description | Field Number |
|---------|--------------------------------------------------|-------------------------------|--------------|
| pub_key | [Public Key](../core/data_structures.md#pub_key) | Public key of the validator | 1 |
| power | int64 | Voting power of the validator | 2 |
* **Usage**:
* Validator identified by PubKey
* Used to tell Tendermint to update the validator set
### VoteInfo
* **Fields**:
| Name | Type | Description | Field Number |
|-------------------|-------------------------|--------------------------------------------------------------|--------------|
| validator | [Validator](#validator) | A validator | 1 |
| signed_last_block | bool | Indicates whether or not the validator signed the last block | 2 |
* **Usage**:
* Indicates whether a validator signed the last block, allowing for rewards
based on validator availability
### Evidence
* **Fields**:
| Name | Type | Description | Field Number |
|--------------------|--------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------|--------------|
| type | [EvidenceType](#evidencetype) | Type of the evidence. An enum of possible evidence's. | 1 |
| validator | [Validator](#validator) | The offending validator | 2 |
| height | int64 | Height when the offense occurred | 3 |
| time | [google.protobuf.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp) | Time of the block that was committed at the height that the offense occurred | 4 |
| total_voting_power | int64 | Total voting power of the validator set at height `Height` | 5 |
#### EvidenceType
* **Fields**
EvidenceType is an enum with the listed fields:
| Name | Field Number |
|---------------------|--------------|
| UNKNOWN | 0 |
| DUPLICATE_VOTE | 1 |
| LIGHT_CLIENT_ATTACK | 2 |
### LastCommitInfo
* **Fields**:
| Name | Type | Description | Field Number |
|-------|--------------------------------|-----------------------------------------------------------------------------------------------------------------------|--------------|
| round | int32 | Commit round. Reflects the total amount of rounds it took to come to consensus for the current block. | 1 |
| votes | repeated [VoteInfo](#voteinfo) | List of validators addresses in the last validator set with their voting power and whether or not they signed a vote. | 2 |
### ConsensusParams
* **Fields**:
| Name | Type | Description | Field Number |
|-----------|---------------------------------------------------------------|------------------------------------------------------------------------------|--------------|
| block | [BlockParams](../core/data_structures.md#blockparams) | Parameters limiting the size of a block and time between consecutive blocks. | 1 |
| evidence | [EvidenceParams](../core/data_structures.md#evidenceparams) | Parameters limiting the validity of evidence of byzantine behavior. | 2 |
| validator | [ValidatorParams](../core/data_structures.md#validatorparams) | Parameters limiting the types of public keys validators can use. | 3 |
| version | [VersionsParams](../core/data_structures.md#versionparams) | The ABCI application version. | 4 |
### ProofOps
* **Fields**:
| Name | Type | Description | Field Number |
|------|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| ops | repeated [ProofOp](#proofop) | List of chained Merkle proofs, of possibly different types. The Merkle root of one op is the value being proven in the next op. The Merkle root of the final op should equal the ultimate root hash being verified against.. | 1 |
### ProofOp
* **Fields**:
| Name | Type | Description | Field Number |
|------|--------|------------------------------------------------|--------------|
| type | string | Type of Merkle proof and how it's encoded. | 1 |
| key | bytes | Key in the Merkle tree that this proof is for. | 2 |
| data | bytes | Encoded Merkle proof for the key. | 3 |
### Snapshot
* **Fields**:
| Name | Type | Description | Field Number |
|----------|--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|
| height | uint64 | The height at which the snapshot was taken (after commit). | 1 |
| format | uint32 | An application-specific snapshot format, allowing applications to version their snapshot data format and make backwards-incompatible changes. Tendermint does not interpret this. | 2 |
| chunks | uint32 | The number of chunks in the snapshot. Must be at least 1 (even if empty). | 3 |
| hash | bytes | TAn arbitrary snapshot hash. Must be equal only for identical snapshots across nodes. Tendermint does not interpret the hash, it only compares them. | 3 |
| metadata | bytes | Arbitrary application metadata, for example chunk hashes or other verification data. | 3 |
* **Usage**:
* Used for state sync snapshots, see the [state sync section](../spec/p2p/messages/state-sync.md) for details.
* A snapshot is considered identical across nodes only if _all_ fields are equal (including
`Metadata`). Chunks may be retrieved from all nodes that have the same snapshot.
* When sent across the network, a snapshot message can be at most 4 MB.

View File

@@ -1,671 +0,0 @@
---
order: 2
title: Applications
---
# Applications
Please ensure you've first read the spec for [ABCI Methods and Types](abci.md)
Here we cover the following components of ABCI applications:
- [Connection State](#connection-state) - the interplay between ABCI connections and application state
and the differences between `CheckTx` and `DeliverTx`.
- [Transaction Results](#transaction-results) - rules around transaction
results and validity
- [Validator Set Updates](#validator-updates) - how validator sets are
changed during `InitChain` and `EndBlock`
- [Query](#query) - standards for using the `Query` method and proofs about the
application state
- [Crash Recovery](#crash-recovery) - handshake protocol to synchronize
Tendermint and the application on startup.
- [State Sync](#state-sync) - rapid bootstrapping of new nodes by restoring state machine snapshots
## Connection State
Since Tendermint maintains four concurrent ABCI connections, it is typical
for an application to maintain a distinct state for each, and for the states to
be synchronized during `Commit`.
### Concurrency
In principle, each of the four ABCI connections operate concurrently with one
another. This means applications need to ensure access to state is
thread safe. In practice, both the
[default in-process ABCI client](https://github.com/tendermint/tendermint/blob/v0.34.4/abci/client/local_client.go#L18)
and the
[default Go ABCI
server](https://github.com/tendermint/tendermint/blob/v0.34.4/abci/server/socket_server.go#L32)
use global locks across all connections, so they are not
concurrent at all. This means if your app is written in Go, and compiled in-process with Tendermint
using the default `NewLocalClient`, or run out-of-process using the default `SocketServer`,
ABCI messages from all connections will be linearizable (received one at a
time).
The existence of this global mutex means Go application developers can get
thread safety for application state by routing *all* reads and writes through the ABCI
system. Thus it may be *unsafe* to expose application state directly to an RPC
interface, and unless explicit measures are taken, all queries should be routed through the ABCI Query method.
### BeginBlock
The BeginBlock request can be used to run some code at the beginning of
every block. It also allows Tendermint to send the current block hash
and header to the application, before it sends any of the transactions.
The app should remember the latest height and header (ie. from which it
has run a successful Commit) so that it can tell Tendermint where to
pick up from when it restarts. See information on the Handshake, below.
### Commit
Application state should only be persisted to disk during `Commit`.
Before `Commit` is called, Tendermint locks and flushes the mempool so that no new messages will
be received on the mempool connection. This provides an opportunity to safely update all four connection
states to the latest committed state at once.
When `Commit` completes, it unlocks the mempool.
WARNING: if the ABCI app logic processing the `Commit` message sends a
`/broadcast_tx_sync` or `/broadcast_tx_commit` and waits for the response
before proceeding, it will deadlock. Executing those `broadcast_tx` calls
involves acquiring a lock that is held during the `Commit` call, so it's not
possible. If you make the call to the `broadcast_tx` endpoints concurrently,
that's no problem, it just can't be part of the sequential logic of the
`Commit` function.
### Consensus Connection
The Consensus Connection should maintain a `DeliverTxState` - the working state
for block execution. It should be updated by the calls to `BeginBlock`, `DeliverTx`,
and `EndBlock` during block execution and committed to disk as the "latest
committed state" during `Commit`.
Updates made to the `DeliverTxState` by each method call must be readable by each subsequent method -
ie. the updates are linearizable.
### Mempool Connection
The mempool Connection should maintain a `CheckTxState`
to sequentially process pending transactions in the mempool that have
not yet been committed. It should be initialized to the latest committed state
at the end of every `Commit`.
Before calling `Commit`, Tendermint will lock and flush the mempool connection,
ensuring that all existing CheckTx are responded to and no new ones can begin.
The `CheckTxState` may be updated concurrently with the `DeliverTxState`, as
messages may be sent concurrently on the Consensus and Mempool connections.
After `Commit`, while still holding the mempool lock, CheckTx is run again on all transactions that remain in the
node's local mempool after filtering those included in the block.
An additional `Type` parameter is made available to the CheckTx function that
indicates whether an incoming transaction is new (`CheckTxType_New`), or a
recheck (`CheckTxType_Recheck`).
Finally, after re-checking transactions in the mempool, Tendermint will unlock
the mempool connection. New transactions are once again able to be processed through CheckTx.
Note that CheckTx is just a weak filter to keep invalid transactions out of the block chain.
CheckTx doesn't have to check everything that affects transaction validity; the
expensive things can be skipped. It's weak because a Byzantine node doesn't
care about CheckTx; it can propose a block full of invalid transactions if it wants.
#### Replay Protection
To prevent old transactions from being replayed, CheckTx must implement
replay protection.
It is possible for old transactions to be sent to the application. So
it is important CheckTx implements some logic to handle them.
### Query Connection
The Info Connection should maintain a `QueryState` for answering queries from the user,
and for initialization when Tendermint first starts up (both described further
below).
It should always contain the latest committed state associated with the
latest committed block.
`QueryState` should be set to the latest `DeliverTxState` at the end of every `Commit`,
after the full block has been processed and the state committed to disk.
Otherwise it should never be modified.
Tendermint Core currently uses the Query connection to filter peers upon
connecting, according to IP address or node ID. For instance,
returning non-OK ABCI response to either of the following queries will
cause Tendermint to not connect to the corresponding peer:
- `p2p/filter/addr/<ip addr>`, where `<ip addr>` is an IP address.
- `p2p/filter/id/<id>`, where `<is>` is the hex-encoded node ID (the hash of
the node's p2p pubkey).
Note: these query formats are subject to change!
### Snapshot Connection
The Snapshot Connection is optional, and is only used to serve state sync snapshots for other nodes
and/or restore state sync snapshots to a local node being bootstrapped.
For more information, see [the state sync section of this document](#state-sync).
## Transaction Results
The `Info` and `Log` fields are non-deterministic values for debugging/convenience purposes
that are otherwise ignored.
The `Data` field must be strictly deterministic, but can be arbitrary data.
### Gas
Ethereum introduced the notion of `gas` as an abstract representation of the
cost of resources used by nodes when processing transactions. Every operation in the
Ethereum Virtual Machine uses some amount of gas, and gas can be accepted at a market-variable price.
Users propose a maximum amount of gas for their transaction; if the tx uses less, they get
the difference credited back. Tendermint adopts a similar abstraction,
though uses it only optionally and weakly, allowing applications to define
their own sense of the cost of execution.
In Tendermint, the [ConsensusParams.Block.MaxGas](../proto/types/params.proto) limits the amount of `gas` that can be used in a block.
The default value is `-1`, meaning no limit, or that the concept of gas is
meaningless.
Responses contain a `GasWanted` and `GasUsed` field. The former is the maximum
amount of gas the sender of a tx is willing to use, and the later is how much it actually
used. Applications should enforce that `GasUsed <= GasWanted` - ie. tx execution
should halt before it can use more resources than it requested.
When `MaxGas > -1`, Tendermint enforces the following rules:
- `GasWanted <= MaxGas` for all txs in the mempool
- `(sum of GasWanted in a block) <= MaxGas` when proposing a block
If `MaxGas == -1`, no rules about gas are enforced.
Note that Tendermint does not currently enforce anything about Gas in the consensus, only the mempool.
This means it does not guarantee that committed blocks satisfy these rules!
It is the application's responsibility to return non-zero response codes when gas limits are exceeded.
The `GasUsed` field is ignored completely by Tendermint. That said, applications should enforce:
- `GasUsed <= GasWanted` for any given transaction
- `(sum of GasUsed in a block) <= MaxGas` for every block
In the future, we intend to add a `Priority` field to the responses that can be
used to explicitly prioritize txs in the mempool for inclusion in a block
proposal. See [#1861](https://github.com/tendermint/tendermint/issues/1861).
### CheckTx
If `Code != 0`, it will be rejected from the mempool and hence
not broadcasted to other peers and not included in a proposal block.
`Data` contains the result of the CheckTx transaction execution, if any. It is
semantically meaningless to Tendermint.
`Events` include any events for the execution, though since the transaction has not
been committed yet, they are effectively ignored by Tendermint.
### DeliverTx
DeliverTx is the workhorse of the blockchain. Tendermint sends the
DeliverTx requests asynchronously but in order, and relies on the
underlying socket protocol (ie. TCP) to ensure they are received by the
app in order. They have already been ordered in the global consensus by
the Tendermint protocol.
If DeliverTx returns `Code != 0`, the transaction will be considered invalid,
though it is still included in the block.
DeliverTx also returns a [Code, Data, and Log](../../proto/abci/types.proto#L189-L191).
`Data` contains the result of the CheckTx transaction execution, if any. It is
semantically meaningless to Tendermint.
Both the `Code` and `Data` are included in a structure that is hashed into the
`LastResultsHash` of the next block header.
`Events` include any events for the execution, which Tendermint will use to index
the transaction by. This allows transactions to be queried according to what
events took place during their execution.
## Updating the Validator Set
The application may set the validator set during InitChain, and may update it during
EndBlock.
Note that the maximum total power of the validator set is bounded by
`MaxTotalVotingPower = MaxInt64 / 8`. Applications are responsible for ensuring
they do not make changes to the validator set that cause it to exceed this
limit.
Additionally, applications must ensure that a single set of updates does not contain any duplicates -
a given public key can only appear once within a given update. If an update includes
duplicates, the block execution will fail irrecoverably.
### InitChain
The `InitChain` method can return a list of validators.
If the list is empty, Tendermint will use the validators loaded in the genesis
file.
If the list returned by `InitChain` is not empty, Tendermint will use its contents as the validator set.
This way the application can set the initial validator set for the
blockchain.
### EndBlock
Updates to the Tendermint validator set can be made by returning
`ValidatorUpdate` objects in the `ResponseEndBlock`:
```protobuf
message ValidatorUpdate {
tendermint.crypto.keys.PublicKey pub_key
int64 power
}
message PublicKey {
oneof {
ed25519 bytes = 1;
}
```
The `pub_key` currently supports only one type:
- `type = "ed25519"`
The `power` is the new voting power for the validator, with the
following rules:
- power must be non-negative
- if power is 0, the validator must already exist, and will be removed from the
validator set
- if power is non-0:
- if the validator does not already exist, it will be added to the validator
set with the given power
- if the validator does already exist, its power will be adjusted to the given power
- the total power of the new validator set must not exceed MaxTotalVotingPower
Note the updates returned in block `H` will only take effect at block `H+2`.
## Consensus Parameters
ConsensusParams enforce certain limits in the blockchain, like the maximum size
of blocks, amount of gas used in a block, and the maximum acceptable age of
evidence. They can be set in InitChain and updated in EndBlock.
### BlockParams.MaxBytes
The maximum size of a complete Protobuf encoded block.
This is enforced by Tendermint consensus.
This implies a maximum transaction size that is this MaxBytes, less the expected size of
the header, the validator set, and any included evidence in the block.
Must have `0 < MaxBytes < 100 MB`.
### BlockParams.MaxGas
The maximum of the sum of `GasWanted` that will be allowed in a proposed block.
This is *not* enforced by Tendermint consensus.
It is left to the app to enforce (ie. if txs are included past the
limit, they should return non-zero codes). It is used by Tendermint to limit the
txs included in a proposed block.
Must have `MaxGas >= -1`.
If `MaxGas == -1`, no limit is enforced.
### EvidenceParams.MaxAgeDuration
This is the maximum age of evidence in time units.
This is enforced by Tendermint consensus.
If a block includes evidence older than this (AND the evidence was created more
than `MaxAgeNumBlocks` ago), the block will be rejected (validators won't vote
for it).
Must have `MaxAgeDuration > 0`.
### EvidenceParams.MaxAgeNumBlocks
This is the maximum age of evidence in blocks.
This is enforced by Tendermint consensus.
If a block includes evidence older than this (AND the evidence was created more
than `MaxAgeDuration` ago), the block will be rejected (validators won't vote
for it).
Must have `MaxAgeNumBlocks > 0`.
### EvidenceParams.MaxNum
This is the maximum number of evidence that can be committed to a single block.
The product of this and the `MaxEvidenceBytes` must not exceed the size of
a block minus it's overhead ( ~ `MaxBytes`).
Must have `MaxNum > 0`.
### Updates
The application may set the ConsensusParams during InitChain, and update them during
EndBlock. If the ConsensusParams is empty, it will be ignored. Each field
that is not empty will be applied in full. For instance, if updating the
Block.MaxBytes, applications must also set the other Block fields (like
Block.MaxGas), even if they are unchanged, as they will otherwise cause the
value to be updated to 0.
#### InitChain
ResponseInitChain includes a ConsensusParams.
If ConsensusParams is nil, Tendermint will use the params loaded in the genesis
file. If ConsensusParams is not nil, Tendermint will use it.
This way the application can determine the initial consensus params for the
blockchain.
#### EndBlock
ResponseEndBlock includes a ConsensusParams.
If ConsensusParams nil, Tendermint will do nothing.
If ConsensusParam is not nil, Tendermint will use it.
This way the application can update the consensus params over time.
Note the updates returned in block `H` will take effect right away for block
`H+1`.
## Query
Query is a generic method with lots of flexibility to enable diverse sets
of queries on application state. Tendermint makes use of Query to filter new peers
based on ID and IP, and exposes Query to the user over RPC.
Note that calls to Query are not replicated across nodes, but rather query the
local node's state - hence they may return stale reads. For reads that require
consensus, use a transaction.
The most important use of Query is to return Merkle proofs of the application state at some height
that can be used for efficient application-specific light-clients.
Note Tendermint has technically no requirements from the Query
message for normal operation - that is, the ABCI app developer need not implement
Query functionality if they do not wish too.
### Query Proofs
The Tendermint block header includes a number of hashes, each providing an
anchor for some type of proof about the blockchain. The `ValidatorsHash` enables
quick verification of the validator set, the `DataHash` gives quick
verification of the transactions included in the block, etc.
The `AppHash` is unique in that it is application specific, and allows for
application-specific Merkle proofs about the state of the application.
While some applications keep all relevant state in the transactions themselves
(like Bitcoin and its UTXOs), others maintain a separated state that is
computed deterministically *from* transactions, but is not contained directly in
the transactions themselves (like Ethereum contracts and accounts).
For such applications, the `AppHash` provides a much more efficient way to verify light-client proofs.
ABCI applications can take advantage of more efficient light-client proofs for
their state as follows:
- return the Merkle root of the deterministic application state in
`ResponseCommit.Data`. This Merkle root will be included as the `AppHash` in the next block.
- return efficient Merkle proofs about that application state in `ResponseQuery.Proof`
that can be verified using the `AppHash` of the corresponding block.
For instance, this allows an application's light-client to verify proofs of
absence in the application state, something which is much less efficient to do using the block hash.
Some applications (eg. Ethereum, Cosmos-SDK) have multiple "levels" of Merkle trees,
where the leaves of one tree are the root hashes of others. To support this, and
the general variability in Merkle proofs, the `ResponseQuery.Proof` has some minimal structure:
```protobuf
message ProofOps {
repeated ProofOp ops
}
message ProofOp {
string type = 1;
bytes key = 2;
bytes data = 3;
}
```
Each `ProofOp` contains a proof for a single key in a single Merkle tree, of the specified `type`.
This allows ABCI to support many different kinds of Merkle trees, encoding
formats, and proofs (eg. of presence and absence) just by varying the `type`.
The `data` contains the actual encoded proof, encoded according to the `type`.
When verifying the full proof, the root hash for one ProofOp is the value being
verified for the next ProofOp in the list. The root hash of the final ProofOp in
the list should match the `AppHash` being verified against.
### Peer Filtering
When Tendermint connects to a peer, it sends two queries to the ABCI application
using the following paths, with no additional data:
- `/p2p/filter/addr/<IP:PORT>`, where `<IP:PORT>` denote the IP address and
the port of the connection
- `p2p/filter/id/<ID>`, where `<ID>` is the peer node ID (ie. the
pubkey.Address() for the peer's PubKey)
If either of these queries return a non-zero ABCI code, Tendermint will refuse
to connect to the peer.
### Paths
Queries are directed at paths, and may optionally include additional data.
The expectation is for there to be some number of high level paths
differentiating concerns, like `/p2p`, `/store`, and `/app`. Currently,
Tendermint only uses `/p2p`, for filtering peers. For more advanced use, see the
implementation of
[Query in the Cosmos-SDK](https://github.com/cosmos/cosmos-sdk/blob/v0.23.1/baseapp/baseapp.go#L333).
## Crash Recovery
On startup, Tendermint calls the `Info` method on the Info Connection to get the latest
committed state of the app. The app MUST return information consistent with the
last block it succesfully completed Commit for.
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
failed during the Commit of block H, then `last_block_height = H-1` and
`last_block_app_hash = <hash returned by Commit for block H-1, which is the hash in the header of block H>`.
We now distinguish three heights, and describe how Tendermint syncs itself with
the app.
```md
storeBlockHeight = height of the last block Tendermint saw a commit for
stateBlockHeight = height of the last block for which Tendermint completed all
block processing and saved all ABCI results to disk
appBlockHeight = height of the last block for which ABCI app succesfully
completed Commit
```
Note we always have `storeBlockHeight >= stateBlockHeight` and `storeBlockHeight >= appBlockHeight`
Note also Tendermint never calls Commit on an ABCI app twice for the same height.
The procedure is as follows.
First, some simple start conditions:
If `appBlockHeight == 0`, then call InitChain.
If `storeBlockHeight == 0`, we're done.
Now, some sanity checks:
If `storeBlockHeight < appBlockHeight`, error
If `storeBlockHeight < stateBlockHeight`, panic
If `storeBlockHeight > stateBlockHeight+1`, panic
Now, the meat:
If `storeBlockHeight == stateBlockHeight && appBlockHeight < storeBlockHeight`,
replay all blocks in full from `appBlockHeight` to `storeBlockHeight`.
This happens if we completed processing the block, but the app forgot its height.
If `storeBlockHeight == stateBlockHeight && appBlockHeight == storeBlockHeight`, we're done.
This happens if we crashed at an opportune spot.
If `storeBlockHeight == stateBlockHeight+1`
This happens if we started processing the block but didn't finish.
If `appBlockHeight < stateBlockHeight`
replay all blocks in full from `appBlockHeight` to `storeBlockHeight-1`,
and replay the block at `storeBlockHeight` using the WAL.
This happens if the app forgot the last block it committed.
If `appBlockHeight == stateBlockHeight`,
replay the last block (storeBlockHeight) in full.
This happens if we crashed before the app finished Commit
If `appBlockHeight == storeBlockHeight`
update the state using the saved ABCI responses but dont run the block against the real app.
This happens if we crashed after the app finished Commit but before Tendermint saved the state.
## State Sync
A new node joining the network can simply join consensus at the genesis height and replay all
historical blocks until it is caught up. However, for large chains this can take a significant
amount of time, often on the order of days or weeks.
State sync is an alternative mechanism for bootstrapping a new node, where it fetches a snapshot
of the state machine at a given height and restores it. Depending on the application, this can
be several orders of magnitude faster than replaying blocks.
Note that state sync does not currently backfill historical blocks, so the node will have a
truncated block history - users are advised to consider the broader network implications of this in
terms of block availability and auditability. This functionality may be added in the future.
For details on the specific ABCI calls and types, see the [methods and types section](abci.md).
### Taking Snapshots
Applications that want to support state syncing must take state snapshots at regular intervals. How
this is accomplished is entirely up to the application. A snapshot consists of some metadata and
a set of binary chunks in an arbitrary format:
- `Height (uint64)`: The height at which the snapshot is taken. It must be taken after the given
height has been committed, and must not contain data from any later heights.
- `Format (uint32)`: An arbitrary snapshot format identifier. This can be used to version snapshot
formats, e.g. to switch from Protobuf to MessagePack for serialization. The application can use
this when restoring to choose whether to accept or reject a snapshot.
- `Chunks (uint32)`: The number of chunks in the snapshot. Each chunk contains arbitrary binary
data, and should be less than 16 MB; 10 MB is a good starting point.
- `Hash ([]byte)`: An arbitrary hash of the snapshot. This is used to check whether a snapshot is
the same across nodes when downloading chunks.
- `Metadata ([]byte)`: Arbitrary snapshot metadata, e.g. chunk hashes for verification or any other
necessary info.
For a snapshot to be considered the same across nodes, all of these fields must be identical. When
sent across the network, snapshot metadata messages are limited to 4 MB.
When a new node is running state sync and discovering snapshots, Tendermint will query an existing
application via the ABCI `ListSnapshots` method to discover available snapshots, and load binary
snapshot chunks via `LoadSnapshotChunk`. The application is free to choose how to implement this
and which formats to use, but must provide the following guarantees:
- **Consistent:** A snapshot must be taken at a single isolated height, unaffected by
concurrent writes. This can be accomplished by using a data store that supports ACID
transactions with snapshot isolation.
- **Asynchronous:** Taking a snapshot can be time-consuming, so it must not halt chain progress,
for example by running in a separate thread.
- **Deterministic:** A snapshot taken at the same height in the same format must be identical
(at the byte level) across nodes, including all metadata. This ensures good availability of
chunks, and that they fit together across nodes.
A very basic approach might be to use a datastore with MVCC transactions (such as RocksDB),
start a transaction immediately after block commit, and spawn a new thread which is passed the
transaction handle. This thread can then export all data items, serialize them using e.g.
Protobuf, hash the byte stream, split it into chunks, and store the chunks in the file system
along with some metadata - all while the blockchain is applying new blocks in parallel.
A more advanced approach might include incremental verification of individual chunks against the
chain app hash, parallel or batched exports, compression, and so on.
Old snapshots should be removed after some time - generally only the last two snapshots are needed
(to prevent the last one from being removed while a node is restoring it).
### Bootstrapping a Node
An empty node can be state synced by setting the configuration option `statesync.enabled =
true`. The node also needs the chain genesis file for basic chain info, and configuration for
light client verification of the restored snapshot: a set of Tendermint RPC servers, and a
trusted header hash and corresponding height from a trusted source, via the `statesync`
configuration section.
Once started, the node will connect to the P2P network and begin discovering snapshots. These
will be offered to the local application via the `OfferSnapshot` ABCI method. Once a snapshot
is accepted Tendermint will fetch and apply the snapshot chunks. After all chunks have been
successfully applied, Tendermint verifies the app's `AppHash` against the chain using the light
client, then switches the node to normal consensus operation.
#### Snapshot Discovery
When the empty node join the P2P network, it asks all peers to report snapshots via the
`ListSnapshots` ABCI call (limited to 10 per node). After some time, the node picks the most
suitable snapshot (generally prioritized by height, format, and number of peers), and offers it
to the application via `OfferSnapshot`. The application can choose a number of responses,
including accepting or rejecting it, rejecting the offered format, rejecting the peer who sent
it, and so on. Tendermint will keep discovering and offering snapshots until one is accepted or
the application aborts.
#### Snapshot Restoration
Once a snapshot has been accepted via `OfferSnapshot`, Tendermint begins downloading chunks from
any peers that have the same snapshot (i.e. that have identical metadata fields). Chunks are
spooled in a temporary directory, and then given to the application in sequential order via
`ApplySnapshotChunk` until all chunks have been accepted.
The method for restoring snapshot chunks is entirely up to the application.
During restoration, the application can respond to `ApplySnapshotChunk` with instructions for how
to continue. This will typically be to accept the chunk and await the next one, but it can also
ask for chunks to be refetched (either the current one or any number of previous ones), P2P peers
to be banned, snapshots to be rejected or retried, and a number of other responses - see the ABCI
reference for details.
If Tendermint fails to fetch a chunk after some time, it will reject the snapshot and try a
different one via `OfferSnapshot` - the application can choose whether it wants to support
restarting restoration, or simply abort with an error.
#### Snapshot Verification
Once all chunks have been accepted, Tendermint issues an `Info` ABCI call to retrieve the
`LastBlockAppHash`. This is compared with the trusted app hash from the chain, retrieved and
verified using the light client. Tendermint also checks that `LastBlockHeight` corresponds to the
height of the snapshot.
This verification ensures that an application is valid before joining the network. However, the
snapshot restoration may take a long time to complete, so applications may want to employ additional
verification during the restore to detect failures early. This might e.g. include incremental
verification of each chunk against the app hash (using bundled Merkle proofs), checksums to
protect against data corruption by the disk or network, and so on. However, it is important to
note that the only trusted information available is the app hash, and all other snapshot metadata
can be spoofed by adversaries.
Apps may also want to consider state sync denial-of-service vectors, where adversaries provide
invalid or harmful snapshots to prevent nodes from joining the network. The application can
counteract this by asking Tendermint to ban peers. As a last resort, node operators can use
P2P configuration options to whitelist a set of trusted peers that can provide valid snapshots.
#### Transition to Consensus
Once the snapshots have all been restored, Tendermint gathers additional information necessary for
bootstrapping the node (e.g. chain ID, consensus parameters, validator sets, and block headers)
from the genesis file and light client RPC servers. It also fetches and records the `AppVersion`
from the ABCI application.
Once the state machine has been restored and Tendermint has gathered this additional
information, it transitions to block sync (if enabled) to fetch any remaining blocks up the chain
head, and then transitions to regular consensus operation. At this point the node operates like
any other node, apart from having a truncated block history at the height of the restored snapshot.

View File

@@ -1,117 +0,0 @@
---
order: 3
title: Client and Server
---
# Client and Server
This section is for those looking to implement their own ABCI Server, perhaps in
a new programming language.
You are expected to have read [ABCI Methods and Types](./abci.md) and [ABCI
Applications](./apps.md).
## Message Protocol
The message protocol consists of pairs of requests and responses defined in the
[protobuf file](https://github.com/tendermint/tendermint/blob/main/proto/tendermint/abci/types.proto).
Some messages have no fields, while others may include byte-arrays, strings, integers,
or custom protobuf types.
For more details on protobuf, see the [documentation](https://developers.google.com/protocol-buffers/docs/overview).
For each request, a server should respond with the corresponding
response, where the order of requests is preserved in the order of
responses.
## Server Implementations
To use ABCI in your programming language of choice, there must be a ABCI
server in that language. Tendermint supports three implementations of the ABCI, written in Go:
- In-process ([Golang](https://github.com/tendermint/tendermint/tree/main/abci),
[Rust](https://github.com/informalsystems/tendermint-rs/tree/main/abci))
- ABCI-socket
- GRPC
The latter two can be tested using the `abci-cli` by setting the `--abci` flag
appropriately (ie. to `socket` or `grpc`).
See examples, in various stages of maintenance, in
[Go](https://github.com/tendermint/tendermint/tree/main/abci/server),
[JavaScript](https://github.com/tendermint/js-abci),
[C++](https://github.com/mdyring/cpp-tmsp), and
[Java](https://github.com/jTendermint/jabci).
### In Process
The simplest implementation uses function calls within Golang.
This means ABCI applications written in Golang can be compiled with Tendermint Core and run as a single binary.
### GRPC
If GRPC is available in your language, this is the easiest approach,
though it will have significant performance overhead.
To get started with GRPC, copy in the [protobuf
file](https://github.com/tendermint/tendermint/blob/main/proto/tendermint/abci/types.proto)
and compile it using the GRPC plugin for your language. For instance,
for golang, the command is `protoc --go_out=plugins=grpc:. types.proto`.
See the [grpc documentation for more details](http://www.grpc.io/docs/).
`protoc` will autogenerate all the necessary code for ABCI client and
server in your language, including whatever interface your application
must satisfy to be used by the ABCI server for handling requests.
Note the length-prefixing used in the socket implementation (TSP) does not apply for GRPC.
### TSP
Tendermint Socket Protocol is an asynchronous, raw socket server which provides
ordered message passing over unix or tcp. Messages are serialized using
Protobuf3 and length-prefixed with an [unsigned
varint](https://developers.google.com/protocol-buffers/docs/encoding?csw=1#varints)
If GRPC is not available in your language, or you require higher performance, or
otherwise enjoy programming, you may implement your own ABCI server using the
Tendermint Socket Protocol. The first step is still to auto-generate the
relevant data types and codec in your language using `protoc`. In addition to
being proto3 encoded, messages coming over the socket are length-prefixed to
facilitate use as a streaming protocol. proto3 doesn't have an official
length-prefix standard, so we use our own. The first byte in the prefix
represents the length of the Big Endian encoded length. The remaining bytes in
the prefix are the Big Endian encoded length.
For example, if the proto3 encoded ABCI message is 0xDEADBEEF (4 bytes), the
length-prefixed message is 0x0104DEADBEEF. If the proto3 encoded ABCI message is
65535 bytes long, the length-prefixed message would be like 0x02FFFF....
The benefit of using this `varint` encoding over the old version (where integers
were encoded as `<len of len><big endian len>` is that it is the common way to
encode integers in Protobuf. It is also generally shorter.
As noted above, this prefixing does not apply for GRPC.
An ABCI server must also be able to support multiple connections, as
Tendermint uses four connections.
### Async vs Sync
The main ABCI server (ie. non-GRPC) provides ordered asynchronous messages.
This is useful for DeliverTx and CheckTx, since it allows Tendermint to forward
transactions to the app before it's finished processing previous ones.
Thus, DeliverTx and CheckTx messages are sent asynchronously, while all other
messages are sent synchronously.
## Client
There are currently two use-cases for an ABCI client. One is a testing
tool, as in the `abci-cli`, which allows ABCI requests to be sent via
command line. The other is a consensus engine, such as Tendermint Core,
which makes requests to the application every time a new transaction is
received or a block is committed.
It is unlikely that you will need to implement a client. For details of
our client, see
[here](https://github.com/tendermint/tendermint/tree/main/abci/client).