From ddb1eb27c95ad07d9df1c390e4420cd09c377c3b Mon Sep 17 00:00:00 2001 From: Sergio Mena Date: Tue, 21 Dec 2021 11:07:04 +0100 Subject: [PATCH] Editorial changes --- .../abci++_app_requirements_002_draft.md | 2 +- .../abci++/abci++_basic_concepts_002_draft.md | 61 +++++++++---------- spec/abci++/abci++_methods_002_draft.md | 1 - ...bci++_tmint_expected_behavior_002_draft.md | 11 +++- 4 files changed, 41 insertions(+), 34 deletions(-) diff --git a/spec/abci++/abci++_app_requirements_002_draft.md b/spec/abci++/abci++_app_requirements_002_draft.md index bd312cabc..f931537b4 100644 --- a/spec/abci++/abci++_app_requirements_002_draft.md +++ b/spec/abci++/abci++_app_requirements_002_draft.md @@ -83,7 +83,7 @@ However, if there is a (deterministic) bug in `ExtendVote` or `VerifyVoteExtensi we will face the same liveness issues as described for Requirement 3, as Precommit messages with invalid vote extensions will be discarded. -* Requirement 7 [`VerifyVoteExtension`, determinism-1]: `VerifyVoteExtension` is a (deterministic) function of +* Requirement 7 [`VerifyVoteExtension`, determinism-1]: `VerifyVoteExtension` is a (deterministic) function of the current state, the vote extension received, and the prepared proposal that the extension refers to. In other words, for any correct process $p$, and any arbitrary vote extension $e$, and any arbitrary block $w$, if $p$'s (resp. $q$'s) Tendermint calls `RequestVerifyVoteExtension` on $e$ and $w$ at height $h$, diff --git a/spec/abci++/abci++_basic_concepts_002_draft.md b/spec/abci++/abci++_basic_concepts_002_draft.md index cd1575d46..be9e2ee73 100644 --- a/spec/abci++/abci++_basic_concepts_002_draft.md +++ b/spec/abci++/abci++_basic_concepts_002_draft.md @@ -16,23 +16,23 @@ When Tendermint and the ABCI++ application are run as separate processes, Tender 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 +### **Consensus** connection * Driven by a consensus protocol and is responsible for block execution. * Handles the `InitChain`, `PrepareProposal`, `ProcessProposal`, `ExtendVote`, `VerifyVoteExtension`, and `FinalizeBlock` method calls. -#### **Mempool** connection +### **Mempool** connection * For validating new transactions, before they're shared or included in a block. * Handles the `CheckTx` calls. -#### **Info** connection +### **Info** connection * For initialization and for queries from the user. * Handles the `Info` and `Query` calls. -#### **Snapshot** connection +### **Snapshot** connection * For serving and restoring [state sync snapshots](../abci/apps.md#state-sync). * Handles the `ListSnapshots`, `LoadSnapshotChunk`, `OfferSnapshot`, and `ApplySnapshotChunk` calls. @@ -48,7 +48,7 @@ More details on managing state across connections can be found in the section on ## Errors The `Query`, and `CheckTx` methods include a `Code` field in their `Response*`. -The `Code` field is also included in type `DeliverTxResult`, used by +The `Code` field is also included in type `DeliverTxResult`, used by method `FinalizeBlock`'s `Response*`. Field `Code` is meant to contain an application-specific response code. A response code of `0` indicates no error. Any other response code @@ -56,12 +56,12 @@ 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`. +Application. The `Codespace` is a namespace for the `Code`. Methods `Echo`, `Info`, and `InitChain` do not return errors. An error in any of these methods represents a critical issue that Tendermint has no reasonable way to handle. If there is an error in one -of these methods, the application must crash to ensure that the error is safely +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 @@ -83,7 +83,7 @@ it is already included. ### `DeliverTxResult` (as part of `FinalizeBlock`) -The `DeliverTxResult` type delivers transactions from Tendermint to the application. +The `DeliverTxResult` type delivers transactions from Tendermint to the Application. When Tendermint receives a `ReponseFinalizeBlock` containing a `DeliverTxResult` with a non-zero `Code`, the response code is logged. The transaction was already included in a block, so the `Code` does not influence @@ -91,8 +91,8 @@ Tendermint consensus. ### `Query` -The `Query` ABCI++ method queries the application for information about application state. -When Tendermint receives a `ResponseQuery` with a non-zero `Code`, this code is +The `Query` ABCI++ method queries the Application for information about application state. +When Tendermint receives a `ResponseQuery` with a non-zero `Code`, this code is returned directly to the client that initiated the query. ## Events @@ -106,7 +106,7 @@ 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 +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. @@ -176,10 +176,10 @@ Example: Tendermint's security model relies on the use of "evidence". Evidence is proof of malicious behaviour by a network participant. It is the responsibility of Tendermint to detect such malicious behaviour. When malicious behavior is detected, Tendermint -will gossip evidence of the behavior to other nodes and commit the evidence to -the chain once it is verified by all validators. This evidence will then be -passed on to the application through ABCI++. It is the responsibility of the -application to handle the evidence and exercise punishment. +will gossip evidence of the behavior to other nodes and commit the evidence to +the chain once it is verified by all validators. This evidence will then be +passed on to the Application through ABCI++. It is the responsibility of the +Application to handle the evidence and exercise punishment. EvidenceType has the following protobuf format: @@ -203,17 +203,17 @@ precommit votes for the decided block that it receives before the block is decid and then includes these votes in the proposed block for the next height whenever the local process is the proposer of the round. -When Tendermint's consensus is about to send a non-`nil` precommit message, it calls +When Tendermint's consensus is about to send a non-`nil` precommit message, it calls method `ExtendVote`, which gives the Application the opportunity to include non-deterministic data, opaque to Tendermint, that will be attached to the precommit message. The data, called _vote extension_, will also be part of the proposed block in the next height, along with the vote it is extending. 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. The Application may also choose not to include any vote extension. When another process receives a precommit message with a vote extension, it calls -method `VerifyVoteExtension` so that the application can validate the data received. +method `VerifyVoteExtension` so that the Application can validate the data received. If the validation fails, the precommit message will be deemed invalid and ignored by Tendermint. This has negative impact on Tendermint's liveness, i.e., if repeatedly vote extensions by correct validators cannot be verified by correct validators, Tendermint may not be able to finalize a block even if sufficiently many (+2/3) of the validators send precommit votes for that block. Thus, `VerifyVoteExtension` should only be used with special care. As a general rule, an Application that detects an invalid vote extension SHOULD @@ -231,13 +231,13 @@ 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 +like Tendermint Core. The Application must only change its state based on input from block execution (`FinalizeBlock` calls), and not through any other kind of request. This is the only way to ensure all nodes see the same transactions and compute the same results. Some Applications may choose to execute the blocks that are about to be proposed -(via `PrepareProposal`), or those that the application is asked to validate +(via `PrepareProposal`), or those that the Application is asked to validate (via `Processproposal`). However the state changes caused by processing those proposed blocks must never replace the previous state until `FinalizeBlock` confirms the block decided. @@ -271,7 +271,7 @@ See [#56](https://github.com/tendermint/abci/issues/56) for original discussion. Note that some methods (`Query, CheckTx, FinalizeBlock`) return explicitly non-deterministic data in the form of `Info` and `Log` fields. The `Log` is -intended for the literal output from the application's logger, while the +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. @@ -280,7 +280,7 @@ on them. All other fields in the `Response*` must be strictly deterministic. The first time a new blockchain is started, Tendermint calls `InitChain`. From then on, method `FinalizeBlock` is executed at the end of each -block, resulting in an updated application state. +block, resulting in an updated Application state. During consensus execution of a block height, before method `FinalizeBlock` is called, methods `PrepareProposal`, `ProcessProposal`, `ExtendVote`, and `VerifyVoteExtension` may be called a number of times. @@ -294,7 +294,7 @@ Tendermint gathers outstanding transactions from the mempool 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 +the (potentially) modified proposal, called _prepared proposal_ in the `Response*` call. The logic modifying the raw proposal can be non-deterministic. When Tendermint receives a prepared proposal it uses method `ProcessProposal` @@ -306,7 +306,6 @@ SHOULD accept a prepared proposal passed via `ProcessProposal`, even if a part o the proposal is invalid (e.g., an invalid transaction); the Application can later ignore the invalid part of the prepared proposal at block execution time. - Cryptographic commitments to the block and transaction results, via the corresponding parameters in `FinalizeBlockResponse` are included in the header of the next block. @@ -362,18 +361,18 @@ state machine snapshots instead of replaying historical blocks. For more details 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 +`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. +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 +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 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 +application with `ApplySnapshotChunk`. When all chunks have been applied, the +Application's `AppHash` is retrieved via an `Info` query. The `AppHash` is then +compared to the blockchain's `AppHash` which is verified via [light client verification](../spec/light-client/verification/README.md). diff --git a/spec/abci++/abci++_methods_002_draft.md b/spec/abci++/abci++_methods_002_draft.md index 29dadd323..e02d1b798 100644 --- a/spec/abci++/abci++_methods_002_draft.md +++ b/spec/abci++/abci++_methods_002_draft.md @@ -531,7 +531,6 @@ In the cases when _p_'s Tendermint is to broadcast `precommit nil` messages (eit * Moreover, application implementors SHOULD always set `ResponseVerifyVoteExtension.accept` to _true_, unless they _really_ know what the potential liveness implications of returning _false_ are. - #### When does Tendermint call it? When a validator _p_ is in Tendermint consensus round _r_, height _h_, state _prevote_ (**TODO** discuss: I think I must remove the state diff --git a/spec/abci++/abci++_tmint_expected_behavior_002_draft.md b/spec/abci++/abci++_tmint_expected_behavior_002_draft.md index 2b011e16b..0b5125f4c 100644 --- a/spec/abci++/abci++_tmint_expected_behavior_002_draft.md +++ b/spec/abci++/abci++_tmint_expected_behavior_002_draft.md @@ -100,6 +100,7 @@ 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 >``` @@ -107,6 +108,7 @@ Let us now examine the grammar line by line, providing further details. * 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, which is a sequence of zero or more consensus heights. + >```abnf >clean-start = init-chain [state-sync] *consensus-height >``` @@ -118,6 +120,7 @@ Let us now examine the grammar line by line, providing further details. 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 @@ -127,6 +130,7 @@ Let us now examine the grammar line by line, providing further details. * In recovery mode, Tendermint first calls `Info` to know from which height it needs to replay decisions to the Application. To replay a decision, Tendermint simply calls `FinalizeBlock` with the decided block at that height. After this, Tendermint enters nomal consensus execution: zero or more consensus heights. + >```abnf >recovery = info *consensus-replay *consensus-height >consensus-replay = decide @@ -134,6 +138,7 @@ Let us now examine the grammar line by line, providing further details. * A consensus height consists of zero or more rounds before deciding via a call to `FinalizeBlock`. In each round, the sequence of method calls depends on whether the local process is the proposer or not. + >```abnf >consensus-height = *consensus-round decide >consensus-round = proposer / non-proposer @@ -141,9 +146,10 @@ Let us now examine the grammar line by line, providing further details. * If the local process is the proposer of the current round, Tendermint starts by calling `PrepareProposal`. No calls to methods related to vote extensions (`ExtendVote`, `VerifyVoteExtension`) can be called - in the present round before `PrepareProposal`. Once `PrepareProposal` is called, calls to + in the present round before `PrepareProposal`. Once `PrepareProposal` is called, calls to `ExtendVote` and `VerifyVoteExtension` can come in any order, although the former will be called at most once in this round. + >```abnf >proposer = prepare-proposal extend-proposer >extend-proposer = *got-vote [extend-vote] *got-vote @@ -153,6 +159,7 @@ Let us now examine the grammar line by line, providing further details. at most once. At most one call to `ExtendVote` can 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. + >```abnf >non-proposer = *got-vote [extend-non-proposer] *got-vote >extend-non-proposer = process-proposal *got-vote [extend-vote] @@ -160,6 +167,7 @@ Let us now examine the grammar line by line, providing further details. * 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"" >offer-snapshot = %s"" @@ -181,6 +189,7 @@ Let us now examine the grammar line by line, providing further details. >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. +>Also, see tendermint/tendermint#7274 ## Failure modes