tendermint/abci

It is not known to which height CheckTx messages refer

KrzysiekJ opened this issue · 2 comments

The documentation on CheckTx states:

Tendermint runs CheckTx and DeliverTx concurrently with eachother, though on distinct ABCI connections - the mempool connection and the consensus connection, respectively.

The application should maintain a separate state to support CheckTx. This state can be reset to the latest committed state during Commit, where Tendermint ensures the mempool is locked and not sending new CheckTx. After Commit, the mempool will rerun CheckTx on all remaining transactions, throwing out any that are no longer valid.

It’s unclear what will happen if messages from different connections are not processed in the order of sending. Let’s assume the following scenario (“server” and “client” refer to ABCI):

  1. Client sends BeginBlock.
  2. Server responds to BeginBlock.
  3. Client receives a new transaction X and sends CheckTx.
  4. Client sends EndBlock.
  5. Server responds to EndBlock.
  6. Client sends Commit.
  7. Server responds to Commit. According to the documentation, the server may now reset state copy maintained for the purpose of checking transactions (why not at EndBlock?).
  8. Client now wants to recheck all transactions remaining in the mempool (if he is a proposer, the results will be used to determine which transactions to include in a block).

This scenario is possible because of CheckTx being sent using different connection than other messages. In Ercoin it is actually how it is currently likely to be procedeed, as CheckTx processing is postponed between BeginBlock and Commit. As the client has not received response to CheckTx regarding transaction X, will it send CheckTx for that transaction again? If so, then client will receive two responses regarding the same transaction, and they will likely be different if the server maintains a separate mutable state for the purpose of CheckTx (“mempool state”). How will such situation be handled?

Shouldn’t the fact that the server should reset mempool state be communicated via mempool connection, via a separate message, instead of Commit delivered by consensus connection? Handling of this message would typically be postponed until EndBlock/Commit if BeginBlock has been sent.

Refs tendermint/tendermint#238.

This actually should not be possible because the mempool connection is flushed before calling Commit. Note flushes are synchronous, so the result will be processed before moving on.

So your sequence would be:

  1. Client sends BeginBlock.
  2. Server responds to BeginBlock.
  3. Client receives a new transaction X and sends CheckTx.
  4. Client sends EndBlock.
  5. Server responds to EndBlock.

6a. Client flushes mempool connection
6b. Server responds to CheckTx
6c. Client sends Commit.

  1. Server responds to Commit.

Does that make sense / alleviate your concern ?

Thank you, it sounds perfectly reasonable now. I guess that documentation may be updated, as from “Tendermint ensures the mempool is locked and not sending new CheckTx” it is not obvious that also responses to all CheckTxs have been received.