New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
abci: use EndBlock to control empty block creation #1909
Comments
It's good idea giving the application this privilege to decide when pausing block creation. |
Another thing we could consider: We could remove the dependence on AppHash in the meantime, and only make blocks if there are transactions (or evidence). It means we won't have proofs for time-dependent transitions in the empty proofBlock, but perhaps that is worth it to eliminate the confusion in this feature. We'd still need to make an empty proofBlock if the last block has transactions so we can get proofs for the new state resulting from the previous block. |
@ebuchman Can we move "AppHash change" in EndBlock or StateCommit (introduce new one) hook and assign AppHash in current block before commit (like validator set)? I am not sure any implications it might have. Or atleast have a configuration flag to disable support for block proof? |
how about processing but not commiting empty block? I mean every node agree that empty block won't change the state... Just an idea... |
Note that an application may want to punish absent validators and therefore application state may potentially change in every block. Also applications may want to use block timestamps to perform some time-dependent transitions, which also implies changing hash with every block. Therefore it may be hard to imagine a non-enterprise (local) application which doesn’t potentially change hash with every block, however light clients don’t necessarily need to be interested in such changes. Not depending on Still there may be situations where an application wants to accelerate block creation or create next block in a predictable time, for example when it announces a change in the validator set, so either introducing a |
So I think we agree that application can decide to commit an empty block or not. Imagine there is an empty block and application decide to not commit it. Then the previous round will be repeated with same validator set, note that most nodes are in consensus about it. In this case the empty block will be processed but not committed and app hash won't change (either the block height). |
Someone want to write ADR-036 for this? It should include a mechanism for the app to control the rate of empty block production through ABCI, but I don't think we want it in the ConsensusParams, because we don't need it to be hashed, and it could conceivably stay a subjective/local/non-consensus setting. Should we use Query for this - to ask the app if or when to make the next empty block? Maybe a path like |
@ebuchman may be a stupid question but what is ADR-036? Would love to fix whole empty block thing between tendermint/cosmos-sdk. |
ADR-36 is an unwritten Architecture Decision Record justifying this change and describing details of its design. See other ADRs for examples: https://github.com/tendermint/tendermint/tree/develop/docs/architecture Issue #2313 tracks the assignment of numbers to new ADRs. Would be great if you want to start by writing this up. |
@ebuchman Great. I will work on it. |
I would like to share my experience since it may help you addressing this issue. Also look here: cosmos/iavl#128 |
Yeh that's a nice idea but I'm not sure it's feasible in practice - apps may want to do things like store the header in the state, or otherwise change the state based on timers even if there's no txs. So we can't really assume that an empty block will have no effect on state |
Without reaching any consensus how can they store things like timestamp? Did you check the iavl project. I found that this project always change that hash anytime the save method calls. I assume some applications using iavl for storing their data so I believe this code is devil here! ==UPDATE== |
@b00f Three use cases (from Ercoin):
What benefit does creating an empty block give in these cases? |
To better understand this special cases, If |
In normal scenario each block determines only one state. The hash of this state is signed by the validator set in the next block, but can be calculated without these signatures (without next block). Empty block may be needed by light clients which are not capable of calculating application state themselves. |
Data should be strictly deterministic (not something like timestamp or random data). My point is here: Tendermint should let application decides to make a block or not. If developers are confident enough the block can be ignored. |
StreamEvents. When serialising BlockExecutions into StreamEvents it is possible that we do not detect dropped SteamEvents when deserialising (consuming) the SteamEvents later. This PR makes the StreamEvent consumers, namely: ConsumeBlockExecutions, BlockAccumulator, and TxStack throw errors if there is an incorrect number of events streamed within each container (BlockExecution or TxExecution). To do this a checksum NumTxs and NumEvents is added to BeginBlock and BeginTx respectively. This allows Vent to crash if it sees an invalid stream (for example due to messages being dropped due to load on Burrow's event emitter) or a transport issue. Vent can then restart from its previous good offset. Annoyance: I had to add in Predecessor to the BlockExecution and BeginBlock messages in order to track the previous _expected_ block since we do not store empty blocks in state to avoid changing the AppHash (which itself is just a workaround for an outstanding issue in tendermint tendermint/tendermint#1909) This PR was in response to suspected event drops in Vent in production. Signed-off-by: Silas Davis <silas@monax.io>
StreamEvents. When serialising BlockExecutions into StreamEvents it is possible that we do not detect dropped SteamEvents when deserialising (consuming) the SteamEvents later. This PR makes the StreamEvent consumers, namely: ConsumeBlockExecutions, BlockAccumulator, and TxStack throw errors if there is an incorrect number of events streamed within each container (BlockExecution or TxExecution). To do this a checksum NumTxs and NumEvents is added to BeginBlock and BeginTx respectively. This allows Vent to crash if it sees an invalid stream (for example due to messages being dropped due to load on Burrow's event emitter) or a transport issue. Vent can then restart from its previous good offset. Annoyance: I had to add in Predecessor to the BlockExecution and BeginBlock messages in order to track the previous _expected_ block since we do not store empty blocks in state to avoid changing the AppHash (which itself is just a workaround for an outstanding issue in tendermint tendermint/tendermint#1909) This PR was in response to suspected event drops in Vent in production. Signed-off-by: Silas Davis <silas@monax.io>
StreamEvents. When serialising BlockExecutions into StreamEvents it is possible that we do not detect dropped SteamEvents when deserialising (consuming) the SteamEvents later. This PR makes the StreamEvent consumers, namely: ConsumeBlockExecutions, BlockAccumulator, and TxStack throw errors if there is an incorrect number of events streamed within each container (BlockExecution or TxExecution). To do this a checksum NumTxs and NumEvents is added to BeginBlock and BeginTx respectively. This allows Vent to crash if it sees an invalid stream (for example due to messages being dropped due to load on Burrow's event emitter) or a transport issue. Vent can then restart from its previous good offset. Annoyance: I had to add in Predecessor to the BlockExecution and BeginBlock messages in order to track the previous _expected_ block since we do not store empty blocks in state to avoid changing the AppHash (which itself is just a workaround for an outstanding issue in tendermint tendermint/tendermint#1909) This PR was in response to suspected event drops in Vent in production. Signed-off-by: Silas Davis <silas@monax.io>
I'm removing this from milestone 0.34 (tentatively scheduled for mid-to-late May), since it still needs an ADR and isn't a priority for the other features in that milestone. I'll keep it in milestone 1.0 so it doesn't get deprioritized completely. If anyone feels differently, please speak up. |
@mdyring this issue has come up recently again. We wanted to see if you would still like to use it |
@marbar3778 yeah I think this would be a nice addition, what do you think @haasted and @blewater? |
I think it would still be a valuable addition. I believe that the Our solution to this has been to move stuff out of the app_state and into an external database. Being able to just signal that a finalizing block is not needed for this state change seems to be the superior option to me. |
…include tendermint/tendermint#1909 in this spec" This reverts commit 22e8aaf.
…include tendermint/tendermint#1909 in this spec" This reverts commit 22e8aaf.
…include tendermint/tendermint#1909 in this spec" This reverts commit 22e8aaf.
…include tendermint/tendermint#1909 in this spec" This reverts commit 22e8aaf.
…include tendermint/tendermint#1909 in this spec" This reverts commit 22e8aaf.
…include tendermint/tendermint#1909 in this spec" This reverts commit 22e8aaf.
Any update on this? |
if u don't plan to fix this anytime soon, please put that on your documentation. |
Since some apps will change the app hash every block, even with empty blocks, setting
create_empty_blocks=false
won't achieve anything.To solve this, we could add a
Pause bool
field to ResponseEndBlock that tells Tendermint whether to make a new block right away or not.We should write a proper ADR before making this change. Note that any state transitions that occur in the last block committed will not have light-client proofs until the next block is committed, so apps need to be careful when setting
Pause=true
The text was updated successfully, but these errors were encountered: