@ -65,8 +65,8 @@ ignore the invalid part of the prepared proposal at block execution time.
The data, called _vote extension_, will also be made available to the
The data, called _vote extension_, will also be made available to the
application in the next height, along with the vote it is extending, in the rounds
application in the next height, along with the vote it is extending, in the rounds
where the local process is the proposer.
where the local process is the proposer.
The Application may also choose not to include any vote extension.
Tendermint calls it when is about to send a non-`nil` precommit message.
If the Application does not have vote extension information to provide, it returns a 0-length byte array as its vote extension.
Tendermint calls `ExtendVote` when is about to send a non-`nil` precommit message.
* [**VerifyVoteExtension:**](./abci++_methods_002_draft.md#verifyvoteextension) It allows validators to validate the vote extension data attached to a precommit message. If the validation fails, the precommit message will be deemed invalid and ignored
* [**VerifyVoteExtension:**](./abci++_methods_002_draft.md#verifyvoteextension) It allows validators to validate the vote extension data attached to a precommit message. If the validation fails, the 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) of the validators send precommit votes for that block. Thus, `VerifyVoteExtension` should be used with special care.
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) of the validators send precommit votes for that block. Thus, `VerifyVoteExtension` should be used with special care.
* If the Application wants to add a new transaction, then the Application should include it in `tx_records` and _mark_ it as `ADD`. In this case, Tendermint will add it to the mempool.
* If the Application wants to add a new transaction, then the Application should include it in `tx_records` and _mark_ it as `ADD`. In this case, Tendermint will add it to the mempool.
* The Application should be aware that removing and adding transactions may compromise _traceability_.
* 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` and add `t2` to the mempool. If a client wants to eventually check what happened to `t1`, it will discover that `t_1` is not in the mempool or in a committed block, getting the wrong idea that `t_1` did not make it into a block. Note that `t_2`_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.
> 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` and add `t2` to the mempool. If a client wants to eventually check what happened to `t1`, it will discover that `t_1` is not in the mempool or in a committed block, getting the wrong idea that `t_1` did not make it into a block. Note that `t_2`_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.
* If the Application modifies the set of transactions, the modified transactions MUST NOT exceed the configured maximum size `RequestPrepareProposal.max_tx_bytes`.
* If the Application does not modify the preliminary set of transactions `txs`, then it sets `ResponsePrepareProposal.modified_tx_status` to `UNMODIFIED`. In this case, Tendermint will ignore the contents of `ResponsePrepareProposal.tx_records`.
* If the Application does not modify the preliminary set of transactions `txs`, then it sets `ResponsePrepareProposal.modified_tx_status` to `UNMODIFIED`. In this case, Tendermint will ignore the contents of `ResponsePrepareProposal.tx_records`.
* In order to optimize the block size in busy blockchains, Tendermint might include a list of transactions in `RequestPrepareProposal.txs` whose size
in bytes exceeds `RequestPrepareProposal.max_tx_bytes`. In this case:
* The Application MUST still abide by the `RequestPrepareProposal.max_tx_bytes` limit in the list of transaction records it returns (excluding those marked as `REMOVE`).
* It is _invalid_ to return `ResponsePrepareProposal.modified_tx_status` set to `UNMODIFIED`: Tendermint will panic.
* In same-block execution mode, the Application must provide values for `ResponsePrepareProposal.app_hash`,
* In same-block execution mode, the Application must provide values for `ResponsePrepareProposal.app_hash`,
`ResponsePrepareProposal.tx_results`, `ResponsePrepareProposal.validator_updates`, and
`ResponsePrepareProposal.tx_results`, `ResponsePrepareProposal.validator_updates`, and
`ResponsePrepareProposal.consensus_param_updates`, as a result of fully executing the block.
`ResponsePrepareProposal.consensus_param_updates`, as a result of fully executing the block.
@ -529,7 +532,7 @@ a [CanonicalVoteExtension](#canonicalvoteextension) field in the `precommit nil`
| hash | bytes | The header hash of the propsed block that the vote extension refers to. | 1 |
| hash | bytes | The header hash of the propsed 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 |
| 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 |
| height | int64 | Height of the block (for sanity check). | 3 |
| vote_extension | bytes | Optional information signed by Tendermint. | 4 |
| vote_extension | bytes | Application-specific information signed by Tendermint. Can have 0 length | 4 |
* **Response**:
* **Response**:
@ -538,6 +541,9 @@ a [CanonicalVoteExtension](#canonicalvoteextension) field in the `precommit nil`
| status | [VerifyStatus](#VerifyStatus) | `enum` signaling if the application accepts the vote extension | 1 |
| status | [VerifyStatus](#VerifyStatus) | `enum` signaling if the application accepts the vote extension | 1 |
* **Usage**:
* **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.
* If `ResponseVerifyVoteExtension.status` is `REJECT`, Tendermint will reject the whole received vote.
* If `ResponseVerifyVoteExtension.status` is `REJECT`, Tendermint will reject the whole received vote.
See the [Requirements](abci++_app_requirements_002_draft.md) section to understand the potential
See the [Requirements](abci++_app_requirements_002_draft.md) section to understand the potential
liveness implications of this.
liveness implications of this.
@ -553,9 +559,11 @@ a [CanonicalVoteExtension](#canonicalvoteextension) field in the `precommit nil`
When a validator _p_ is in Tendermint consensus round _r_, height _h_, state _prevote_ (**TODO** discuss: I think I must remove the state
When a validator _p_ is in Tendermint consensus round _r_, height _h_, state _prevote_ (**TODO** discuss: I think I must remove the state
from this condition, but not sure), and _p_ receives a Precommit message for round _r_, height _h_ from _q_:
from this condition, but not sure), and _p_ receives a Precommit message for round _r_, height _h_ from _q_: