| modified_tx | bool | The Application sets it to true to denote it made changes to transactions | 1 |
| modified_tx | bool | The Application sets it to true to denote it made changes to transactions | 1 |
| tx | repeated [TransactionRecord](#transactionrecord) | Possibly modified list of transactions that have been picked as part of the proposed block. | 2 |
| tx | repeated [TransactionRecord](#transactionrecord) | Possibly modified list of transactions that have been picked as part of the proposed block. | 2 |
| same_block | bool | If true, Application is in same-block execution mode | 3 |
| data | bytes | The Merkle root hash of the application state. | 4 |
| tx_result | repeated [DeliverTxResult](#delivertxresult) | List of structures containing the data resulting from executing the transactions | 5 |
| validator_updates | repeated [ValidatorUpdate](#validatorupdate) | Changes to validator set (set voting power to 0 to remove). | 6 |
| consensus_param_updates | [ConsensusParams](#consensusparams) | Changes to consensus-critical gas, size, and other parameters. | 7 |
| data | bytes | The Merkle root hash of the application state. | 3 |
| tx_result | repeated [DeliverTxResult](#delivertxresult) | List of structures containing the data resulting from executing the transactions | 4 |
| validator_updates | repeated [ValidatorUpdate](#validatorupdate) | Changes to validator set (set voting power to 0 to remove). | 5 |
| consensus_param_updates | [ConsensusParams](#consensusparams) | Changes to consensus-critical gas, size, and other parameters. | 6 |
* **Usage**:
* **Usage**:
* Contains a preliminary block to be proposed, which the Application can modify.
* Contains a preliminary block to be proposed, which the Application can modify.
@ -320,10 +319,9 @@ From the App's perspective, they'll probably skip ProcessProposal
them in `ResponsePrepareProposal`. In that case, `ResponsePrepareProposal.modified_tx` is set to true.
them in `ResponsePrepareProposal`. In that case, `ResponsePrepareProposal.modified_tx` is set to true.
* If `ResponsePrepareProposal.modified_tx` is false, then Tendermint will ignore the contents of
* If `ResponsePrepareProposal.modified_tx` is false, then Tendermint will ignore the contents of
`ResponsePrepareProposal.tx`.
`ResponsePrepareProposal.tx`.
* In same-block execution mode, the Application must set `ResponsePrepareProposal.same_block` to true, and,
as a result of executing the block, provide values for `ResponsePrepareProposal.data`,
* In same-block execution mode, the Application must provide values for `ResponsePrepareProposal.data`,
`ResponsePrepareProposal.tx_result`, `ResponsePrepareProposal.validator_updates`, and
`ResponsePrepareProposal.tx_result`, `ResponsePrepareProposal.validator_updates`, and
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 and there will be no byzantine process. In these frequent, benign conditions:
* Tendermint will decide in round 0;
* `PrepareProposal` will be called exactly once at the proposer process of round 0, height _h_;
* `ProcessProposal` will be called exactly once at all processes except the proposer of round 0, and
will return _accept_ in its `Response*`;
* `ExtendVote` will be called exactly once at all processes
* `VerifyVoteExtension` will be called _n-1_ times at each validator process, where _n_ is the number of validators; and
* `FinalizeBlock` will be finally called at all processes at the end of height _h_, conveying the same prepared
block that all calls to `PrepareProposal` and `ProcessProposal` had previously reported for 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 an a precise way.
As mentioned in the [Basic Concepts](abci++_basic_concepts_002_draft.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 Backus–Naur form (ABNF, specified
in [IETF rfc7405](https://datatracker.ietf.org/doc/html/rfc7405)), specifies all possible
sequences of calls to ABCI++ across all heights from the genesis block, including recovery runs,
* 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>"
>extend-vote = %s"<ExtendVote>"
>got-vote = %s"<VerifyVoteExtension>"
>decide = %s"<FinalizeBlock>"
>```
## `ProcessProposal`'s timeout (a.k.a. Zarko's Github comment in Issue#351)
>**TODO** (to discuss): `PrepareProposal` is called synchronously. `ProcessProposal` may also want to fully process the block synchronously.
>**TODO** (to discuss): `PrepareProposal` is called synchronously. `ProcessProposal` may also want to fully process the block synchronously.
>However, they stand on Tendermint's critical path, so the Tendermint's Propose timeout needs to accomodate that.
>However, they stand on Tendermint's critical path, so the Tendermint's Propose timeout needs to accomodate that.
>
>
>Idea: Make propose timestamp (currently hardcoded to 3 secs in the Tendermint Go implementation) part of ConsensusParams,
>Idea: Make propose timestamp (currently hardcoded to 3 secs in the Tendermint Go implementation) part of ConsensusParams,
>so the App can adjust it with its knowledge of the time may take to prepare/process the proposal.
>so the App can adjust it with its knowledge of the time may take to prepare/process the proposal.
>
>This should probably go elsewhere in the spec.
# Failure modes
>**TODO** Is it worth explaining the failure modes? Since we're going for halt, and can't configure them.
# Application modes
[This is a sketch ATM]
Mode 1: Simple mode (equivalent to ABCI).
**TODO**: Define _candidate block_
Definition: "candidate state" is the App state resulting from the optimistic exectution of a block that is not decided yet by consensus. An application managing candidate states needs to be able to discard them and recover the previous state
* PrepareProposal: Set `ResponsePrepareProposal.modified` to false and return
* ProcessProposal: keep the block data in memory (indexed by app hash) as _candidate block_ and return Accept
* ExtendVote: return empty byte array
* VerifyVoteExtension: if the byte array is empty, return Accept; else, return Reject
* Finalize block: look up the block by the app hash and fully execute it. Discard all other candidate blocks
Mode 2: Basic checks on proposals.
* PrepareProposal: Go through the transactions, apply basic app-dependent checks based on the block and last committed state. Remove/reorder invalid transactions in the block
* ProcessProposal: Same as PrepareProposal; return Reject if invalid transactions are detected. If Accept, keep the block data in memory (indexed by app hash) as _candidate block_.
* ExtendVote: return empty byte array
* VerifyVoteExtension: if the byte array is empty, return Accept; else, return Reject
* Finalize block: look up the block by the app hash and fully execute it. Discard all other candidate blocks
Mode 3: Full check of proposals. Optimistic (or immediate) execution. No candidate state management.
* PrepareProposal: fully execute the block, but discard the resulting state. Remove/reorder invalid transactions in the block.
* ProcessProposal: Same as PrepareProposal. Return Reject if invalid transactions are detected. If Accept, keep the block data in memory (indexed by app hash) as _candidate block_.
* ExtendVote: return empty byte array
* VerifyVoteExtension: if the byte array is empty, return Accept; else, return Reject
* Finalize block: look up the block by the app hash and fully execute it. Discard all other candidate blocks
## Failure modes
This mode guarantees that no invalid transactions will ever make it into a committed block
>**TODO** Is it worth explaining the failure modes? Since we're going for halt, and can't configure them...
Mode 4: Mode 3 + candidate state management.
## Adapting existing Applications that use ABCI
* PrepareProposal: First Remove/reorder invalid transactions in the block. If _v_ is not in the set of candidate states, fully execute the block, add the resulting state as candidate state for value _v_, height _h_.
* ProcessProposal: Same as PrepareProposal. Return Reject if invalid transactions are detected
* ExtendVote: return empty byte array
* VerifyVoteExtension: if the byte array is empty, return Accept; else, return Reject
* Finalize block: commit candidate state corresponding to _v_, discard all other candidate states.
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.
Mode 5: Mode 4 + AppHash for heigh _h_ is in _h_'s header
First of all, all the methods that did not change from ABCI to ABCI++, namely `Echo`, `Flush`, `Info`, `InitChain`,
`Query`, `CheckTx`, `ListSnapshots`, `LoadSnapshotChunk`, `OfferSnapshot`, and `ApplySnapshotChunk`, do not need
to undergo any changes in their implementation.
>**TODO** Mode 6: With vote extensions (?)
As for the new methods:
>**TODO**: Explain the two workflows discussed with Callum: App hash on N+1 vs App hash on N. How to capture it in ABCI++ ?
* `PrepareProposal` should set `ResponsePrepareProposal.modified_tx` to _false_ and return.
* `ProcessProposal` should set `ResponseProcessProposal.accept` to _true_ and return.
* `ExtendVote` should set `ResponseExtendVote.extension` to an empty byte array and return.
* `VerifyVoteExtension` should set `ResponseVerifyVoteExtension.accept` to _true_ if the extension is an empty byte array
and _false_ otherwise, then return.
* `FinalizeBlock` should coalesce the implementation of methods `BeginBlock`, `DeliverTx`, `EndBlock`, and `Commit`.
The logic extracted from `DeliverTx` should be wrappped by a loop that will execute as many times as