-
Notifications
You must be signed in to change notification settings - Fork 378
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
fix: catch the out of gas exception in preprocess #2638
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2638 +/- ##
==========================================
+ Coverage 54.99% 60.06% +5.06%
==========================================
Files 595 560 -35
Lines 79775 75825 -3950
==========================================
+ Hits 43872 45542 +1670
+ Misses 32581 26834 -5747
- Partials 3322 3449 +127
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
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.
Conceptually the same as this PR
Do you think it could make sense to swap with using errors.As, as I suggested here?
Also, do you have a testcase that can show what happens when there's an out-of-gas in preprocess/predefine? (that's what we were missing on the other PR)
Yes, Same. This PR catch all places that could throw Out Of Gas Exception in preprocess.
Using return errors in preprocess will change many signatures and also involves catching errors in recursive calls during transcribe. It will be easier to make mistakes in future changes not handling errors or shadowing error in closures and switch case block. Recover and throwing panic(r) is a clearer and simpler approach. I would prefer panic everywhere with exceptions in the VM itself and catch the panics outside of VM and process them as errors in Keeper. In addition, to handle it properly, an OutOfGas exception should be thrown all the way to the ante handler and base app where the gas meter was originally set.
I will add testing cases. |
I'm not suggesting we returns error. Simply, that we are The advantage I see out of this is that we don't have to think to add a condition to not wrap the error any other time we add a recover in vm. (They should happen seldom; but anyway I think the responsibility to do this kind of handling relies in the keeper). |
I found right gas amount to replicate the errors that PR2368 could not reproduce and added proper integration test for that. Both store.GetPackage and store.GetTypeSafe could cause out-of-gas exceptions during preprocess.
using error.As() adds additional unnecessary abstraction. We do use different exception types for VM panics. OutOfGasException and PreprocessError are the examples. To use errors.As(), we not only have to wrap exceptions with errors in VM, but also when we recover from a panic in Keeper, instead of type switching on r.(type), directly, we need to use
It only works if we do not recover any panic and wrap additional information on the call path to the Keeper. However, this is not the case. Currently, we recover from panic, wrap the stack trace, and preprocess trace in PreprocessError. Therefore, we need to differentiate the OutOfGas execution in the VM. This is actually the root cause of the issue we are fixing. |
Hello, I wanted to report the issue, then I saw that the problem was already being fixed, to check, I cloned the fix branch, install gno from this branch and I have the impression of still having the problem, or is it something else? @piux2 https://www.loom.com/share/4c507cb56f0e45b6bec819fdd85c6152?sid=558ebe55-0cb8-4758-ac76-1fe87584d69b |
@MikaelVallenet thank you for the feedback. This is a normal case and not an issue. The chain checks the size of the transaction and consumes gas based on that size. The transaction runs out of gas before it reaches the VM. Line 108 in 763bdd1
For the issue we are trying to solve in this PR, the out-of-gas event happens during preprocessing. Before the fix, it returned the stack trace and preprocess stack. After the fix, it returns a normal out-of-gas message and stack trace, as seen in your video clip. The issue is tricky to reproduce. Only a specific gas amount will be able to trigger it. You can try it out in the newly added txtar file and compare the results before and after the fix. |
Hello, thanks for information but i mean not the first error but the second one around 0:55 of my video (cf. screenshot below) I think it should print the out of gas exception, isn't ? |
Have you checked if you ran the test against the correct version of the chain? I noticed you only ran Also, here is the stack trace from the video at 1:04. At line numbers preprocess.go:137 and preprocess.go:173, they do not match the code that follows the trace in this fixed patch. |
I see, indeed i did not start chain w/ patch thanks for clarification 🙏 |
stderr '--= Error =--' | ||
stderr 'Data: out of gas error' | ||
stderr 'Msg Traces:' | ||
stderr ' 0 /home/runner/work/gno/gno/tm2/pkg/crypto/keys/client/maketx.go:215 - deliver transaction failed: log:out of gas, gasWanted: 60000, gasUsed: 60343 location: ReadFlat' |
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.
stderr ' 0 /home/runner/work/gno/gno/tm2/pkg/crypto/keys/client/maketx.go:215 - deliver transaction failed: log:out of gas, gasWanted: 60000, gasUsed: 60343 location: ReadFlat' | |
stderr ' 0 /home/runner/work/gno/gno/tm2/pkg/crypto/keys/client/maketx.go:215 - deliver transaction failed: log:out of gas, gasWanted: 60000, gasUsed: \d+ location: ReadFlat' |
Same for the other gas used. I'd rather we checked the values of gas in gas_test.go rather than in filetests.
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 chain consumes gas at multiple points outside the VM before reaching the VM. Even inside the VM, a transaction may run out of gas during preprocessing or runtime. To precisely replicate and verify that the bug is fixed in the preprocessing stage, we need to specify an exact gas amount in the integration test.
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 is checking against the error message. If we change how gas calculated, even slightly, this is yet another file where we need to go update the tests. It's an annoyance.
In this case, it's not necessary for the test; this is just checking the error message.
gnoland start | ||
|
||
# add foo package | ||
gnokey maketx addpkg -pkgdir $WORK/foo -pkgpath gno.land/r/foo -gas-fee 1000000ugnot -gas-wanted 211483 -broadcast -chainid=tendermint_test test1 |
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.
gnokey maketx addpkg -pkgdir $WORK/foo -pkgpath gno.land/r/foo -gas-fee 1000000ugnot -gas-wanted 211483 -broadcast -chainid=tendermint_test test1 | |
gnokey maketx addpkg -pkgdir $WORK/foo -pkgpath gno.land/r/foo -gas-fee 1000000ugnot -gas-wanted 500000 -broadcast -chainid=tendermint_test test1 |
like the other comment, let's maybe not make this a test against specific gas results
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.
Same reason as above:
The chain consumes gas at multiple points outside the VM before reaching the VM. Even inside the VM, a transaction may run out of gas during preprocessing or runtime. To precisely replicate and verify that the bug is fixed in the preprocessing stage, we need to specify an exact gas amount in the integration test.
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.
Same here, this command is not supposed fail; in fact it's not prefixed with !
.
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.
Let's change the test and merge this; I'd rather we did it slightly differently but I'm happy to do a follow-up PR myself.
Contributors' checklist...
BREAKING CHANGE: xxx
message was included in the description