-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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: handle error and revert data in EthEstimateGas and EthCall #12553
base: master
Are you sure you want to change the base?
Conversation
@aarshkshah1992 I am using lotus/node/impl/full/eth_utils.go Line 333 in 0e7292a
|
node/impl/full/eth.go
Outdated
} | ||
|
||
func (e *EthCallError) Error() string { | ||
return e.Message |
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.
But how will the go-jsonrpc
library extract the data here to then send it to the client ?
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.
We're not exposing the data at all here.
Best way to test this is to write an itest that deploys a contract that does a divide by 0 (so there's a revert) -> send a transaction that executes the contract -> see what error you get when you call I think you'll then see what I'm talking about. The client should see the contract revert reason in the |
@virajbhartiya: I assume you'll re-request review when you're ready for review again. |
Hey @BigLep, yes I'll request a re-review, currently I'm running into a few issues while testing out on devnet so working on fixing those. |
@aarshkshah1992 me and @virajbhartiya was discussing about returning The changes I have pushed are not complete, need to get your thoughts on it, then will finish the changes. |
@akaladarshi Would be great to first get this working e2e on a calibnet node and we can then discuss the exact semantics of the error message. Also, thanks to both for this ! |
@aarshkshah1992 here is the Here is the response from ethereum node for same data |
@akaladarshi @virajbhartiya Great stuff ! That looks correct. Can you also confirm that we ONLY get this data field for contract reverts and that the response for all other errors is the same as it was before ? Once you confirm that, I think we can implement this for the other API as well. Thanks a lot. |
CHANGELOG.md
Outdated
@@ -3,6 +3,17 @@ | |||
# UNRELEASED | |||
|
|||
## New features | |||
|
|||
* Add `EthSendRawTransactionUntrusted` RPC method to be used for the gateway when accepting `EthSendRawTransaction` and `eth_sendRawTransaction`. Applies a tighter limit on the number of messages in the queue from a single sender and applies additional restrictions on nonce increments. ([filecoin-project/lotus#12431](https://github.com/filecoin-project/lotus/pull/12431)) |
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.
You probably need to rebase on master again for all of these to disappear.
chain/types/ethtypes/errors.go
Outdated
|
||
// ErrorCode returns the JSON error code for a revert. | ||
func (e *ExecutionRevertedError) ErrorCode() int { | ||
return 3 |
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.
Why is this hard coded to 3 ?
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.
Don't we have a Code
field on ExecutionRevertedError
? Shouldn't we use that ?
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.
Yeah this (3) should be default error code for EthCall
and EstimateGas
. Will update it.
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 mean we should pass the error code/exit code from the receipt returned by applyMessage
here, right ? So when EthCall
/EthEstimateGas
create this reverted error, they should use the exit code returned by FVM here.
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.
Yeah that make sense, So let me confirm once what kind of error codes FVM returns and I will update it accordingly.
chain/types/ethtypes/errors.go
Outdated
type ExecutionRevertedError struct { | ||
Message string | ||
Code int | ||
Meta []byte |
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.
Don't see this Meta
field being used anywhere. It's neither written to or read from. Should be accepting it in the constructor and setting it ?
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.
We can remove this as we have Data field now.
go.mod
Outdated
@@ -12,6 +12,8 @@ replace github.com/filecoin-project/test-vectors => ./extern/test-vectors // pro | |||
|
|||
replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi // provided via a git submodule | |||
|
|||
replace github.com/filecoin-project/go-jsonrpc => github.com/virajbhartiya/go-jsonrpc v0.0.0-20241011111701-53eab64ec154 |
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.
We will need to change this once the go-jsonrpc
PR lands and we have a release for it.
node/impl/full/eth_utils.go
Outdated
@@ -31,6 +31,10 @@ import ( | |||
"github.com/filecoin-project/lotus/chain/vm" | |||
) | |||
|
|||
const ( | |||
errcodeDefault = -32000 |
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.
What's this for ? Why did we have to add it ?
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.
Will remove it in favor of error code 3
for EthCall
and EstimateGas
, but in other places for execution reverted we need to return this(-32000) code.
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.
@akaladarshi But then why was it not a pre-existing code ? How did we handle this before you raised this PR ?
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 have to look into it little bit what exact error code FVM is returning, that's why I asked it in slack (do we have same error code as ethereum): https://filecoinproject.slack.com/archives/CP50PPW2X/p1728633105115299,
Will check this and update it accordingly.
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.
Irrespective of what it is returning, let's not change the error codes here. We only want the data field to be in like with ETH here -> everything else should stay the same right ?
itests/fevm_test.go
Outdated
@@ -7,14 +7,17 @@ import ( | |||
"encoding/binary" | |||
"encoding/hex" |
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.
Why do we have such a large diff in this file ? Can we get rid of all the unnecessary whitespace changes and only change the test code we need to ? Reviewing diffs like this is tricky.
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.
It's a linter fix, everywhere there is whitespace after //
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.
if this is from your editor doing this automatically then it's typically good practice to disable that--it's fine to make lint fixes but large diffs like that should be done as a separate PR and not come in with a PR where the changes are unrelated, or at least make them minimal (e.g. it's OK to fix up some of these around the site where you're changing things, but usually not the whole file if you can help it.)
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.
So generally I try to do go fmt
in files after changing things that's why sometimes I get large diff, anyway, I will disable it and revert these whitespace changes so we can keep it clean.
node/impl/full/eth.go
Outdated
reason := parseEthRevert(res.MsgRct.Return) | ||
return nil, xerrors.Errorf("message execution failed: exit %s, revert reason: %s, vm error: %s", res.MsgRct.ExitCode, reason, res.Error) | ||
return nil, ethtypes.NewExecutionRevertedWithDataError( | ||
errcodeDefault, |
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.
Shouldn't we pass the exit code on the receipt here ? Why are we passing errcodeDefault
here ?
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.
@aarshkshah1992 actually there was some confusion about what error code to return because, in ethereum there two different kind of error codes for the same message (execution reverted), In EthCall
and EstimateGas
it returns error code 3
and generally while executing message it returns -3200
.
I will the default error code to 3
for EthCall
and EstimateGas
which we were already returning in ErrorCode()
node/impl/full/eth.go
Outdated
@@ -1612,6 +1623,13 @@ func ethGasSearch( | |||
} | |||
|
|||
func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) { | |||
var result ethtypes.EthBytes | |||
defer func() { | |||
if r := recover(); r != nil { |
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.
What is this for ? Why do we need it ?
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.
Removed.
node/impl/full/eth.go
Outdated
return ethtypes.EthBytes{}, nil | ||
} else if len(invokeResult.MsgRct.Return) > 0 { | ||
return cbg.ReadByteArray(bytes.NewReader(invokeResult.MsgRct.Return), uint64(len(invokeResult.MsgRct.Return))) | ||
result, err = cbg.ReadByteArray(bytes.NewReader(invokeResult.MsgRct.Return), uint64(len(invokeResult.MsgRct.Return))) |
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.
What is this change doing ? I don't see us returning an ExecutionRevertedError
anywhere.
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.
It was added just to add more context in the error:
return nil, xerrors.Errorf("failed to read msg recipient: %w", err)
ExecutionRevertedError
will be returned by the applyMessage
directly as it was already returning the execution reverted
error.
node/impl/full/eth.go
Outdated
@@ -1612,6 +1623,13 @@ func ethGasSearch( | |||
} | |||
|
|||
func (a *EthModule) EthCall(ctx context.Context, tx ethtypes.EthCall, blkParam ethtypes.EthBlockNumberOrHash) (ethtypes.EthBytes, error) { |
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.
Where are we returning an ExecutionRevertedError
in this function ?
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.
@aarshkshah1992
We are returning the ExecutionRevertedError
from applyMessage
function directly, so we don't to do it separately.
In EstimateGas
we are checking separately because of GasEstimateMessageGas
function also returns an error.
Reviewed. Thanks a lot. Also need to rebase this on master and fix the conflicts. |
Let's address the current batch of comments for which we have solid answers to @akaladarshi. For stuff that is still unclear/ambiguous -> we can then request a review from Stebalien 👍 |
@aarshkshah1992 So I have removed all the hardcoded error codes, and I am directly using the FVM returned error code. Now the only thing we need to answer is whether we should register the
|
@Stebalien Please can you take a look at just the one comment above i.e. #12553 (comment) ? |
@akaladarshi Please can you fix the CI ? Looks like it's all red. |
@aarshkshah1992 I was fixing a test, I'll check why the CI is failing |
Personally, I'd:
|
c82da3d
to
273cbcc
Compare
Which PR ? Your comment is missing a link. |
chain/types/ethtypes/errors.go
Outdated
} | ||
|
||
// NewExecutionRevertedWithDataError returns an ExecutionRevertedError with the given code and data. | ||
func NewExecutionRevertedWithDataError(code int, data string) *ExecutionRevertedError { |
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.
constructor name should match struct name with a New
in front
chain/types/ethtypes/errors.go
Outdated
"golang.org/x/xerrors" | ||
) | ||
|
||
var ErrExecutionReverted = xerrors.New("execution reverted") |
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.
You've made 2 error objects in this file (this one, and the struct
that conforms to the interface) and the only time you use this one is for its string in this file and once in the itest. I'd just either use this string, "execution reverted"
inline in the constructor, or make it a private const
here. It's OK to expect ErrorContains
"execution reverted"
in the test without linking it to an existing const, in fact that's desirable in a test so make sure what you think is a const is actually what you want it to be.
chain/types/ethtypes/errors.go
Outdated
if e.Message == "" { | ||
return fmt.Sprintf("json-rpc error %d", e.Code) | ||
} |
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.
do we expect to ever hit this?
maybe we should do away with Message
entirely and just always return this, make it ("execution reverted: %d", e.Code)
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.
and if we don't hit this code, I wonder what the point of Code
is, do we use that anywhere?
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.
Yeah so If you look at the ErrorCode()
function it returns the code, which is basically for not registered errors.
If you look at this comment above I think you will get the idea: #12553 (comment)
Whatever we decide based on it, we will either remove the code or keep it.
@@ -7,6 +7,7 @@ | |||
- Reduce size of embedded genesis CAR files by removing WASM actor blocks and compressing with zstd. This reduces the `lotus` binary size by approximately 10 MiB. ([filecoin-project/lotus#12439](https://github.com/filecoin-project/lotus/pull/12439)) | |||
- Add ChainSafe operated Calibration archival node to the bootstrap list ([filecoin-project/lotus#12517](https://github.com/filecoin-project/lotus/pull/12517)) | |||
- Fix hotloop in F3 pariticpation API ([filecoin-project/lotus#12575](https://github.com/filecoin-project/lotus/pull/12575)) | |||
- Return data with `eth_call` and `eth_estimateGas` APIs `execution reverted` error ([filecoin-project/lotus#12553](https://github.com/filecoin-project/lotus/pull/12553)) |
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.
- Return data with `eth_call` and `eth_estimateGas` APIs `execution reverted` error ([filecoin-project/lotus#12553](https://github.com/filecoin-project/lotus/pull/12553)) | |
- Return a `Data` field from RPC when `eth_call` and `eth_estimateGas` APIs encounter `execution reverted` errors ([filecoin-project/lotus#12553](https://github.com/filecoin-project/lotus/pull/12553)) |
api/api_errors.go
Outdated
func (e *ErrExecutionRevertedWithData) Error() string { return e.message } | ||
|
||
// ErrorData returns the error data. | ||
func (e *ErrExecutionRevertedWithData) ErrorData() interface{} { return e.data } | ||
|
||
// NewErrExecutionRevertedWithData creates a new ErrExecutionRevertedWithData. | ||
func NewErrExecutionRevertedWithData(data string) *ErrExecutionRevertedWithData { | ||
return &ErrExecutionRevertedWithData{ |
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.
func (e *ErrExecutionRevertedWithData) Error() string { return e.message } | |
// ErrorData returns the error data. | |
func (e *ErrExecutionRevertedWithData) ErrorData() interface{} { return e.data } | |
// NewErrExecutionRevertedWithData creates a new ErrExecutionRevertedWithData. | |
func NewErrExecutionRevertedWithData(data string) *ErrExecutionRevertedWithData { | |
return &ErrExecutionRevertedWithData{ | |
func (e ErrExecutionRevertedWithData) Error() string { return e.message } | |
// ErrorData returns the error data. | |
func (e ErrExecutionRevertedWithData) ErrorData() interface{} { return e.data } | |
// NewErrExecutionRevertedWithData creates a new ErrExecutionRevertedWithData. | |
func NewErrExecutionRevertedWithData(data string) ErrExecutionRevertedWithData { | |
return ErrExecutionRevertedWithData{ |
Does jsonrpc bork still on non-interface? Not a big deal but if we can avoid pointer receivers where they are not necessary.
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.
@rvagg They are necessary as of now because we are registering the errors as RPCErrors.Register(EExecutionRevertedWithData, new(*ErrExecutionRevertedWithData)) }
so go-jsonrpc
will expect error to be returned as a pointer type for c, ok := e.byType[reflect.TypeOf(err)];
.
I am trying to figure out a way, so we can get the code without worrying if the error is pointer type or not.
Related Issues
Closes #10311
Proposed Changes
Modified
EthCall
andEthEstimateGas
to handle errors and revert dataChecklist
Before you mark the PR ready for review, please make sure that: