From 2d3ef53c5304e429a04983210a417c1f4e0dafb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Fri, 5 Jun 2020 12:10:03 +0300 Subject: [PATCH] accounts, console, internal, rpc: minor error interface cleanups --- accounts/abi/bind/backends/simulated.go | 19 ++++++++------ accounts/abi/bind/backends/simulated_test.go | 6 ++--- console/bridge.go | 23 +++++++++-------- internal/ethapi/api.go | 19 ++++++++------ rpc/errors.go | 27 +++++++++++--------- rpc/handler.go | 2 +- rpc/json.go | 16 +++--------- rpc/types.go | 14 +++++----- 8 files changed, 63 insertions(+), 63 deletions(-) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 2cf7a3810f..73e3434aca 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -352,24 +352,27 @@ func newRevertError(result *core.ExecutionResult) *revertError { err = fmt.Errorf("execution reverted: %v", reason) } return &revertError{ - error: err, - errData: hexutil.Encode(result.Revert()), + error: err, + reason: hexutil.Encode(result.Revert()), } } +// revertError is an API error that encompassas an EVM revertal with JSON error +// code and a binary data blob. type revertError struct { error - errData interface{} // additional data + reason string // revert reason hex encoded } -func (e revertError) ErrorCode() int { - // revert errors are execution errors. - // See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal +// Core returns the JSON error code for a revertal. +// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal +func (e *revertError) Code() int { return 3 } -func (e revertError) ErrorData() interface{} { - return e.errData +// Data returns the hex encoded revert reason. +func (e *revertError) Data() interface{} { + return e.reason } // CallContract executes a contract call. diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go index 6dfd071b86..cc425a5f61 100644 --- a/accounts/abi/bind/backends/simulated_test.go +++ b/accounts/abi/bind/backends/simulated_test.go @@ -463,10 +463,10 @@ func TestSimulatedBackend_EstimateGas(t *testing.T) { t.Fatalf("Expect error, want %v, got %v", c.expectError, err) } if c.expectData != nil { - if rerr, ok := err.(*revertError); !ok { + if err, ok := err.(*revertError); !ok { t.Fatalf("Expect revert error, got %T", err) - } else if !reflect.DeepEqual(rerr.ErrorData(), c.expectData) { - t.Fatalf("Error data mismatch, want %v, got %v", c.expectData, rerr.ErrorData()) + } else if !reflect.DeepEqual(err.Data(), c.expectData) { + t.Fatalf("Error data mismatch, want %v, got %v", c.expectData, err.Data()) } } continue diff --git a/console/bridge.go b/console/bridge.go index c3cdcfaafc..e3002c79d8 100644 --- a/console/bridge.go +++ b/console/bridge.go @@ -413,9 +413,7 @@ func (b *bridge) Send(call jsre.Call) (goja.Value, error) { resp.Set("id", req.ID) var result json.RawMessage - err = b.client.Call(&result, req.Method, req.Params...) - switch err := err.(type) { - case nil: + if err = b.client.Call(&result, req.Method, req.Params...); err == nil { if result == nil { // Special case null because it is decoded as an empty // raw message for some reason. @@ -433,18 +431,21 @@ func (b *bridge) Send(call jsre.Call) (goja.Value, error) { resp.Set("result", resultVal) } } - case rpc.Error: - if dataErr, ok := err.(rpc.DataError); ok { - setError(resp, err.ErrorCode(), err.Error(), dataErr.ErrorData()) - } else { - setError(resp, err.ErrorCode(), err.Error(), nil) + } else { + var ( + code int = -32603 + data interface{} = nil + ) + if err, ok := err.(rpc.ErrorWithCode); ok { + code = err.Code() } - default: - setError(resp, -32603, err.Error(), nil) + if err, ok := err.(rpc.ErrorWithData); ok { + data = err.Data() + } + setError(resp, code, err.Error(), data) } resps = append(resps, resp) } - // Return the responses either to the callback (if supplied) // or directly as the return value. var result goja.Value diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 2933fd7a77..5b4bb600f3 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -871,24 +871,27 @@ func newRevertError(result *core.ExecutionResult) *revertError { err = fmt.Errorf("execution reverted: %v", reason) } return &revertError{ - error: err, - errData: hexutil.Encode(result.Revert()), + error: err, + reason: hexutil.Encode(result.Revert()), } } +// revertError is an API error that encompassas an EVM revertal with JSON error +// code and a binary data blob. type revertError struct { error - errData interface{} // additional data + reason string // revert reason hex encoded } -func (e revertError) ErrorCode() int { - // revert errors are execution errors. - // See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal +// Core returns the JSON error code for a revertal. +// See: https://github.com/ethereum/wiki/wiki/JSON-RPC-Error-Codes-Improvement-Proposal +func (e *revertError) Code() int { return 3 } -func (e revertError) ErrorData() interface{} { - return e.errData +// Data returns the hex encoded revert reason. +func (e *revertError) Data() interface{} { + return e.reason } // Call executes the given transaction on the state for the given block number. diff --git a/rpc/errors.go b/rpc/errors.go index c3aa826cc8..30b7186462 100644 --- a/rpc/errors.go +++ b/rpc/errors.go @@ -18,20 +18,27 @@ package rpc import "fmt" +var ( + _ ErrorWithCode = new(methodNotFoundError) + _ ErrorWithCode = new(subscriptionNotFoundError) + _ ErrorWithCode = new(parseError) + _ ErrorWithCode = new(invalidRequestError) + _ ErrorWithCode = new(invalidMessageError) + _ ErrorWithCode = new(invalidParamsError) +) + const defaultErrorCode = -32000 type methodNotFoundError struct{ method string } -func (e *methodNotFoundError) ErrorCode() int { return -32601 } - +func (e *methodNotFoundError) Code() int { return -32601 } func (e *methodNotFoundError) Error() string { return fmt.Sprintf("the method %s does not exist/is not available", e.method) } type subscriptionNotFoundError struct{ namespace, subscription string } -func (e *subscriptionNotFoundError) ErrorCode() int { return -32601 } - +func (e *subscriptionNotFoundError) Code() int { return -32601 } func (e *subscriptionNotFoundError) Error() string { return fmt.Sprintf("no %q subscription in %s namespace", e.subscription, e.namespace) } @@ -39,27 +46,23 @@ func (e *subscriptionNotFoundError) Error() string { // Invalid JSON was received by the server. type parseError struct{ message string } -func (e *parseError) ErrorCode() int { return -32700 } - +func (e *parseError) Code() int { return -32700 } func (e *parseError) Error() string { return e.message } // received message isn't a valid request type invalidRequestError struct{ message string } -func (e *invalidRequestError) ErrorCode() int { return -32600 } - +func (e *invalidRequestError) Code() int { return -32600 } func (e *invalidRequestError) Error() string { return e.message } // received message is invalid type invalidMessageError struct{ message string } -func (e *invalidMessageError) ErrorCode() int { return -32700 } - +func (e *invalidMessageError) Code() int { return -32700 } func (e *invalidMessageError) Error() string { return e.message } // unable to decode supplied params, or an invalid number of parameters type invalidParamsError struct{ message string } -func (e *invalidParamsError) ErrorCode() int { return -32602 } - +func (e *invalidParamsError) Code() int { return -32602 } func (e *invalidParamsError) Error() string { return e.message } diff --git a/rpc/handler.go b/rpc/handler.go index 23023eaca1..2999c44c6e 100644 --- a/rpc/handler.go +++ b/rpc/handler.go @@ -301,7 +301,7 @@ func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMess if resp.Error != nil { ctx = append(ctx, "err", resp.Error.Message) if resp.Error.Data != nil { - ctx = append(ctx, "errdata", resp.Error.Data) + ctx = append(ctx, "data", resp.Error.Data) } h.log.Warn("Served "+msg.Method, ctx...) } else { diff --git a/rpc/json.go b/rpc/json.go index 3be5d55f48..3f2026301b 100644 --- a/rpc/json.go +++ b/rpc/json.go @@ -111,13 +111,13 @@ func errorMessage(err error) *jsonrpcMessage { Code: defaultErrorCode, Message: err.Error(), }} - ec, ok := err.(Error) + ec, ok := err.(ErrorWithCode) if ok { - msg.Error.Code = ec.ErrorCode() + msg.Error.Code = ec.Code() } - de, ok := err.(DataError) + de, ok := err.(ErrorWithData) if ok { - msg.Error.Data = de.ErrorData() + msg.Error.Data = de.Data() } return msg } @@ -135,14 +135,6 @@ func (err *jsonError) Error() string { return err.Message } -func (err *jsonError) ErrorCode() int { - return err.Code -} - -func (err *jsonError) ErrorData() interface{} { - return err.Data -} - // Conn is a subset of the methods of net.Conn which are sufficient for ServerCodec. type Conn interface { io.ReadWriteCloser diff --git a/rpc/types.go b/rpc/types.go index bab1b3957b..23c59cd56c 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -35,16 +35,14 @@ type API struct { Public bool // indication if the methods must be considered safe for public use } -// Error wraps RPC errors, which contain an error code in addition to the message. -type Error interface { - Error() string // returns the message - ErrorCode() int // returns the code +// ErrorWithCode defines an error code in addition to the message. +type ErrorWithCode interface { + Code() int // returns the code } -// A DataError contains some data in addition to the error message. -type DataError interface { - Error() string // returns the message - ErrorData() interface{} // returns the error data +// ErrorWithData defines a data item in addition to the message. +type ErrorWithData interface { + Data() interface{} // returns the error data } // ServerCodec implements reading, parsing and writing RPC messages for the server side of