Skip to content
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 mining reverted txs #1712

Merged
merged 11 commits into from
Mar 2, 2023
Prev Previous commit
Next Next commit
fix reverted errors when calling eth_call
  • Loading branch information
tclemos committed Mar 1, 2023
commit c3ac8662b7e8675d4a932506b4d5919d252814a7
14 changes: 10 additions & 4 deletions jsonrpc/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ type Response struct {

// ErrorObject is a jsonrpc error
type ErrorObject struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
Code int `json:"code"`
Message string `json:"message"`
Data *argBytes `json:"data,omitempty"`
}

// NewResponse returns Success/Error response object
Expand All @@ -62,7 +62,13 @@ func NewResponse(req Request, reply []byte, err rpcError) Response {

var errorObj *ErrorObject
if err != nil {
errorObj = &ErrorObject{err.ErrorCode(), err.Error(), nil}
errorObj = &ErrorObject{
Code: err.ErrorCode(),
Message: err.Error(),
}
if err.ErrorData() != nil {
errorObj.Data = argBytesPtr(*err.ErrorData())
}
}

return Response{
Expand Down
6 changes: 4 additions & 2 deletions jsonrpc/endpoints_eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ func (e *EthEndpoints) Call(arg *txnArgs, number *BlockNumber) (interface{}, rpc
blockNumberToProcessTx = &blockNumber
}

result := e.state.ProcessUnsignedTransaction(ctx, tx, sender, blockNumberToProcessTx, true, dbTx)
result := e.state.ProcessUnsignedTransaction(ctx, tx, sender, blockNumberToProcessTx, false, dbTx)
if result.Failed() {
return rpcErrorResponse(defaultErrorCode, result.Err.Error(), nil)
data := make([]byte, len(result.ReturnValue))
copy(data, result.ReturnValue)
return rpcErrorResponseWithData(revertedErrorCode, result.Err.Error(), &data, nil)
}

return argBytesPtr(result.ReturnValue), nil
Expand Down
14 changes: 13 additions & 1 deletion jsonrpc/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "fmt"

const (
defaultErrorCode = -32000
revertedErrorCode = 3
invalidRequestErrorCode = -32600
notFoundErrorCode = -32601
invalidParamsErrorCode = -32602
Expand All @@ -13,22 +14,28 @@ const (
type rpcError interface {
Error() string
ErrorCode() int
ErrorData() *[]byte
}

// RPCError represents an RPC error.
type RPCError struct {
err string
code int
data *[]byte
}

func newRPCError(code int, err string, args ...interface{}) *RPCError {
return newRPCErrorWithData(code, err, nil, args)
}

func newRPCErrorWithData(code int, err string, data *[]byte, args ...interface{}) *RPCError {
var errMessage string
if len(args) > 0 {
errMessage = fmt.Sprintf(err, args...)
} else {
errMessage = err
}
return &RPCError{code: code, err: errMessage}
return &RPCError{code: code, err: errMessage, data: data}
}

// Error returns the error message.
Expand All @@ -40,3 +47,8 @@ func (e *RPCError) Error() string {
func (e *RPCError) ErrorCode() int {
return e.code
}

// ErrorData returns the error data.
func (e *RPCError) ErrorData() *[]byte {
return e.data
}
12 changes: 8 additions & 4 deletions jsonrpc/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,15 @@ func handleError(w http.ResponseWriter, err error) {
}
}

func rpcErrorResponse(code int, errorMessage string, err error) (interface{}, rpcError) {
func rpcErrorResponse(code int, message string, err error) (interface{}, rpcError) {
return rpcErrorResponseWithData(code, message, nil, err)
}

func rpcErrorResponseWithData(code int, message string, data *[]byte, err error) (interface{}, rpcError) {
if err != nil {
log.Errorf("%v:%v", errorMessage, err.Error())
log.Errorf("%v:%v", message, err.Error())
} else {
log.Error(errorMessage)
log.Error(message)
}
return nil, newRPCError(code, errorMessage)
return nil, newRPCErrorWithData(code, message, data)
}
Binary file added test/e2e/__debug_bin
Binary file not shown.
46 changes: 46 additions & 0 deletions test/e2e/jsonrpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ import (
"github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Storage"
"github.com/0xPolygonHermez/zkevm-node/test/operations"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
"github.com/gorilla/websocket"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -847,6 +849,28 @@ func Test_RevertOnConstructorTransaction(t *testing.T) {
require.NoError(t, err)

assert.Equal(t, receipt.Status, types.ReceiptStatusFailed)

msg := ethereum.CallMsg{
From: auth.From,
To: scTx.To(),
Gas: scTx.Gas(),

Value: scTx.Value(),
Data: scTx.Data(),
}
result, err := client.CallContract(ctx, msg, receipt.BlockNumber)
require.NotNil(t, err)
require.Nil(t, result)
rpcErr := err.(rpc.Error)
assert.Equal(t, 3, rpcErr.ErrorCode())
assert.Equal(t, "execution reverted: Today is not juernes", rpcErr.Error())

dataErr := err.(rpc.DataError)
data := dataErr.ErrorData().(string)
decodedData := hex.DecodeBig(data)
unpackedData, err := abi.UnpackRevert(decodedData.Bytes())
require.NoError(t, err)
assert.Equal(t, "Today is not juernes", unpackedData)
}
}

Expand Down Expand Up @@ -886,5 +910,27 @@ func Test_RevertOnSCCallTransaction(t *testing.T) {
require.NoError(t, err)

assert.Equal(t, receipt.Status, types.ReceiptStatusFailed)

msg := ethereum.CallMsg{
From: auth.From,
To: tx.To(),
Gas: tx.Gas(),

Value: tx.Value(),
Data: tx.Data(),
}
result, err := client.CallContract(ctx, msg, receipt.BlockNumber)
require.NotNil(t, err)
require.Nil(t, result)
rpcErr := err.(rpc.Error)
assert.Equal(t, 3, rpcErr.ErrorCode())
assert.Equal(t, "execution reverted: Today is not juernes", rpcErr.Error())

dataErr := err.(rpc.DataError)
data := dataErr.ErrorData().(string)
decodedData := hex.DecodeBig(data)
unpackedData, err := abi.UnpackRevert(decodedData.Bytes())
require.NoError(t, err)
assert.Equal(t, "Today is not juernes", unpackedData)
}
}