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 newCheckTx
. AfterCommit
, 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):
- Client sends
BeginBlock
. - Server responds to
BeginBlock
. - Client receives a new transaction X and sends
CheckTx
. - Client sends
EndBlock
. - Server responds to
EndBlock
. - Client sends
Commit
. - Server responds to
Commit
. According to the documentation, the server may now reset state copy maintained for the purpose of checking transactions (why not atEndBlock
?). - 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.
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:
- Client sends BeginBlock.
- Server responds to BeginBlock.
- Client receives a new transaction X and sends CheckTx.
- Client sends EndBlock.
- Server responds to EndBlock.
6a. Client flushes mempool connection
6b. Server responds to CheckTx
6c. Client sends Commit.
- 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 CheckTx
s have been received.