Browse Source

Vote extensions: new design (#8031)

* Changed the spec text to agreed VoteExtension solution

* Revert "Removed protobufs related to vote extensions"

This reverts commit 4566f1e302.

* Changes to ABCI protocol buffers

* Update spec/core/data_structures.md

Co-authored-by: M. J. Fromberger <fromberger@interchain.io>

* Update spec/core/data_structures.md

Co-authored-by: M. J. Fromberger <fromberger@interchain.io>

* Fix dangling link in ABCI++ readme

* Addressed comments

Co-authored-by: M. J. Fromberger <fromberger@interchain.io>
pull/8064/head
Sergio Mena 3 years ago
committed by GitHub
parent
commit
7c4fe5b108
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 212 additions and 127 deletions
  1. +93
    -49
      proto/tendermint/abci/types.proto
  2. +1
    -2
      spec/abci++/README.md
  3. +3
    -2
      spec/abci++/abci++_basic_concepts_002_draft.md
  4. +98
    -61
      spec/abci++/abci++_methods_002_draft.md
  5. +2
    -1
      spec/abci++/abci++_tmint_expected_behavior_002_draft.md
  6. +15
    -12
      spec/core/data_structures.md

+ 93
- 49
proto/tendermint/abci/types.proto View File

@ -21,26 +21,26 @@ import "gogoproto/gogo.proto";
message Request { message Request {
oneof value { oneof value {
RequestEcho echo = 1;
RequestFlush flush = 2;
RequestInfo info = 3;
RequestInitChain init_chain = 4;
RequestQuery query = 5;
RequestBeginBlock begin_block = 6 [deprecated = true];
RequestCheckTx check_tx = 7;
RequestDeliverTx deliver_tx = 8 [deprecated = true];
RequestEndBlock end_block = 9 [deprecated = true];
RequestCommit commit = 10;
RequestListSnapshots list_snapshots = 11;
RequestOfferSnapshot offer_snapshot = 12;
RequestLoadSnapshotChunk load_snapshot_chunk = 13;
RequestApplySnapshotChunk apply_snapshot_chunk = 14;
RequestPrepareProposal prepare_proposal = 15;
RequestProcessProposal process_proposal = 16;
RequestFinalizeBlock finalize_block = 19;
RequestEcho echo = 1;
RequestFlush flush = 2;
RequestInfo info = 3;
RequestInitChain init_chain = 4;
RequestQuery query = 5;
RequestBeginBlock begin_block = 6 [deprecated = true];
RequestCheckTx check_tx = 7;
RequestDeliverTx deliver_tx = 8 [deprecated = true];
RequestEndBlock end_block = 9 [deprecated = true];
RequestCommit commit = 10;
RequestListSnapshots list_snapshots = 11;
RequestOfferSnapshot offer_snapshot = 12;
RequestLoadSnapshotChunk load_snapshot_chunk = 13;
RequestApplySnapshotChunk apply_snapshot_chunk = 14;
RequestPrepareProposal prepare_proposal = 15;
RequestProcessProposal process_proposal = 16;
RequestExtendVote extend_vote = 17;
RequestVerifyVoteExtension verify_vote_extension = 18;
RequestFinalizeBlock finalize_block = 19;
} }
reserved 17; // Placeholder for RequestExtendVote in v0.37
reserved 18; // Placeholder for RequestVerifyVoteExtension in v0.37
} }
message RequestEcho { message RequestEcho {
@ -75,7 +75,7 @@ message RequestQuery {
message RequestBeginBlock { message RequestBeginBlock {
bytes hash = 1; bytes hash = 1;
tendermint.types.Header header = 2 [(gogoproto.nullable) = false]; tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
LastCommitInfo last_commit_info = 3 [(gogoproto.nullable) = false];
CommitInfo last_commit_info = 3 [(gogoproto.nullable) = false];
repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false]; repeated Evidence byzantine_validators = 4 [(gogoproto.nullable) = false];
} }
@ -127,9 +127,9 @@ message RequestPrepareProposal {
tendermint.types.Header header = 2 [(gogoproto.nullable) = false]; tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
// txs is an array of transactions that will be included in a block, // txs is an array of transactions that will be included in a block,
// sent to the app for possible modifications. // sent to the app for possible modifications.
repeated bytes txs = 3;
LastCommitInfo last_commit_info = 4 [(gogoproto.nullable) = false];
repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false];
repeated bytes txs = 3;
ExtendedCommitInfo local_last_commit = 4 [(gogoproto.nullable) = false];
repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false];
// the modified transactions cannot exceed this size. // the modified transactions cannot exceed this size.
int64 max_tx_bytes = 6; int64 max_tx_bytes = 6;
} }
@ -138,15 +138,29 @@ message RequestProcessProposal {
bytes hash = 1; bytes hash = 1;
tendermint.types.Header header = 2 [(gogoproto.nullable) = false]; tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
repeated bytes txs = 3; repeated bytes txs = 3;
LastCommitInfo last_commit_info = 4 [(gogoproto.nullable) = false];
CommitInfo proposed_last_commit = 4 [(gogoproto.nullable) = false];
repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false]; repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false];
} }
// Extends a vote with application-side injection
message RequestExtendVote {
bytes hash = 1;
int64 height = 2;
}
// Verify the vote extension
message RequestVerifyVoteExtension {
bytes hash = 1;
bytes validator_address = 2;
int64 height = 3;
bytes vote_extension = 4;
}
message RequestFinalizeBlock { message RequestFinalizeBlock {
bytes hash = 1; bytes hash = 1;
tendermint.types.Header header = 2 [(gogoproto.nullable) = false]; tendermint.types.Header header = 2 [(gogoproto.nullable) = false];
repeated bytes txs = 3; repeated bytes txs = 3;
LastCommitInfo last_commit_info = 4 [(gogoproto.nullable) = false];
CommitInfo decided_last_commit = 4 [(gogoproto.nullable) = false];
repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false]; repeated Evidence byzantine_validators = 5 [(gogoproto.nullable) = false];
} }
@ -155,27 +169,27 @@ message RequestFinalizeBlock {
message Response { message Response {
oneof value { oneof value {
ResponseException exception = 1;
ResponseEcho echo = 2;
ResponseFlush flush = 3;
ResponseInfo info = 4;
ResponseInitChain init_chain = 5;
ResponseQuery query = 6;
ResponseBeginBlock begin_block = 7 [deprecated = true];
ResponseCheckTx check_tx = 8;
ResponseDeliverTx deliver_tx = 9 [deprecated = true];
ResponseEndBlock end_block = 10 [deprecated = true];
ResponseCommit commit = 11;
ResponseListSnapshots list_snapshots = 12;
ResponseOfferSnapshot offer_snapshot = 13;
ResponseLoadSnapshotChunk load_snapshot_chunk = 14;
ResponseApplySnapshotChunk apply_snapshot_chunk = 15;
ResponsePrepareProposal prepare_proposal = 16;
ResponseProcessProposal process_proposal = 17;
ResponseFinalizeBlock finalize_block = 20;
ResponseException exception = 1;
ResponseEcho echo = 2;
ResponseFlush flush = 3;
ResponseInfo info = 4;
ResponseInitChain init_chain = 5;
ResponseQuery query = 6;
ResponseBeginBlock begin_block = 7 [deprecated = true];
ResponseCheckTx check_tx = 8;
ResponseDeliverTx deliver_tx = 9 [deprecated = true];
ResponseEndBlock end_block = 10 [deprecated = true];
ResponseCommit commit = 11;
ResponseListSnapshots list_snapshots = 12;
ResponseOfferSnapshot offer_snapshot = 13;
ResponseLoadSnapshotChunk load_snapshot_chunk = 14;
ResponseApplySnapshotChunk apply_snapshot_chunk = 15;
ResponsePrepareProposal prepare_proposal = 16;
ResponseProcessProposal process_proposal = 17;
ResponseExtendVote extend_vote = 18;
ResponseVerifyVoteExtension verify_vote_extension = 19;
ResponseFinalizeBlock finalize_block = 20;
} }
reserved 18; // Placeholder for ResponseExtendVote in v0.37
reserved 19; // Placeholder for ResponseVerifyVoteExtension in v0.37
} }
// nondeterministic // nondeterministic
@ -308,7 +322,7 @@ message ResponsePrepareProposal {
repeated ExecTxResult tx_results = 4; repeated ExecTxResult tx_results = 4;
repeated ValidatorUpdate validator_updates = 5; repeated ValidatorUpdate validator_updates = 5;
tendermint.types.ConsensusParams consensus_param_updates = 6; tendermint.types.ConsensusParams consensus_param_updates = 6;
reserved 7; // Placeholder for app_signed_updates in v0.37
repeated bytes app_signed_updates = 7;
} }
message ResponseProcessProposal { message ResponseProcessProposal {
@ -319,6 +333,14 @@ message ResponseProcessProposal {
tendermint.types.ConsensusParams consensus_param_updates = 5; tendermint.types.ConsensusParams consensus_param_updates = 5;
} }
message ResponseExtendVote {
bytes vote_extension = 1;
}
message ResponseVerifyVoteExtension {
bool accept = 1;
}
message ResponseFinalizeBlock { message ResponseFinalizeBlock {
repeated Event block_events = 1 repeated Event block_events = 1
[(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"];
@ -332,11 +354,16 @@ message ResponseFinalizeBlock {
//---------------------------------------- //----------------------------------------
// Misc. // Misc.
message LastCommitInfo {
message CommitInfo {
int32 round = 1; int32 round = 1;
repeated VoteInfo votes = 2 [(gogoproto.nullable) = false]; repeated VoteInfo votes = 2 [(gogoproto.nullable) = false];
} }
message ExtendedCommitInfo {
int32 round = 1;
repeated ExtendedVoteInfo votes = 2 [(gogoproto.nullable) = false];
}
// Event allows application developers to attach additional information to // Event allows application developers to attach additional information to
// ResponseBeginBlock, ResponseEndBlock, ResponseCheckTx and ResponseDeliverTx. // ResponseBeginBlock, ResponseEndBlock, ResponseCheckTx and ResponseDeliverTx.
// Later, transactions may be queried using these events. // Later, transactions may be queried using these events.
@ -410,8 +437,23 @@ message ValidatorUpdate {
message VoteInfo { message VoteInfo {
Validator validator = 1 [(gogoproto.nullable) = false]; Validator validator = 1 [(gogoproto.nullable) = false];
bool signed_last_block = 2; bool signed_last_block = 2;
reserved 3; // Placeholder for tendermint_signed_extension in v0.37
reserved 4; // Placeholder for app_signed_extension in v0.37
}
// ExtendedVoteInfo
message ExtendedVoteInfo {
Validator validator = 1 [(gogoproto.nullable) = false];
bool signed_last_block = 2;
bytes vote_extension = 3;
}
// CanonicalVoteExtension
// TODO: move this to core Tendermint data structures
message CanonicalVoteExtension {
bytes extension = 1;
int64 height = 2;
int32 round = 3;
string chain_id = 4;
bytes address = 5;
} }
enum EvidenceType { enum EvidenceType {
@ -462,5 +504,7 @@ service ABCIApplication {
rpc ApplySnapshotChunk(RequestApplySnapshotChunk) returns (ResponseApplySnapshotChunk); rpc ApplySnapshotChunk(RequestApplySnapshotChunk) returns (ResponseApplySnapshotChunk);
rpc PrepareProposal(RequestPrepareProposal) returns (ResponsePrepareProposal); rpc PrepareProposal(RequestPrepareProposal) returns (ResponsePrepareProposal);
rpc ProcessProposal(RequestProcessProposal) returns (ResponseProcessProposal); rpc ProcessProposal(RequestProcessProposal) returns (ResponseProcessProposal);
rpc ExtendVote(RequestExtendVote) returns (ResponseExtendVote);
rpc VerifyVoteExtension(RequestVerifyVoteExtension) returns (ResponseVerifyVoteExtension);
rpc FinalizeBlock(RequestFinalizeBlock) returns (ResponseFinalizeBlock); rpc FinalizeBlock(RequestFinalizeBlock) returns (ResponseFinalizeBlock);
} }

+ 1
- 2
spec/abci++/README.md View File

@ -20,8 +20,7 @@ for handling all ABCI++ methods.
Thus, Tendermint always sends the `Request*` messages and receives the `Response*` messages Thus, Tendermint always sends the `Request*` messages and receives the `Response*` messages
in return. in return.
All ABCI++ messages and methods are defined in
[protocol buffers](https://github.com/tendermint/tendermint/blob/master/proto/spec/abci/types.proto).
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 allows Tendermint to run with applications written in many programming languages.
This specification is split as follows: This specification is split as follows:


+ 3
- 2
spec/abci++/abci++_basic_concepts_002_draft.md View File

@ -206,8 +206,9 @@ the local process is the proposer of the round.
When Tendermint's consensus is about to send a non-`nil` precommit message, it calls When Tendermint's consensus is about to send a non-`nil` precommit message, it calls
method `ExtendVote`, which gives the Application the opportunity to include method `ExtendVote`, which gives the Application the opportunity to include
non-deterministic data, opaque to Tendermint, that will be attached to the precommit non-deterministic data, opaque to Tendermint, that will be attached to the precommit
message. The data, called _vote extension_, will also be part of the proposed block
in the next height, along with the vote it is extending.
message. The data, called _vote extension_, will also be made available to the
application in the next height, along with the vote it is extending, in the rounds
where the local process is the proposer.
The vote extension data is split into two parts, one signed by Tendermint as part The vote extension data is split into two parts, one signed by Tendermint as part
of the vote data structure, and the other (optionally) signed by the Application. of the vote data structure, and the other (optionally) signed by the Application.


+ 98
- 61
spec/abci++/abci++_methods_002_draft.md View File

@ -290,15 +290,10 @@ title: Methods
| hash | bytes | The block header's hash of the block to propose. Present for convenience (can be derived from the block header). | 1 | | hash | bytes | The block header's hash of the block to propose. Present for convenience (can be derived from the block header). | 1 |
| header | [Header](../core/data_structures.md#header) | The header of the block to propose. | 2 | | header | [Header](../core/data_structures.md#header) | The header of the block to propose. | 2 |
| txs | repeated bytes | Preliminary list of transactions that have been picked as part of the block to propose. | 3 | | txs | repeated bytes | Preliminary list of transactions that have been picked as part of the block to propose. | 3 |
| last_commit_info | [LastCommitInfo](#lastcommitinfo) | Info about the last commit, including the round, the validator list, and which ones signed the last block. | 4 |
| local_last_commit | [ExtendedCommitInfo](#extendedcommitinfo) | Info about the last commit, obtained locally from Tendermint's data structures. | 4 |
| byzantine_validators | repeated [Evidence](#evidence) | List of evidence of validators that acted maliciously. | 5 | | byzantine_validators | repeated [Evidence](#evidence) | List of evidence of validators that acted maliciously. | 5 |
| max_tx_bytes | int64 | Currently configured maximum size in bytes taken by the modified transactions. | 6 | | max_tx_bytes | int64 | Currently configured maximum size in bytes taken by the modified transactions. | 6 |
>**TODO**: Add the changes needed in LastCommitInfo for vote extensions
>**TODO**: DISCUSS: We need to make clear whether a proposer is also running the logic of a non-proposer node (in particular "ProcessProposal")
From the App's perspective, they'll probably skip ProcessProposal
* **Response**: * **Response**:
| Name | Type | Description | Field Number | | Name | Type | Description | Field Number |
@ -340,7 +335,7 @@ From the App's perspective, they'll probably skip ProcessProposal
for blocks `H+1`, and `H+2`. Heights following a validator update are affected in the following way: for blocks `H+1`, and `H+2`. Heights following a validator update are affected in the following way:
* `H`: `NextValidatorsHash` includes the new `validator_updates` value. * `H`: `NextValidatorsHash` includes the new `validator_updates` value.
* `H+1`: The validator set change takes effect and `ValidatorsHash` is updated. * `H+1`: The validator set change takes effect and `ValidatorsHash` is updated.
* `H+2`: `last_commit_info` is changed to include the altered validator set.
* `H+2`: `local_last_commit` now includes the altered validator set.
* `ResponseFinalizeBlock.consensus_param_updates` returned for block `H` apply to the consensus * `ResponseFinalizeBlock.consensus_param_updates` returned for block `H` apply to the consensus
params for block `H+1` even if the change is agreed in block `H`. params for block `H+1` even if the change is agreed in block `H`.
For more information on the consensus parameters, For more information on the consensus parameters,
@ -414,7 +409,7 @@ Note that, if _p_ has a non-`nil` _validValue_, Tendermint will use it as propos
| hash | bytes | The block header's hash of the proposed block. Present for convenience (can be derived from the block header). | 1 | | hash | bytes | The block header's hash of the proposed block. Present for convenience (can be derived from the block header). | 1 |
| header | [Header](../core/data_structures.md#header) | The proposed block's header. | 2 | | header | [Header](../core/data_structures.md#header) | The proposed block's header. | 2 |
| txs | repeated bytes | List of transactions that have been picked as part of the proposed block. | 3 | | txs | repeated bytes | List of transactions that have been picked as part of the proposed block. | 3 |
| last_commit_info | [LastCommitInfo](#lastcommitinfo) | Info about the last commit, including the round , the validator list, and which ones signed the last block. | 4 |
| proposed_last_commit | [CommitInfo](#commitinfo) | Info about the last commit, obtained from the information in the proposed block. | 4 |
| byzantine_validators | repeated [Evidence](#evidence) | List of evidence of validators that acted maliciously. | 5 | | byzantine_validators | repeated [Evidence](#evidence) | List of evidence of validators that acted maliciously. | 5 |
* **Response**: * **Response**:
@ -495,18 +490,17 @@ When a validator _p_ enters Tendermint consensus round _r_, height _h_, in which
* **Response**: * **Response**:
| Name | Type | Description | Field Number |
|-------------------|-------|---------------------------------------------------------------------|--------------|
| app_signed | bytes | Optional information signed by the Application (not by Tendermint). | 1 |
| tendermint_signed | bytes | Optional information signed by Tendermint. | 2 |
| Name | Type | Description | Field Number |
|-------------------|-------|-----------------------------------------------|--------------|
| vote_extension | bytes | Optional information signed by by Tendermint. | 1 |
* **Usage**: * **Usage**:
* Both `ResponseExtendVote.app_signed` and `ResponseExtendVote.tendermint_signed` are optional information that will
be attached to the Precommit message.
* `ResponseExtendVote.vote_extension` is optional information that, if present, will be signed by Tendermint and
attached to the Precommit message.
* `RequestExtendVote.hash` corresponds to the hash of a proposed block that was made available to the application * `RequestExtendVote.hash` corresponds to the hash of a proposed block that was made available to the application
in a previous call to `ProcessProposal` or `PrepareProposal` for the current height. in a previous call to `ProcessProposal` or `PrepareProposal` for the current height.
* `ResponseExtendVote.app_signed` and `ResponseExtendVote.tendermint_signed` will always be attached to a non-`nil`
Precommit message. If Tendermint is to precommit `nil`, it will not call `RequestExtendVote`.
* `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. * The Application logic that creates the extension can be non-deterministic.
#### When does Tendermint call it? #### When does Tendermint call it?
@ -520,11 +514,18 @@ then _p_'s Tendermint locks _v_ and sends a Precommit message in the following
1. _p_'s Tendermint sets _lockedValue_ and _validValue_ to _v_, and sets _lockedRound_ and _validRound_ to _r_ 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. 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` as a new field in the Precommit message.
5. _p_'s Tendermint signs and 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 include an empty byte array as vote extension in the `precommit nil` message.
3. The Application optionally 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 ### VerifyVoteExtension
@ -534,11 +535,10 @@ In the cases when _p_'s Tendermint is to broadcast `precommit nil` messages (eit
| Name | Type | Description | Field Number | | Name | Type | Description | Field Number |
|-------------------|-------|------------------------------------------------------------------------------------------|--------------| |-------------------|-------|------------------------------------------------------------------------------------------|--------------|
| app_signed | bytes | Optional information signed by the Application (not by Tendermint). | 1 |
| tendermint_signed | bytes | Optional information signed by Tendermint. | 2 |
| hash | bytes | The header hash of the propsed block that the vote extension refers to. | 3 |
| validator_address | bytes | [Address](../core/data_structures.md#address) of the validator that signed the extension | 4 |
| height | int64 | Height of the block (for sanity check). | 5 |
| 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 |
| height | int64 | Height of the block (for sanity check). | 3 |
| vote_extension | bytes | Optional information signed by Tendermint. | 4 |
* **Response**: * **Response**:
@ -566,11 +566,8 @@ from this condition, but not sure), and _p_ receives a Precommit message for rou
2. The Application returns _accept_ or _reject_ via `ResponseVerifyVoteExtension.accept`. 2. The Application returns _accept_ or _reject_ via `ResponseVerifyVoteExtension.accept`.
3. If the Application returns 3. If the Application returns
* _accept_, _p_'s Tendermint will keep the received vote, together with its corresponding * _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:
* calculate field _LastCommitHash_ in the header of the block proposed for height _h + 1_
(in the rounds where _p_ will be proposer).
* populate _LastCommitInfo_ in calls to `RequestPrepareProposal`, `RequestProcessProposal`,
and `RequestFinalizeBlock` in height _h + 1_.
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. * _reject_, _p_'s Tendermint will deem the Precommit message invalid and discard it.
### FinalizeBlock ### FinalizeBlock
@ -579,13 +576,13 @@ from this condition, but not sure), and _p_ receives a Precommit message for rou
* **Request**: * **Request**:
| Name | Type | Description | Field Number |
|----------------------|---------------------------------------------|-------------------------------------------------------------------------------------------------------------------|--------------|
| hash | bytes | The block header's hash. Present for convenience (can be derived from the block header). | 1 |
| header | [Header](../core/data_structures.md#header) | The block header. | 2 |
| txs | repeated bytes | List of transactions committed as part of the block. | 3 |
| 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. | 4 |
| byzantine_validators | repeated [Evidence](#evidence) | List of evidence of validators that acted maliciously. | 5 |
| Name | Type | Description | Field Number |
|----------------------|---------------------------------------------|------------------------------------------------------------------------------------------|--------------|
| hash | bytes | The block header's hash. Present for convenience (can be derived from the block header). | 1 |
| header | [Header](../core/data_structures.md#header) | The block header. | 2 |
| txs | repeated bytes | List of transactions committed as part of the block. | 3 |
| decided_last_commit | [CommitInfo](#commitinfo) | Info about the last commit, obtained from the block that was just decided. | 4 |
| byzantine_validators | repeated [Evidence](#evidence) | List of evidence of validators that acted maliciously. | 5 |
* **Response**: * **Response**:
@ -603,7 +600,7 @@ from this condition, but not sure), and _p_ receives a Precommit message for rou
* This method is equivalent to the call sequence `BeginBlock`, [`DeliverTx`], * This method is equivalent to the call sequence `BeginBlock`, [`DeliverTx`],
`EndBlock`, `Commit` in the previous version of ABCI. `EndBlock`, `Commit` in the previous version of ABCI.
* The header exactly matches the Tendermint header of the proposed block. * The header exactly matches the Tendermint header of the proposed block.
* The Application can use `RequestFinalizeBlock.last_commit_info` and `RequestFinalizeBlock.byzantine_validators`
* The Application can use `RequestFinalizeBlock.decided_last_commit` and `RequestFinalizeBlock.byzantine_validators`
to determine rewards and punishments for the validators. to determine rewards and punishments for the validators.
* The application must execute the transactions in full, in the order they appear in `RequestFinalizeBlock.txs`, * The application must execute the transactions in full, in the order they appear in `RequestFinalizeBlock.txs`,
before returning control to Tendermint. Alternatively, it can commit the candidate state corresponding to the same block before returning control to Tendermint. Alternatively, it can commit the candidate state corresponding to the same block
@ -619,7 +616,7 @@ from this condition, but not sure), and _p_ receives a Precommit message for rou
for blocks `H+1`, `H+2`, and `H+3`. Heights following a validator update are affected in the following way: 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+1`: `NextValidatorsHash` includes the new `validator_updates` value.
- Height `H+2`: The validator set change takes effect and `ValidatorsHash` is updated. - Height `H+2`: The validator set change takes effect and `ValidatorsHash` is updated.
- Height `H+3`: `last_commit_info` is changed to include the altered validator set.
- Height `H+3`: `decided_last_commit` now includes the altered validator set.
* `ResponseFinalizeBlock.consensus_param_updates` returned for block `H` apply to the consensus * `ResponseFinalizeBlock.consensus_param_updates` returned for block `H` apply to the consensus
params for block `H+1`. For more information on the consensus parameters, params for block `H+1`. For more information on the consensus parameters,
see the [application spec entry on consensus parameters](../abci/apps.md#consensus-parameters). see the [application spec entry on consensus parameters](../abci/apps.md#consensus-parameters).
@ -728,25 +725,16 @@ Most of the data structures used in ABCI are shared [common data structures](../
| DUPLICATE_VOTE | 1 | | DUPLICATE_VOTE | 1 |
| LIGHT_CLIENT_ATTACK | 2 | | 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 ### ConsensusParams
* **Fields**: * **Fields**:
| Name | Type | Description | Field Number | | 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 |
| 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 | | 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 | | 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 |
| version | [VersionsParams](../core/data_structures.md#versionparams) | The ABCI application version. | 4 |
### ProofOps ### ProofOps
@ -790,18 +778,47 @@ Most of the data structures used in ABCI are shared [common data structures](../
* **Fields**: * **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 |
| tendermint_signed_extension | bytes | Indicates whether or not the validator signed the last block | 3 |
| app_signed_extension | bytes | Indicates whether or not the validator signed the last block | 3 |
| 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**: * **Usage**:
* Indicates whether a validator signed the last block, allowing for rewards
based on validator availability
* `tendermint_signed_extension` conveys the part of the validator's vote extension that was signed by Tendermint.
* `app_signed_extension` conveys the optional *app_signed* part of the validator's vote extension.
* 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 | Non-deterministic extension provided by the sending validator's Application. | 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` contains the sending validator's vote extension, which is signed by Tendermint. It can be empty
### 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 ### ExecTxResult
@ -843,3 +860,23 @@ Most of the data structures used in ABCI are shared [common data structures](../
|------------|-----------------------|------------------------------------------------------------------|--------------| |------------|-----------------------|------------------------------------------------------------------|--------------|
| action | [TxAction](#txaction) | What should Tendermint do with this transaction? | 1 | | action | [TxAction](#txaction) | What should Tendermint do with this transaction? | 1 |
| tx | bytes | Transaction contents | 2 | | tx | bytes | Transaction contents | 2 |
### 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.

+ 2
- 1
spec/abci++/abci++_tmint_expected_behavior_002_draft.md View File

@ -10,7 +10,8 @@ title: Tendermint's expected behavior
This section describes what the Application can expect from Tendermint. 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 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:
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; * Tendermint will decide in round 0;
* `PrepareProposal` will be called exactly once at the proposer process of round 0, height _h_; * `PrepareProposal` will be called exactly once at the proposer process of round 0, height _h_;


+ 15
- 12
spec/core/data_structures.md View File

@ -230,17 +230,20 @@ enum BlockIDFlag {
A vote is a signed message from a validator for a particular block. A vote is a signed message from a validator for a particular block.
The vote includes information about the validator signing it. When stored in the blockchain or propagated over the network, votes are encoded in Protobuf. The vote includes information about the validator signing it. When stored in the blockchain or propagated over the network, votes are encoded in Protobuf.
| Name | Type | Description | Validation |
|------------------|---------------------------------|---------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|
| Type | [SignedMsgType](#signedmsgtype) | Either prevote or precommit. [SignedMsgType](#signedmsgtype) | A Vote is valid if its corresponding fields are included in the enum [signedMsgType](#signedmsgtype) |
| Height | uint64 | Height for which this vote was created for | Must be > 0 |
| Round | int32 | Round that the commit corresponds to. | Must be > 0 |
| BlockID | [BlockID](#blockid) | The blockID of the corresponding block. | [BlockID](#blockid) |
| Timestamp | [Time](#Time) | Timestamp represents the time at which a validator signed. | [Time](#time) |
| ValidatorAddress | slice of bytes (`[]byte`) | Address of the validator | Length must be equal to 20 |
| ValidatorIndex | int32 | Index at a specific block height that corresponds to the Index of the validator in the set. | must be > 0 |
| Signature | slice of bytes (`[]byte`) | Signature by the validator if they participated in consensus for the associated bock. | Length of signature must be > 0 and < 64 |
The vote extension is not part of the [`CanonicalVote`](#canonicalvote).
| Name | Type | Description | Validation |
|--------------------|---------------------------------|---------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|
| Type | [SignedMsgType](#signedmsgtype) | Either prevote or precommit. [SignedMsgType](#signedmsgtype) | A Vote is valid if its corresponding fields are included in the enum [signedMsgType](#signedmsgtype) |
| Height | uint64 | Height for which this vote was created. | Must be > 0 |
| Round | int32 | Round that the commit corresponds to. | Must be > 0 |
| BlockID | [BlockID](#blockid) | The blockID of the corresponding block. | [BlockID](#blockid) |
| Timestamp | [Time](#Time) | The time at which a validator signed. | [Time](#time) |
| ValidatorAddress | slice of bytes (`[]byte`) | Address of the validator | Length must be equal to 20 |
| ValidatorIndex | int32 | Index at a specific block height that corresponds to the Index of the validator in the set. | must be > 0 |
| Signature | slice of bytes (`[]byte`) | Signature by the validator if they participated in consensus for the associated bock. | Length of signature must be > 0 and < 64 |
| Extension | slice of bytes (`[]byte`) | The vote extension provided by the Application. Only valid for precommit messages. | Length must be 0 if Type != `SIGNED_MSG_TYPE_PRECOMMIT` |
| ExtensionSignature | slice of bytes (`[]byte`) | Signature by the validator if they participated in consensus for the associated bock. | Length must be 0 if Type != `SIGNED_MSG_TYPE_PRECOMMIT`; else length must be > 0 and < 64 |
## CanonicalVote ## CanonicalVote
@ -250,7 +253,7 @@ the fields.
```proto ```proto
message CanonicalVote { message CanonicalVote {
SignedMsgType type = 1; SignedMsgType type = 1;
fixed64 height = 2;
fixed64 height = 2;
sfixed64 round = 3; sfixed64 round = 3;
CanonicalBlockID block_id = 4; CanonicalBlockID block_id = 4;
google.protobuf.Timestamp timestamp = 5; google.protobuf.Timestamp timestamp = 5;


Loading…
Cancel
Save