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
Try to handle estimateGas predicting that a call will fail #2988
Try to handle estimateGas predicting that a call will fail #2988
Conversation
096afe7
to
05fc391
Compare
df0d533
to
8776c8f
Compare
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.
Left some nits, but we can fix this next week.
Quick note: I added a comment in another PR which is relate to this one: #2623 (review) |
we need to figure out the waiting thingy
8776c8f
to
d400484
Compare
Rebased on latest master, fixed conflicts. Now going to look at the PR comments and test failures. |
493b847
to
13007e9
Compare
As discussed in Github [here](raiden-network#2988 (comment)) we are now using the following order for gas estimation and call() in the smart contract proxy transactions: ```python nonblockchain_preconditions() blockchain_preconditions(consistent_block) # this will also function as a check of the logic that lead us to start the call in the first place gas = gas_estimate(pending_block) if gas is not None: txhash = send_transaction() result = poll(txhash) if gas is None or result is Failure: transaction_mined = gas is not None known_race, msg = check_blockchain_conditions(mined_block if transaction_mined else pending_block) if known_race: raise RaidenRecoverableError('{} {}'.format('Transaction Failed' if transaction_mined else 'Transaction will fail', msg)) else: raise RaidenUnrecoverableError("Bad error -- we don't know why") ```
This PR is first steps towards a model such as: #3268 |
13007e9
to
fc25fa5
Compare
As discussed in Github [here](raiden-network#2988 (comment)) we are now using the following order for gas estimation and call() in the smart contract proxy transactions: ```python nonblockchain_preconditions() blockchain_preconditions(consistent_block) # this will also function as a check of the logic that lead us to start the call in the first place gas = gas_estimate(pending_block) if gas is not None: txhash = send_transaction() result = poll(txhash) if gas is None or result is Failure: transaction_mined = gas is not None known_race, msg = check_blockchain_conditions(mined_block if transaction_mined else pending_block) if known_race: raise RaidenRecoverableError('{} {}'.format('Transaction Failed' if transaction_mined else 'Transaction will fail', msg)) else: raise RaidenUnrecoverableError("Bad error -- we don't know why") ```
86c595d
to
59bf2bd
Compare
Note that with this approach of calling This is no longer the case. We can't detect this anymore and we now just return an As an alternative to allow detecting this we could still do something like below for each proxy transaction where estimateGas fails: gas_limit = estimate_gas()
...
if not gas_limit:
if balanceOf(self.node.address) < GAS_REQUIRED_FOR_TX * gas_price:
raise InsufficientFunds() I can't see any problem with having the above added so I will probably add it in the morning. |
As discussed in Github [here](raiden-network#2988 (comment)) we are now using the following order for gas estimation and call() in the smart contract proxy transactions: ```python nonblockchain_preconditions() blockchain_preconditions(consistent_block) # this will also function as a check of the logic that lead us to start the call in the first place gas = gas_estimate(pending_block) if gas is not None: txhash = send_transaction() result = poll(txhash) if gas is None or result is Failure: transaction_mined = gas is not None known_race, msg = check_blockchain_conditions(mined_block if transaction_mined else pending_block) if known_race: raise RaidenRecoverableError('{} {}'.format('Transaction Failed' if transaction_mined else 'Transaction will fail', msg)) else: raise RaidenUnrecoverableError("Bad error -- we don't know why") ```
Agreed, but the purpose of this PR is not to increase readability but optimize in the case of estimateGas failing so that we don't change the transaction. I hope to continue with #3268 which should help with code readability and organization for the proxies. |
e88c5ef
to
5e255b0
Compare
Codecov Report
@@ Coverage Diff @@
## master #2988 +/- ##
=========================================
Coverage ? 74.75%
=========================================
Files ? 94
Lines ? 12338
Branches ? 1729
=========================================
Hits ? 9223
Misses ? 2474
Partials ? 641
Continue to review full report at Codecov.
|
After the changes introduced by raiden-network#2623 we again rely on gas estimation for the gas limit to provide to an onchain call which is great since it reduces our overall ETH balance requirements. But we don't take into account the fact that if estimateGas returns None it's because the transaction will fail, either due to our account not having enough funds or because the call will just revert somewhere down the line due to the contract logic (e.g. calling settle before closing). With that in mind we can now detect those bad cases a bit earlier and handle them without sending an onchain transaction. This is what this PR is trying to achieve.
- Better logging messages - kwargs - Swap mistaken errors messages on why approve call failed
This is temporary and should be reverted in favour of the web3.py implementation as soon as they include it in a release.
As discussed in Github [here](raiden-network#2988 (comment)) we are now using the following order for gas estimation and call() in the smart contract proxy transactions: ```python nonblockchain_preconditions() blockchain_preconditions(consistent_block) # this will also function as a check of the logic that lead us to start the call in the first place gas = gas_estimate(pending_block) if gas is not None: txhash = send_transaction() result = poll(txhash) if gas is None or result is Failure: transaction_mined = gas is not None known_race, msg = check_blockchain_conditions(mined_block if transaction_mined else pending_block) if known_race: raise RaidenRecoverableError('{} {}'.format('Transaction Failed' if transaction_mined else 'Transaction will fail', msg)) else: raise RaidenUnrecoverableError("Bad error -- we don't know why") ```
If estimate gas fails, then introduce an extra check which will determine if the failure came due to our address not having sufficient ETH to pay for gas
73a6c99
to
9eaa6c3
Compare
Rebased on master to avoid the secret revealed flakiness. |
As discussed in Github [here](#2988 (comment)) we are now using the following order for gas estimation and call() in the smart contract proxy transactions: ```python nonblockchain_preconditions() blockchain_preconditions(consistent_block) # this will also function as a check of the logic that lead us to start the call in the first place gas = gas_estimate(pending_block) if gas is not None: txhash = send_transaction() result = poll(txhash) if gas is None or result is Failure: transaction_mined = gas is not None known_race, msg = check_blockchain_conditions(mined_block if transaction_mined else pending_block) if known_race: raise RaidenRecoverableError('{} {}'.format('Transaction Failed' if transaction_mined else 'Transaction will fail', msg)) else: raise RaidenUnrecoverableError("Bad error -- we don't know why") ```
As discussed in Github [here](raiden-network#2988 (comment)) we are now using the following order for gas estimation and call() in the smart contract proxy transactions: ```python nonblockchain_preconditions() blockchain_preconditions(consistent_block) # this will also function as a check of the logic that lead us to start the call in the first place gas = gas_estimate(pending_block) if gas is not None: txhash = send_transaction() result = poll(txhash) if gas is None or result is Failure: transaction_mined = gas is not None known_race, msg = check_blockchain_conditions(mined_block if transaction_mined else pending_block) if known_race: raise RaidenRecoverableError('{} {}'.format('Transaction Failed' if transaction_mined else 'Transaction will fail', msg)) else: raise RaidenUnrecoverableError("Bad error -- we don't know why") ```
As discussed in Github [here](raiden-network#2988 (comment)) we are now using the following order for gas estimation and call() in the smart contract proxy transactions: ```python nonblockchain_preconditions() blockchain_preconditions(consistent_block) # this will also function as a check of the logic that lead us to start the call in the first place gas = gas_estimate(pending_block) if gas is not None: txhash = send_transaction() result = poll(txhash) if gas is None or result is Failure: transaction_mined = gas is not None known_race, msg = check_blockchain_conditions(mined_block if transaction_mined else pending_block) if known_race: raise RaidenRecoverableError('{} {}'.format('Transaction Failed' if transaction_mined else 'Transaction will fail', msg)) else: raise RaidenUnrecoverableError("Bad error -- we don't know why") ```
As discussed in Github [here](raiden-network#2988 (comment)) we are now using the following order for gas estimation and call() in the smart contract proxy transactions: ```python nonblockchain_preconditions() blockchain_preconditions(consistent_block) # this will also function as a check of the logic that lead us to start the call in the first place gas = gas_estimate(pending_block) if gas is not None: txhash = send_transaction() result = poll(txhash) if gas is None or result is Failure: transaction_mined = gas is not None known_race, msg = check_blockchain_conditions(mined_block if transaction_mined else pending_block) if known_race: raise RaidenRecoverableError('{} {}'.format('Transaction Failed' if transaction_mined else 'Transaction will fail', msg)) else: raise RaidenUnrecoverableError("Bad error -- we don't know why") ```
After the changes introduced by #2623 we again rely on gas estimation for the gas limit to provide to an onchain call which is great since it reduces our overall ETH balance requirements.
But we don't take into account the fact that if estimateGas returns
None
it'sbecause the transaction will fail, either due to our account not having enough
funds or because the call will just revert somewhere down the line due to the
contract logic (e.g. calling settle before closing).
With that in mind we can now detect those bad cases a bit earlier and handle
them without sending an onchain transaction. This is what this PR is trying to achieve.
Admittedly all those cases are bad ones. Since all the checks should have stopped us from getting into that part of the code in the first place, unless we expected that sending an onchain transaction will succeed.