github.com/aakash4dev/cometbft@v0.38.2/spec/abci/abci++_comet_expected_behavior.md (about)

     1  ---
     2  order: 4
     3  title: CometBFT's expected behavior
     4  ---
     5  
     6  # CometBFT's expected behavior
     7  
     8  ## Valid method call sequences
     9  
    10  This section describes what the Application can expect from CometBFT.
    11  
    12  The Tendermint consensus algorithm, currently adopted in CometBFT, is designed to protect safety under any network conditions, as long as
    13  less than 1/3 of validators' voting power is byzantine. Most of the time, though, the network will behave
    14  synchronously, no process will fall behind, and there will be no byzantine process. The following describes
    15  what will happen during a block height _h_ in these frequent, benign conditions:
    16  
    17  * Consensus will decide in round 0, for height _h_;
    18  * `PrepareProposal` will be called exactly once at the proposer process of round 0, height _h_;
    19  * `ProcessProposal` will be called exactly once at all processes, and
    20    will return _accept_ in its `Response*`;
    21  * `ExtendVote` will be called exactly once at all processes;
    22  * `VerifyVoteExtension` will be called exactly _n-1_ times at each validator process, where _n_ is
    23    the number of validators, and will always return _accept_ in its `Response*`;
    24  * `FinalizeBlock` will be called exactly once at all processes, conveying the same prepared
    25    block that all calls to `PrepareProposal` and `ProcessProposal` had previously reported for
    26    height _h_; and
    27  * `Commit` will finally be called exactly once at all processes at the end of height _h_.
    28  
    29  However, the Application logic must be ready to cope with any possible run of the consensus algorithm for a given
    30  height, including bad periods (byzantine proposers, network being asynchronous).
    31  In these cases, the sequence of calls to ABCI++ methods may not be so straightforward, but
    32  the Application should still be able to handle them, e.g., without crashing.
    33  The purpose of this section is to define what these sequences look like in a precise way.
    34  
    35  As mentioned in the [Basic Concepts](./abci%2B%2B_basic_concepts.md) section, CometBFT
    36  acts as a client of ABCI++ and the Application acts as a server. Thus, it is up to CometBFT to
    37  determine when and in which order the different ABCI++ methods will be called. A well-written
    38  Application design should consider _any_ of these possible sequences.
    39  
    40  The following grammar, written in case-sensitive Augmented Backus–Naur form (ABNF, specified
    41  in [IETF rfc7405](https://datatracker.ietf.org/doc/html/rfc7405)), specifies all possible
    42  sequences of calls to ABCI++, taken by a **correct process**, across all heights from the genesis block,
    43  including recovery runs, from the point of view of the Application.
    44  
    45  ```abnf
    46  start               = clean-start / recovery
    47  
    48  clean-start         = init-chain [state-sync] consensus-exec
    49  state-sync          = *state-sync-attempt success-sync info
    50  state-sync-attempt  = offer-snapshot *apply-chunk
    51  success-sync        = offer-snapshot 1*apply-chunk
    52  
    53  recovery            = info consensus-exec
    54  
    55  consensus-exec      = (inf)consensus-height
    56  consensus-height    = *consensus-round decide commit
    57  consensus-round     = proposer / non-proposer
    58  
    59  proposer            = *got-vote [prepare-proposal [process-proposal]] [extend]
    60  extend              = *got-vote extend-vote *got-vote
    61  non-proposer        = *got-vote [process-proposal] [extend]
    62  
    63  init-chain          = %s"<InitChain>"
    64  offer-snapshot      = %s"<OfferSnapshot>"
    65  apply-chunk         = %s"<ApplySnapshotChunk>"
    66  info                = %s"<Info>"
    67  prepare-proposal    = %s"<PrepareProposal>"
    68  process-proposal    = %s"<ProcessProposal>"
    69  extend-vote         = %s"<ExtendVote>"
    70  got-vote            = %s"<VerifyVoteExtension>"
    71  decide              = %s"<FinalizeBlock>"
    72  commit              = %s"<Commit>"
    73  ```
    74  
    75  We have kept some ABCI methods out of the grammar, in order to keep it as clear and concise as possible.
    76  A common reason for keeping all these methods out is that they all can be called at any point in a sequence defined
    77  by the grammar above. Other reasons depend on the method in question:
    78  
    79  * `Echo` and `Flush` are only used for debugging purposes. Further, their handling by the Application should be trivial.
    80  * `CheckTx` is detached from the main method call sequence that drives block execution.
    81  * `Query` provides read-only access to the current Application state, so handling it should also be independent from
    82    block execution.
    83  * Similarly, `ListSnapshots` and `LoadSnapshotChunk` provide read-only access to the Application's previously created
    84    snapshots (if any), and help populate the parameters of `OfferSnapshot` and `ApplySnapshotChunk` at a process performing
    85    state-sync while bootstrapping. Unlike `ListSnapshots` and `LoadSnapshotChunk`, both `OfferSnapshot`
    86    and `ApplySnapshotChunk` _are_ included in the grammar.
    87  
    88  Finally, method `Info` is a special case. The method's purpose is three-fold, it can be used
    89  
    90  1. as part of handling an RPC call from an external client,
    91  2. as a handshake between CometBFT and the Application upon recovery to check whether any blocks need
    92     to be replayed, and
    93  3. at the end of _state-sync_ to verify that the correct state has been reached.
    94  
    95  We have left `Info`'s first purpose out of the grammar for the same reasons as all the others: it can happen
    96  at any time, and has nothing to do with the block execution sequence. The second and third purposes, on the other
    97  hand, are present in the grammar.
    98  
    99  Let us now examine the grammar line by line, providing further details.
   100  
   101  * When a process starts, it may do so for the first time or after a crash (it is recovering).
   102  
   103  >```abnf
   104  >start               = clean-start / recovery
   105  >```
   106  
   107  * If the process is starting from scratch, CometBFT first calls `InitChain`, then it may optionally
   108    start a _state-sync_ mechanism to catch up with other processes. Finally, it enters normal
   109    consensus execution.
   110  
   111  >```abnf
   112  >clean-start         = init-chain [state-sync] consensus-exec
   113  >```
   114  
   115  * In _state-sync_ mode, CometBFT makes one or more attempts at synchronizing the Application's state.
   116    At the beginning of each attempt, it offers the Application a snapshot found at another process.
   117    If the Application accepts the snapshot, a sequence of calls to `ApplySnapshotChunk` method follow
   118    to provide the Application with all the snapshots needed, in order to reconstruct the state locally.
   119    A successful attempt must provide at least one chunk via `ApplySnapshotChunk`.
   120    At the end of a successful attempt, CometBFT calls `Info` to make sure the reconstructed state's
   121    _AppHash_ matches the one in the block header at the corresponding height. Note that the state 
   122    of  the application does not contain vote extensions itself. The application can rely on 
   123    [CometBFT to ensure](./../../docs/rfc/rfc-100-abci-vote-extension-propag.md#base-implementation-persist-and-propagate-extended-commit-history)
   124    the node has all the relevant data to proceed with the execution beyond this point. 
   125  
   126  >```abnf
   127  >state-sync          = *state-sync-attempt success-sync info
   128  >state-sync-attempt  = offer-snapshot *apply-chunk
   129  >success-sync        = offer-snapshot 1*apply-chunk
   130  >```
   131  
   132  * In recovery mode, CometBFT first calls `Info` to know from which height it needs to replay decisions
   133    to the Application. After this, CometBFT enters consensus execution, first in replay mode and then
   134    in normal mode.
   135  
   136  >```abnf
   137  >recovery            = info consensus-exec
   138  >```
   139  
   140  * The non-terminal `consensus-exec` is a key point in this grammar. It is an infinite sequence of
   141    consensus heights. The grammar is thus an
   142    [omega-grammar](https://dl.acm.org/doi/10.5555/2361476.2361481), since it produces infinite
   143    sequences of terminals (i.e., the API calls).
   144  
   145  >```abnf
   146  >consensus-exec      = (inf)consensus-height
   147  >```
   148  
   149  * A consensus height consists of zero or more rounds before deciding and executing via a call to
   150    `FinalizeBlock`, followed by a call to `Commit`. In each round, the sequence of method calls
   151    depends on whether the local process is the proposer or not. Note that, if a height contains zero
   152    rounds, this means the process is replaying an already decided value (catch-up mode).
   153  
   154  >```abnf
   155  >consensus-height    = *consensus-round decide commit
   156  >consensus-round     = proposer / non-proposer
   157  >```
   158  
   159  * For every round, if the local process is the proposer of the current round, CometBFT calls `PrepareProposal`.
   160    A successful execution of `PrepareProposal` implies in a proposal block being (i)signed and (ii)stored
   161    (e.g., in stable storage).
   162  
   163    A crash during this step will direct how the node proceeds the next time it is executed, for the same round, after restarted.
   164    If it crashed before (i), then, during the recovery, `PrepareProposal` will execute as if for the first time.
   165    Following a crash between (i) and (ii) and in (the likely) case `PrepareProposal` produces a different block,
   166    the signing of this block will fail, which means that the new block will not be stored or broadcast.
   167    If the crash happened after (ii), then signing fails but nothing happens to the stored block.
   168    
   169    If a block was stored, it is sent to all validators, including the proposer.
   170    Receiving a proposal block triggers `ProcessProposal` with such a block.
   171  
   172    Then, optionally, the Application is
   173    asked to extend its vote for that round. Calls to `VerifyVoteExtension` can come at any time: the
   174    local process may be slightly late in the current round, or votes may come from a future round
   175    of this height.
   176  
   177  >```abnf
   178  >proposer            = *got-vote [prepare-proposal [process-proposal]] [extend]
   179  >extend              = *got-vote extend-vote *got-vote
   180  >```
   181  
   182  * Also for every round, if the local process is _not_ the proposer of the current round, CometBFT
   183    will call `ProcessProposal` at most once. At most one call to `ExtendVote` may occur only after
   184    `ProcessProposal` is called. A number of calls to `VerifyVoteExtension` can occur in any order
   185    with respect to `ProcessProposal` and `ExtendVote` throughout the round. The reasons are the same
   186    as above, namely, the process running slightly late in the current round, or votes from future
   187    rounds of this height received.
   188  
   189  >```abnf
   190  >non-proposer        = *got-vote [process-proposal] [extend]
   191  >```
   192  
   193  * Finally, the grammar describes all its terminal symbols, which denote the different ABCI++ method calls that
   194    may appear in a sequence.
   195  
   196  >```abnf
   197  >init-chain          = %s"<InitChain>"
   198  >offer-snapshot      = %s"<OfferSnapshot>"
   199  >apply-chunk         = %s"<ApplySnapshotChunk>"
   200  >info                = %s"<Info>"
   201  >prepare-proposal    = %s"<PrepareProposal>"
   202  >process-proposal    = %s"<ProcessProposal>"
   203  >extend-vote         = %s"<ExtendVote>"
   204  >got-vote            = %s"<VerifyVoteExtension>"
   205  >decide              = %s"<FinalizeBlock>"
   206  >commit              = %s"<Commit>"
   207  >```
   208  
   209  ## Adapting existing Applications that use ABCI
   210  
   211  In some cases, an existing Application using the legacy ABCI may need to be adapted to work with ABCI++
   212  with as minimal changes as possible. In this case, of course, ABCI++ will not provide any advantage with respect
   213  to the existing implementation, but will keep the same guarantees already provided by ABCI.
   214  Here is how ABCI++ methods should be implemented.
   215  
   216  First of all, all the methods that did not change from ABCI 0.17.0 to ABCI 2.0, namely `Echo`, `Flush`, `Info`, `InitChain`,
   217  `Query`, `CheckTx`, `ListSnapshots`, `LoadSnapshotChunk`, `OfferSnapshot`, and `ApplySnapshotChunk`, do not need
   218  to undergo any changes in their implementation.
   219  
   220  As for the new methods:
   221  
   222  * `PrepareProposal` must create a list of [transactions](./abci++_methods.md#prepareproposal)
   223    by copying over the transaction list passed in `RequestPrepareProposal.txs`, in the same order.
   224    
   225    The Application must check whether the size of all transactions exceeds the byte limit
   226    (`RequestPrepareProposal.max_tx_bytes`). If so, the Application must remove transactions at the
   227    end of the list until the total byte size is at or below the limit.
   228  * `ProcessProposal` must set `ResponseProcessProposal.status` to _accept_ and return.
   229  * `ExtendVote` is to set `ResponseExtendVote.extension` to an empty byte array and return.
   230  * `VerifyVoteExtension` must set `ResponseVerifyVoteExtension.accept` to _true_ if the extension is
   231    an empty byte array and _false_ otherwise, then return.
   232  * `FinalizeBlock` is to coalesce the implementation of methods `BeginBlock`, `DeliverTx`, and
   233    `EndBlock`. Legacy applications looking to reuse old code that implemented `DeliverTx` should
   234    wrap the legacy `DeliverTx` logic in a loop that executes one transaction iteration per
   235    transaction in `RequestFinalizeBlock.tx`.
   236  
   237  Finally, `Commit`, which is kept in ABCI++, no longer returns the `AppHash`. It is now up to
   238  `FinalizeBlock` to do so. Thus, a slight refactoring of the old `Commit` implementation will be
   239  needed to move the return of `AppHash` to `FinalizeBlock`.
   240  
   241  ## Accommodating for vote extensions
   242  
   243  In a manner transparent to the application, CometBFT ensures the node is provided with all
   244  the data it needs to participate in consensus. 
   245  
   246  In the case of recovering from a crash, or joining the network via state sync, CometBFT will make
   247  sure the node acquires the necessary vote extensions before switching to consensus. 
   248  
   249  If a node is already in consensus but falls behind, during catch-up, CometBFT will provide the node with 
   250  vote extensions from past heights by retrieving the extensions within `ExtendedCommit` for old heights that it had previously stored.
   251  
   252  We realize this is sub-optimal due to the increase in storage needed to store the extensions, we are 
   253  working on an optimization of this implementation which should alleviate this concern.
   254  However, the application can use the existing `retain_height` parameter to decide how much
   255  history it wants to keep, just as is done with the block history. The network-wide implications
   256  of the usage of `retain_height` stay the same.
   257  The decision to store 
   258  historical commits and potential optimizations, are discussed in detail in [RFC-100](./../../docs/rfc/rfc-100-abci-vote-extension-propag.md#current-limitations-and-possible-implementations)
   259  
   260  ## Handling upgrades to ABCI 2.0
   261  
   262  If applications upgrade to ABCI 2.0, CometBFT internally ensures that the [application setup](./abci%2B%2B_app_requirements.md#application-configuration-required-to-switch-to-abci-20) is reflected in its operation.
   263  CometBFT retrieves from the application configuration the value of `VoteExtensionsEnableHeight`( *h<sub>e</sub>*,),
   264  the height at which vote extensions are required for consensus to proceed, and uses it to determine the data it stores and data it sends to a peer that is catching up.
   265  
   266  Namely, upon saving the block for a given height *h* in the block store at decision time
   267  * if *h ≥ h<sub>e</sub>*, the corresponding extended commit that was used to decide locally is saved as well
   268  * if *h < h<sub>e</sub>*, there are no changes to the data saved
   269  
   270  In the catch-up mechanism, when a node *f* realizes that another peer is at height *h<sub>p</sub>*, which is more than 2 heights behind,
   271  * if *h<sub>p</sub> ≥ h<sub>e</sub>*, *f* uses the extended commit to
   272        reconstruct the precommit votes with their corresponding extensions
   273  * if *h<sub>p</sub> < h<sub>e</sub>*, *f* uses the canonical commit to reconstruct the precommit votes,
   274        as done for ABCI 1.0 and earlier.