diff --git a/rpc/api.go b/rpc/api.go index fcf2ac9dc2..06ed73885c 100644 --- a/rpc/api.go +++ b/rpc/api.go @@ -214,7 +214,7 @@ func (self *EthereumApi) FilterChanged(id int, reply *interface{}) error { defer self.logMut.Unlock() if self.logs[id] != nil { - *reply = toLogs(self.logs[id].get()) + *reply = NewLogsRes(self.logs[id].get()) } return nil @@ -226,7 +226,7 @@ func (self *EthereumApi) Logs(id int, reply *interface{}) error { filter := self.filterManager.GetFilter(id) if filter != nil { - *reply = toLogs(filter.Find()) + *reply = NewLogsRes(filter.Find()) } return nil @@ -236,7 +236,7 @@ func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error filter := core.NewFilter(self.xeth().Backend()) filter.SetOptions(toFilterOptions(args)) - *reply = toLogs(filter.Find()) + *reply = NewLogsRes(filter.Find()) return nil } @@ -873,3 +873,36 @@ func toFilterOptions(options *FilterOptions) core.FilterOptions { return opts } + +type whisperFilter struct { + messages []xeth.WhisperMessage + timeout time.Time + id int +} + +func (w *whisperFilter) add(msgs ...xeth.WhisperMessage) { + w.messages = append(w.messages, msgs...) +} +func (w *whisperFilter) get() []xeth.WhisperMessage { + w.timeout = time.Now() + tmp := w.messages + w.messages = nil + return tmp +} + +type logFilter struct { + logs state.Logs + timeout time.Time + id int +} + +func (l *logFilter) add(logs ...state.Log) { + l.logs = append(l.logs, logs...) +} + +func (l *logFilter) get() state.Logs { + l.timeout = time.Now() + tmp := l.logs + l.logs = nil + return tmp +} diff --git a/rpc/http.go b/rpc/http.go index 5f2445e6c2..3dfb677815 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/xeth" ) -var rpchttplogger = logger.NewLogger("RPC-HTTP") +var rpclogger = logger.NewLogger("RPC") const ( jsonrpcver = "2.0" @@ -28,7 +28,7 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler { // Limit request size to resist DoS if req.ContentLength > maxSizeReqLength { jsonerr := &RpcErrorObject{-32700, "Request too large"} - Send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr}) + send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr}) return } @@ -37,14 +37,14 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler { body, err := ioutil.ReadAll(req.Body) if err != nil { jsonerr := &RpcErrorObject{-32700, "Could not read request body"} - Send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr}) + send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr}) } // Try to parse the request as a single var reqSingle RpcRequest if err := json.Unmarshal(body, &reqSingle); err == nil { response := RpcResponse(api, &reqSingle) - Send(w, &response) + send(w, &response) return } @@ -57,13 +57,13 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler { response := RpcResponse(api, &request) resBatch[i] = response } - Send(w, resBatch) + send(w, resBatch) return } // Not a batch or single request, error jsonerr := &RpcErrorObject{-32600, "Could not decode request"} - Send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr}) + send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr}) }) } @@ -84,11 +84,11 @@ func RpcResponse(api *EthereumApi, request *RpcRequest) *interface{} { response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr} } - rpchttplogger.DebugDetailf("Generated response: %T %s", response, response) + rpclogger.DebugDetailf("Generated response: %T %s", response, response) return &response } -func Send(writer io.Writer, v interface{}) (n int, err error) { +func send(writer io.Writer, v interface{}) (n int, err error) { var payload []byte payload, err = json.MarshalIndent(v, "", "\t") if err != nil { diff --git a/rpc/messages_test.go b/rpc/messages_test.go new file mode 100644 index 0000000000..5274c91e42 --- /dev/null +++ b/rpc/messages_test.go @@ -0,0 +1,41 @@ +package rpc + +import ( + "testing" +) + +func TestInsufficientParamsError(t *testing.T) { + err := NewInsufficientParamsError(0, 1) + expected := "insufficient params, want 1 have 0" + + if err.Error() != expected { + t.Error(err.Error()) + } +} + +func TestNotImplementedError(t *testing.T) { + err := NewNotImplementedError("foo") + expected := "foo method not implemented" + + if err.Error() != expected { + t.Error(err.Error()) + } +} + +func TestDecodeParamError(t *testing.T) { + err := NewDecodeParamError("foo") + expected := "could not decode, foo" + + if err.Error() != expected { + t.Error(err.Error()) + } +} + +func TestValidationError(t *testing.T) { + err := NewValidationError("foo", "should be `bar`") + expected := "foo not valid, should be `bar`" + + if err.Error() != expected { + t.Error(err.Error()) + } +} diff --git a/rpc/responses.go b/rpc/responses.go index eec483fb7b..a3613f3809 100644 --- a/rpc/responses.go +++ b/rpc/responses.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/state" ) type BlockRes struct { @@ -211,3 +212,28 @@ type FilterWhisperRes struct { Payload string `json:"payload"` WorkProved string `json:"workProved"` } + +type LogRes struct { + Address string `json:"address"` + Topic []string `json:"topic"` + Data string `json:"data"` + Number uint64 `json:"number"` +} + +func NewLogsRes(logs state.Logs) (ls []LogRes) { + ls = make([]LogRes, len(logs)) + + for i, log := range logs { + var l LogRes + l.Topic = make([]string, len(log.Topics())) + l.Address = common.ToHex(log.Address()) + l.Data = common.ToHex(log.Data()) + l.Number = log.Number() + for j, topic := range log.Topics() { + l.Topic[j] = common.ToHex(topic) + } + ls[i] = l + } + + return +} diff --git a/rpc/util.go b/rpc/util.go deleted file mode 100644 index 0798ae1d22..0000000000 --- a/rpc/util.go +++ /dev/null @@ -1,86 +0,0 @@ -/* - This file is part of go-ethereum - - go-ethereum is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - go-ethereum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with go-ethereum. If not, see . -*/ -package rpc - -import ( - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/logger" - "github.com/ethereum/go-ethereum/state" - "github.com/ethereum/go-ethereum/xeth" -) - -var rpclogger = logger.NewLogger("RPC") - -type Log struct { - Address string `json:"address"` - Topic []string `json:"topic"` - Data string `json:"data"` - Number uint64 `json:"number"` -} - -func toLogs(logs state.Logs) (ls []Log) { - ls = make([]Log, len(logs)) - - for i, log := range logs { - var l Log - l.Topic = make([]string, len(log.Topics())) - l.Address = common.ToHex(log.Address()) - l.Data = common.ToHex(log.Data()) - l.Number = log.Number() - for j, topic := range log.Topics() { - l.Topic[j] = common.ToHex(topic) - } - ls[i] = l - } - - return -} - -type whisperFilter struct { - messages []xeth.WhisperMessage - timeout time.Time - id int -} - -func (w *whisperFilter) add(msgs ...xeth.WhisperMessage) { - w.messages = append(w.messages, msgs...) -} -func (w *whisperFilter) get() []xeth.WhisperMessage { - w.timeout = time.Now() - tmp := w.messages - w.messages = nil - return tmp -} - -type logFilter struct { - logs state.Logs - timeout time.Time - id int -} - -func (l *logFilter) add(logs ...state.Log) { - l.logs = append(l.logs, logs...) -} - -func (l *logFilter) get() state.Logs { - l.timeout = time.Now() - tmp := l.logs - l.logs = nil - return tmp -}