Commit a59bb053 authored by obscuren's avatar obscuren

merge

parents deee9cb1 28e19712
...@@ -34,7 +34,7 @@ type Filter struct { ...@@ -34,7 +34,7 @@ type Filter struct {
topics [][]common.Hash topics [][]common.Hash
BlockCallback func(*types.Block, state.Logs) BlockCallback func(*types.Block, state.Logs)
PendingCallback func(*types.Block, state.Logs) PendingCallback func(*types.Transaction)
LogsCallback func(state.Logs) LogsCallback func(state.Logs)
} }
...@@ -46,7 +46,7 @@ func NewFilter(eth Backend) *Filter { ...@@ -46,7 +46,7 @@ func NewFilter(eth Backend) *Filter {
// SetOptions copies the filter options to the filter it self. The reason for this "silly" copy // SetOptions copies the filter options to the filter it self. The reason for this "silly" copy
// is simply because named arguments in this case is extremely nice and readable. // is simply because named arguments in this case is extremely nice and readable.
func (self *Filter) SetOptions(options FilterOptions) { func (self *Filter) SetOptions(options *FilterOptions) {
self.earliest = options.Earliest self.earliest = options.Earliest
self.latest = options.Latest self.latest = options.Latest
self.skip = options.Skip self.skip = options.Skip
......
...@@ -48,7 +48,9 @@ func (self *FilterManager) InstallFilter(filter *core.Filter) (id int) { ...@@ -48,7 +48,9 @@ func (self *FilterManager) InstallFilter(filter *core.Filter) (id int) {
func (self *FilterManager) UninstallFilter(id int) { func (self *FilterManager) UninstallFilter(id int) {
self.filterMu.Lock() self.filterMu.Lock()
defer self.filterMu.Unlock() defer self.filterMu.Unlock()
delete(self.filters, id) if _, ok := self.filters[id]; ok {
delete(self.filters, id)
}
} }
// GetFilter retrieves a filter installed using InstallFilter. // GetFilter retrieves a filter installed using InstallFilter.
...@@ -62,8 +64,9 @@ func (self *FilterManager) GetFilter(id int) *core.Filter { ...@@ -62,8 +64,9 @@ func (self *FilterManager) GetFilter(id int) *core.Filter {
func (self *FilterManager) filterLoop() { func (self *FilterManager) filterLoop() {
// Subscribe to events // Subscribe to events
events := self.eventMux.Subscribe( events := self.eventMux.Subscribe(
core.PendingBlockEvent{}, //core.PendingBlockEvent{},
core.ChainEvent{}, core.ChainEvent{},
core.TxPreEvent{},
state.Logs(nil)) state.Logs(nil))
out: out:
...@@ -82,11 +85,11 @@ out: ...@@ -82,11 +85,11 @@ out:
} }
self.filterMu.RUnlock() self.filterMu.RUnlock()
case core.PendingBlockEvent: case core.TxPreEvent:
self.filterMu.RLock() self.filterMu.RLock()
for _, filter := range self.filters { for _, filter := range self.filters {
if filter.PendingCallback != nil { if filter.PendingCallback != nil {
filter.PendingCallback(event.Block, event.Logs) filter.PendingCallback(event.Tx)
} }
} }
self.filterMu.RUnlock() self.filterMu.RUnlock()
......
This diff is collapsed.
...@@ -2,9 +2,9 @@ package rpc ...@@ -2,9 +2,9 @@ package rpc
import ( import (
"encoding/json" "encoding/json"
"sync" // "sync"
"testing" "testing"
"time" // "time"
) )
func TestWeb3Sha3(t *testing.T) { func TestWeb3Sha3(t *testing.T) {
...@@ -24,33 +24,33 @@ func TestWeb3Sha3(t *testing.T) { ...@@ -24,33 +24,33 @@ func TestWeb3Sha3(t *testing.T) {
} }
} }
func TestFilterClose(t *testing.T) { // func TestFilterClose(t *testing.T) {
t.Skip() // t.Skip()
api := &EthereumApi{ // api := &EthereumApi{
logs: make(map[int]*logFilter), // logs: make(map[int]*logFilter),
messages: make(map[int]*whisperFilter), // messages: make(map[int]*whisperFilter),
quit: make(chan struct{}), // quit: make(chan struct{}),
} // }
filterTickerTime = 1 // filterTickerTime = 1
api.logs[0] = &logFilter{} // api.logs[0] = &logFilter{}
api.messages[0] = &whisperFilter{} // api.messages[0] = &whisperFilter{}
var wg sync.WaitGroup // var wg sync.WaitGroup
wg.Add(1) // wg.Add(1)
go api.start() // go api.start()
go func() { // go func() {
select { // select {
case <-time.After(500 * time.Millisecond): // case <-time.After(500 * time.Millisecond):
api.stop() // api.stop()
wg.Done() // wg.Done()
} // }
}() // }()
wg.Wait() // wg.Wait()
if len(api.logs) != 0 { // if len(api.logs) != 0 {
t.Error("expected logs to be empty") // t.Error("expected logs to be empty")
} // }
if len(api.messages) != 0 { // if len(api.messages) != 0 {
t.Error("expected messages to be empty") // t.Error("expected messages to be empty")
} // }
} // }
...@@ -35,8 +35,8 @@ func blockAge(raw interface{}, number *int64) (err error) { ...@@ -35,8 +35,8 @@ func blockAge(raw interface{}, number *int64) (err error) {
} }
type GetBlockByHashArgs struct { type GetBlockByHashArgs struct {
BlockHash string BlockHash string
Transactions bool IncludeTxs bool
} }
func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) { func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
...@@ -57,15 +57,15 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) { ...@@ -57,15 +57,15 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
args.BlockHash = argstr args.BlockHash = argstr
if len(obj) > 1 { if len(obj) > 1 {
args.Transactions = obj[1].(bool) args.IncludeTxs = obj[1].(bool)
} }
return nil return nil
} }
type GetBlockByNumberArgs struct { type GetBlockByNumberArgs struct {
BlockNumber int64 BlockNumber int64
Transactions bool IncludeTxs bool
} }
func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) { func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
...@@ -86,7 +86,7 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) { ...@@ -86,7 +86,7 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
} }
if len(obj) > 1 { if len(obj) > 1 {
args.Transactions = obj[1].(bool) args.IncludeTxs = obj[1].(bool)
} }
return nil return nil
...@@ -433,7 +433,7 @@ func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) { ...@@ -433,7 +433,7 @@ func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
return nil return nil
} }
type FilterOptions struct { type BlockFilterArgs struct {
Earliest int64 Earliest int64
Latest int64 Latest int64
Address interface{} Address interface{}
...@@ -442,7 +442,7 @@ type FilterOptions struct { ...@@ -442,7 +442,7 @@ type FilterOptions struct {
Max int Max int
} }
func (args *FilterOptions) UnmarshalJSON(b []byte) (err error) { func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
var obj []struct { var obj []struct {
FromBlock interface{} `json:"fromBlock"` FromBlock interface{} `json:"fromBlock"`
ToBlock interface{} `json:"toBlock"` ToBlock interface{} `json:"toBlock"`
...@@ -609,6 +609,16 @@ func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) { ...@@ -609,6 +609,16 @@ func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
return nil return nil
} }
func (args *FilterStringArgs) requirements() error {
switch args.Word {
case "latest", "pending":
break
default:
return NewValidationError("Word", "Must be `latest` or `pending`")
}
return nil
}
type FilterIdArgs struct { type FilterIdArgs struct {
Id int Id int
} }
......
...@@ -82,7 +82,7 @@ func TestGetBlockByHashArgs(t *testing.T) { ...@@ -82,7 +82,7 @@ func TestGetBlockByHashArgs(t *testing.T) {
input := `["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", true]` input := `["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", true]`
expected := new(GetBlockByHashArgs) expected := new(GetBlockByHashArgs)
expected.BlockHash = "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331" expected.BlockHash = "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
expected.Transactions = true expected.IncludeTxs = true
args := new(GetBlockByHashArgs) args := new(GetBlockByHashArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil { if err := json.Unmarshal([]byte(input), &args); err != nil {
...@@ -93,8 +93,8 @@ func TestGetBlockByHashArgs(t *testing.T) { ...@@ -93,8 +93,8 @@ func TestGetBlockByHashArgs(t *testing.T) {
t.Errorf("BlockHash should be %v but is %v", expected.BlockHash, args.BlockHash) t.Errorf("BlockHash should be %v but is %v", expected.BlockHash, args.BlockHash)
} }
if args.Transactions != expected.Transactions { if args.IncludeTxs != expected.IncludeTxs {
t.Errorf("Transactions should be %v but is %v", expected.Transactions, args.Transactions) t.Errorf("IncludeTxs should be %v but is %v", expected.IncludeTxs, args.IncludeTxs)
} }
} }
...@@ -112,7 +112,7 @@ func TestGetBlockByNumberArgs(t *testing.T) { ...@@ -112,7 +112,7 @@ func TestGetBlockByNumberArgs(t *testing.T) {
input := `["0x1b4", false]` input := `["0x1b4", false]`
expected := new(GetBlockByNumberArgs) expected := new(GetBlockByNumberArgs)
expected.BlockNumber = 436 expected.BlockNumber = 436
expected.Transactions = false expected.IncludeTxs = false
args := new(GetBlockByNumberArgs) args := new(GetBlockByNumberArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil { if err := json.Unmarshal([]byte(input), &args); err != nil {
...@@ -123,8 +123,8 @@ func TestGetBlockByNumberArgs(t *testing.T) { ...@@ -123,8 +123,8 @@ func TestGetBlockByNumberArgs(t *testing.T) {
t.Errorf("BlockHash should be %v but is %v", expected.BlockNumber, args.BlockNumber) t.Errorf("BlockHash should be %v but is %v", expected.BlockNumber, args.BlockNumber)
} }
if args.Transactions != expected.Transactions { if args.IncludeTxs != expected.IncludeTxs {
t.Errorf("Transactions should be %v but is %v", expected.Transactions, args.Transactions) t.Errorf("IncludeTxs should be %v but is %v", expected.IncludeTxs, args.IncludeTxs)
} }
} }
...@@ -388,7 +388,7 @@ func TestGetDataEmptyArgs(t *testing.T) { ...@@ -388,7 +388,7 @@ func TestGetDataEmptyArgs(t *testing.T) {
} }
} }
func TestFilterOptions(t *testing.T) { func TestBlockFilterArgs(t *testing.T) {
input := `[{ input := `[{
"fromBlock": "0x1", "fromBlock": "0x1",
"toBlock": "0x2", "toBlock": "0x2",
...@@ -396,7 +396,7 @@ func TestFilterOptions(t *testing.T) { ...@@ -396,7 +396,7 @@ func TestFilterOptions(t *testing.T) {
"offset": "0x0", "offset": "0x0",
"address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8", "address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
"topics": ["0x12341234"]}]` "topics": ["0x12341234"]}]`
expected := new(FilterOptions) expected := new(BlockFilterArgs)
expected.Earliest = 1 expected.Earliest = 1
expected.Latest = 2 expected.Latest = 2
expected.Max = 3 expected.Max = 3
...@@ -404,7 +404,7 @@ func TestFilterOptions(t *testing.T) { ...@@ -404,7 +404,7 @@ func TestFilterOptions(t *testing.T) {
expected.Address = "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8" expected.Address = "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"
// expected.Topics = []string{"0x12341234"} // expected.Topics = []string{"0x12341234"}
args := new(FilterOptions) args := new(BlockFilterArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil { if err := json.Unmarshal([]byte(input), &args); err != nil {
t.Error(err) t.Error(err)
} }
...@@ -434,16 +434,16 @@ func TestFilterOptions(t *testing.T) { ...@@ -434,16 +434,16 @@ func TestFilterOptions(t *testing.T) {
// } // }
} }
func TestFilterOptionsWords(t *testing.T) { func TestBlockFilterArgsWords(t *testing.T) {
input := `[{ input := `[{
"fromBlock": "latest", "fromBlock": "latest",
"toBlock": "pending" "toBlock": "pending"
}]` }]`
expected := new(FilterOptions) expected := new(BlockFilterArgs)
expected.Earliest = 0 expected.Earliest = 0
expected.Latest = -1 expected.Latest = -1
args := new(FilterOptions) args := new(BlockFilterArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil { if err := json.Unmarshal([]byte(input), &args); err != nil {
t.Error(err) t.Error(err)
} }
...@@ -457,13 +457,13 @@ func TestFilterOptionsWords(t *testing.T) { ...@@ -457,13 +457,13 @@ func TestFilterOptionsWords(t *testing.T) {
} }
} }
func TestFilterOptionsNums(t *testing.T) { func TestBlockFilterArgsNums(t *testing.T) {
input := `[{ input := `[{
"fromBlock": 2, "fromBlock": 2,
"toBlock": 3 "toBlock": 3
}]` }]`
args := new(FilterOptions) args := new(BlockFilterArgs)
err := json.Unmarshal([]byte(input), &args) err := json.Unmarshal([]byte(input), &args)
switch err.(type) { switch err.(type) {
case *DecodeParamError: case *DecodeParamError:
...@@ -474,10 +474,10 @@ func TestFilterOptionsNums(t *testing.T) { ...@@ -474,10 +474,10 @@ func TestFilterOptionsNums(t *testing.T) {
} }
func TestFilterOptionsEmptyArgs(t *testing.T) { func TestBlockFilterArgsEmptyArgs(t *testing.T) {
input := `[]` input := `[]`
args := new(FilterOptions) args := new(BlockFilterArgs)
err := json.Unmarshal([]byte(input), &args) err := json.Unmarshal([]byte(input), &args)
if err == nil { if err == nil {
t.Error("Expected error but didn't get one") t.Error("Expected error but didn't get one")
......
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
"github.com/ethereum/go-ethereum/xeth" "github.com/ethereum/go-ethereum/xeth"
) )
var rpchttplogger = logger.NewLogger("RPC-HTTP") var rpclogger = logger.NewLogger("RPC")
const ( const (
jsonrpcver = "2.0" jsonrpcver = "2.0"
...@@ -28,7 +28,7 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler { ...@@ -28,7 +28,7 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler {
// Limit request size to resist DoS // Limit request size to resist DoS
if req.ContentLength > maxSizeReqLength { if req.ContentLength > maxSizeReqLength {
jsonerr := &RpcErrorObject{-32700, "Request too large"} 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 return
} }
...@@ -37,14 +37,14 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler { ...@@ -37,14 +37,14 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler {
body, err := ioutil.ReadAll(req.Body) body, err := ioutil.ReadAll(req.Body)
if err != nil { if err != nil {
jsonerr := &RpcErrorObject{-32700, "Could not read request body"} 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 // Try to parse the request as a single
var reqSingle RpcRequest var reqSingle RpcRequest
if err := json.Unmarshal(body, &reqSingle); err == nil { if err := json.Unmarshal(body, &reqSingle); err == nil {
response := RpcResponse(api, &reqSingle) response := RpcResponse(api, &reqSingle)
Send(w, &response) send(w, &response)
return return
} }
...@@ -57,13 +57,13 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler { ...@@ -57,13 +57,13 @@ func JSONRPC(pipe *xeth.XEth, dataDir string) http.Handler {
response := RpcResponse(api, &request) response := RpcResponse(api, &request)
resBatch[i] = response resBatch[i] = response
} }
Send(w, resBatch) send(w, resBatch)
return return
} }
// Not a batch or single request, error // Not a batch or single request, error
jsonerr := &RpcErrorObject{-32600, "Could not decode request"} 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{} { ...@@ -84,11 +84,11 @@ func RpcResponse(api *EthereumApi, request *RpcRequest) *interface{} {
response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr} 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 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 var payload []byte
payload, err = json.MarshalIndent(v, "", "\t") payload, err = json.MarshalIndent(v, "", "\t")
if err != nil { if err != nil {
......
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())
}
}
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/state"
) )
type BlockRes struct { type BlockRes struct {
...@@ -215,3 +216,28 @@ type FilterWhisperRes struct { ...@@ -215,3 +216,28 @@ type FilterWhisperRes struct {
Payload string `json:"payload"` Payload string `json:"payload"`
WorkProved string `json:"workProved"` 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 = log.Address().Hex()
l.Data = common.ToHex(log.Data())
l.Number = log.Number()
for j, topic := range log.Topics() {
l.Topic[j] = topic.Hex()
}
ls[i] = l
}
return
}
/*
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 <http://www.gnu.org/licenses/>.
*/
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 = log.Address().Hex()
l.Data = common.ToHex(log.Data())
l.Number = log.Number()
for j, topic := range log.Topics() {
l.Topic[j] = topic.Hex()
}
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
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment