-
Notifications
You must be signed in to change notification settings - Fork 0
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
Include failed transaction in a block #1451
Open
bzawisto
wants to merge
15
commits into
main
Choose a base branch
from
1443-included-failed-transaction-in-a-block
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
149390a
Include failed transaction in a block
914da9b
Fixes
6310695
Fixes
24aef79
Update Changelog
1d555cc
Merge branch 'main' into 1443-included-failed-transaction-in-a-block
f67b962
Merge branch 'main' into 1443-included-failed-transaction-in-a-block
bzawisto 62a4fe3
Addressed review feedback
fb9c329
Merge branch '1443-included-failed-transaction-in-a-block' of github.…
b8f741b
Merge branch 'main' into 1443-included-failed-transaction-in-a-block
20b212c
Fmt
89601a6
Unused code
9877425
Further work
9bba1a1
Handle non-evm code type
ae03e9f
Fmt
4c7f80d
Fix
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like we are re-implementing things that should really be handled inside
revm
. I'm quite worried about doing this because when we did it before (when we depended on sputnik) we got lots of the edge cases wrong.Just to summarise my understanding of the root issue here - The problem is that transactions get dropped from the transaction pool if we try to execute them and after executing, realise that there is not enough space left in the block. Could we not instead solve that issue by being more strict on the condition by which we consider executing a transaction - Instead of (optimistically) executing the next transaction and checking it fits, what if we checked the maximum gas spend of a transaction before executing it and stop building the block if it doesn't fit. That way, we only execute a transaction once we are certain it can be included in the block.
reth
does this and I don't think its a problem from the user's perspective if their transaction with an overly large gas limit gets included one block later than it theoretically could have.Am I making sense? Happy to have a chat to discuss this instead if you prefer.
cc @DrZoltanFazekas
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem here is actually different (matching block gas limit has already been implemented and merged).
There's a user that submits x transactions and at the time the block is proposed one of the transaction fails to execute because it turned out the user has no longer enough funds (all transactions entered mempool because each individually met the criteria).
Currently we just drop this transaction - it's neither included in a block nor queryable by get_transaction_receipt. User code keeps polling for receipt, but it never receives it so it just times out after several attempts.
In addition, revm handles such cases as
Err(EVMError)
- withInvalidTransaction
. The same way it signals database errors. In such case you won't getResultAndState
.There are a few ways of handling it:
1). Detect all but Database Errors and treat them as if they were regular failures (e.g. out of gas). In case of lack of funds, this will be just unsuccessful transaction that should be marked as failed. This approach requires doing what is done now or was done previously. Plus the nonce is increased and user pays a fee (which I believe is a behaviour similar to zq1). This is why
revm::primitives::Account
is used - we can then apply delta inapply_delta_evm
.Do the same thing as 1) but don't enforce fees and nonce mutation - then we just construct empty
ResultAndState
and no deltas are applied. User will have to resubmit txn with the same nonce - this could becomeHandle failures and re-insert txn to mempool - this doesn't solve the problem of hung clients waiting for receipts but there's a hope that some other txn might be a transfer to this user and affected transaction will be included in next proposal (since lack of funds will no longer apply).
CC: @DrZoltanFazekas @JamesHinshelwood
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I preproduced the case on the Holesky testnet, which we can consider as a "reference" for correct behaviour. First I reduced the balance of my account
0xd819ffce7a58b1e835c25617db7b46a00888b013
to0.000008323450116360 ether
. Then I sent 10 simple transfer transactions knowing that after 5 of them my account will run out of gas. The first 5 transactions were mined in the same block, you can see them as the 5 topmost transactions in the list: https://holesky.etherscan.io/address/0xd819ffce7a58b1e835c25617db7b46a00888b013. I also got the receipts for those 5 transactions. Then my script got stuck waiting for further receipts and timed out minutes later with:In the Holesky RPC node's mempool there was no
pending
orqueued
transaction from my account, so the other 5 transactions for which there wasn't enough balance left must have been dropped.Note the difference between Holesky and our prototestnet: on the prototestnet the validators would drop the other 5 transactions, but they would stay in the API nodes' mempool as
pending
(forever). On Holesky, the 5 transactions were dropped on the API node too.