aboutsummaryrefslogtreecommitdiffstats
path: root/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'rpc')
-rw-r--r--rpc/api.go771
-rw-r--r--rpc/api_test.go64
-rw-r--r--rpc/args.go26
-rw-r--r--rpc/args_test.go32
4 files changed, 243 insertions, 650 deletions
diff --git a/rpc/api.go b/rpc/api.go
index 06ed73885..548bace5c 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -2,494 +2,49 @@ package rpc
import (
"encoding/json"
- "fmt"
"math/big"
"path"
- "strings"
"sync"
- "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/event"
- "github.com/ethereum/go-ethereum/event/filter"
- "github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/xeth"
)
-var (
- defaultGasPrice = big.NewInt(150000000000)
- defaultGas = big.NewInt(500000)
- filterTickerTime = 5 * time.Minute
-)
-
type EthereumApi struct {
eth *xeth.XEth
xethMu sync.RWMutex
- mux *event.TypeMux
-
- quit chan struct{}
- filterManager *filter.FilterManager
-
- logMut sync.RWMutex
- logs map[int]*logFilter
-
- messagesMut sync.RWMutex
- messages map[int]*whisperFilter
- // Register keeps a list of accounts and transaction data
- regmut sync.Mutex
- register map[string][]*NewTxArgs
-
- db common.Database
+ db common.Database
}
func NewEthereumApi(eth *xeth.XEth, dataDir string) *EthereumApi {
+ // What about when dataDir is empty?
db, _ := ethdb.NewLDBDatabase(path.Join(dataDir, "dapps"))
api := &EthereumApi{
- eth: eth,
- mux: eth.Backend().EventMux(),
- quit: make(chan struct{}),
- filterManager: filter.NewFilterManager(eth.Backend().EventMux()),
- logs: make(map[int]*logFilter),
- messages: make(map[int]*whisperFilter),
- db: db,
+ eth: eth,
+ db: db,
}
- go api.filterManager.Start()
- go api.start()
return api
}
-func (self *EthereumApi) xethWithStateNum(num int64) *xeth.XEth {
- chain := self.xeth().Backend().ChainManager()
- var block *types.Block
-
- if num < 0 {
- num = chain.CurrentBlock().Number().Int64() + num + 1
- }
- block = chain.GetBlockByNumber(uint64(num))
-
- var st *state.StateDB
- if block != nil {
- st = state.New(block.Root(), self.xeth().Backend().StateDb())
- } else {
- st = chain.State()
- }
- return self.xeth().WithState(st)
-}
-
-func (self *EthereumApi) getStateWithNum(num int64) *xeth.State {
- return self.xethWithStateNum(num).State()
-}
-
-func (self *EthereumApi) start() {
- timer := time.NewTicker(2 * time.Second)
-done:
- for {
- select {
- case <-timer.C:
- self.logMut.Lock()
- self.messagesMut.Lock()
- for id, filter := range self.logs {
- if time.Since(filter.timeout) > filterTickerTime {
- self.filterManager.UninstallFilter(id)
- delete(self.logs, id)
- }
- }
-
- for id, filter := range self.messages {
- if time.Since(filter.timeout) > filterTickerTime {
- self.xeth().Whisper().Unwatch(id)
- delete(self.messages, id)
- }
- }
- self.messagesMut.Unlock()
- self.logMut.Unlock()
- case <-self.quit:
- break done
- }
- }
-}
-
-func (self *EthereumApi) stop() {
- close(self.quit)
-}
-
-// func (self *EthereumApi) Register(args string, reply *interface{}) error {
-// self.regmut.Lock()
-// defer self.regmut.Unlock()
-
-// if _, ok := self.register[args]; ok {
-// self.register[args] = nil // register with empty
-// }
-// return nil
-// }
-
-// func (self *EthereumApi) Unregister(args string, reply *interface{}) error {
-// self.regmut.Lock()
-// defer self.regmut.Unlock()
-
-// delete(self.register, args)
-
-// return nil
-// }
-
-// func (self *EthereumApi) WatchTx(args string, reply *interface{}) error {
-// self.regmut.Lock()
-// defer self.regmut.Unlock()
-
-// txs := self.register[args]
-// self.register[args] = nil
-
-// *reply = txs
-// return nil
-// }
-
-func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) error {
- var id int
- filter := core.NewFilter(self.xeth().Backend())
- filter.SetOptions(toFilterOptions(args))
- filter.LogsCallback = func(logs state.Logs) {
- self.logMut.Lock()
- defer self.logMut.Unlock()
-
- self.logs[id].add(logs...)
- }
- id = self.filterManager.InstallFilter(filter)
- self.logs[id] = &logFilter{timeout: time.Now()}
-
- *reply = common.ToHex(big.NewInt(int64(id)).Bytes())
-
- return nil
-}
-
-func (self *EthereumApi) UninstallFilter(id int, reply *interface{}) error {
- if _, ok := self.logs[id]; ok {
- delete(self.logs, id)
- }
-
- self.filterManager.UninstallFilter(id)
- *reply = true
- return nil
-}
-
-func (self *EthereumApi) NewFilterString(args *FilterStringArgs, reply *interface{}) error {
- var id int
- filter := core.NewFilter(self.xeth().Backend())
-
- switch args.Word {
- case "pending":
- filter.PendingCallback = func(tx *types.Transaction) {
- self.logMut.Lock()
- defer self.logMut.Unlock()
-
- self.logs[id].add(&state.StateLog{})
- }
- case "latest":
- filter.BlockCallback = func(block *types.Block, logs state.Logs) {
- self.logMut.Lock()
- defer self.logMut.Unlock()
-
- for _, log := range logs {
- self.logs[id].add(log)
- }
- self.logs[id].add(&state.StateLog{})
- }
- default:
- return NewValidationError("Word", "Must be `latest` or `pending`")
- }
-
- id = self.filterManager.InstallFilter(filter)
- self.logs[id] = &logFilter{timeout: time.Now()}
- *reply = common.ToHex(big.NewInt(int64(id)).Bytes())
-
- return nil
-}
-
-func (self *EthereumApi) FilterChanged(id int, reply *interface{}) error {
- self.logMut.Lock()
- defer self.logMut.Unlock()
-
- if self.logs[id] != nil {
- *reply = NewLogsRes(self.logs[id].get())
- }
-
- return nil
-}
-
-func (self *EthereumApi) Logs(id int, reply *interface{}) error {
- self.logMut.Lock()
- defer self.logMut.Unlock()
-
- filter := self.filterManager.GetFilter(id)
- if filter != nil {
- *reply = NewLogsRes(filter.Find())
- }
-
- return nil
-}
-
-func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error {
- filter := core.NewFilter(self.xeth().Backend())
- filter.SetOptions(toFilterOptions(args))
-
- *reply = NewLogsRes(filter.Find())
-
- return nil
-}
-
-func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) (err error) {
- // TODO if no_private_key then
- //if _, exists := p.register[args.From]; exists {
- // p.register[args.From] = append(p.register[args.From], args)
- //} else {
- /*
- account := accounts.Get(common.FromHex(args.From))
- if account != nil {
- if account.Unlocked() {
- if !unlockAccount(account) {
- return
- }
- }
-
- result, _ := account.Transact(common.FromHex(args.To), common.FromHex(args.Value), common.FromHex(args.Gas), common.FromHex(args.GasPrice), common.FromHex(args.Data))
- if len(result) > 0 {
- *reply = common.ToHex(result)
- }
- } else if _, exists := p.register[args.From]; exists {
- p.register[ags.From] = append(p.register[args.From], args)
- }
- */
-
- if err := args.requirements(); err != nil {
- return err
- }
-
- // TODO: align default values to have the same type, e.g. not depend on
- // common.Value conversions later on
- if args.Gas.Cmp(big.NewInt(0)) == 0 {
- args.Gas = defaultGas
- }
-
- if args.GasPrice.Cmp(big.NewInt(0)) == 0 {
- args.GasPrice = defaultGasPrice
- }
-
- *reply, err = p.xeth().Transact(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
- if err != nil {
- fmt.Println("err:", err)
- return err
- }
-
- return nil
-}
-
-func (p *EthereumApi) Call(args *NewTxArgs, reply *interface{}) error {
- result, err := p.xethWithStateNum(args.BlockNumber).Call(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
- if err != nil {
- return err
- }
-
- *reply = result
- return nil
-}
-
-func (p *EthereumApi) GetBalance(args *GetBalanceArgs, reply *interface{}) error {
- if err := args.requirements(); err != nil {
- return err
- }
- state := p.getStateWithNum(args.BlockNumber).SafeGet(args.Address)
- *reply = common.ToHex(state.Balance().Bytes())
- return nil
-}
-
-func (p *EthereumApi) GetStorage(args *GetStorageArgs, reply *interface{}) error {
- if err := args.requirements(); err != nil {
- return err
- }
- *reply = p.getStateWithNum(args.BlockNumber).SafeGet(args.Address).Storage()
- return nil
-}
-
-func (p *EthereumApi) GetStorageAt(args *GetStorageAtArgs, reply *interface{}) error {
- if err := args.requirements(); err != nil {
- return err
- }
- state := p.getStateWithNum(args.BlockNumber).SafeGet(args.Address)
-
- value := state.StorageString(args.Key)
- var hx string
- if strings.Index(args.Key, "0x") == 0 {
- hx = string([]byte(args.Key)[2:])
- } else {
- // Convert the incoming string (which is a bigint) into hex
- i, _ := new(big.Int).SetString(args.Key, 10)
- hx = common.Bytes2Hex(i.Bytes())
- }
- rpclogger.Debugf("GetStateAt(%s, %s)\n", args.Address, hx)
- *reply = map[string]string{args.Key: value.Str()}
- return nil
-}
-
-func (p *EthereumApi) GetTxCountAt(args *GetTxCountArgs, reply *interface{}) error {
- err := args.requirements()
- if err != nil {
- return err
- }
- *reply = p.xethWithStateNum(args.BlockNumber).TxCountAt(args.Address)
- return nil
-}
-
-func (p *EthereumApi) GetData(args *GetDataArgs, reply *interface{}) error {
- if err := args.requirements(); err != nil {
- return err
- }
- *reply = p.xethWithStateNum(args.BlockNumber).CodeAt(args.Address)
- return nil
-}
-
-func (p *EthereumApi) GetCompilers(reply *interface{}) error {
- c := []string{""}
- *reply = c
- return nil
-}
-
-func (p *EthereumApi) DbPut(args *DbArgs, reply *interface{}) error {
- if err := args.requirements(); err != nil {
- return err
- }
-
- p.db.Put([]byte(args.Database+args.Key), []byte(args.Value))
- *reply = true
- return nil
-}
-
-func (p *EthereumApi) DbGet(args *DbArgs, reply *interface{}) error {
- if err := args.requirements(); err != nil {
- return err
- }
-
- res, _ := p.db.Get([]byte(args.Database + args.Key))
- *reply = string(res)
- return nil
-}
-
-func (p *EthereumApi) NewWhisperIdentity(reply *interface{}) error {
- *reply = p.xeth().Whisper().NewIdentity()
- return nil
-}
-
-// func (p *EthereumApi) RemoveWhisperIdentity(args *WhisperIdentityArgs, reply *interface{}) error {
-// *reply = p.xeth().Whisper().RemoveIdentity(args.Identity)
-// return nil
-// }
-
-func (p *EthereumApi) NewWhisperFilter(args *WhisperFilterArgs, reply *interface{}) error {
- var id int
- opts := new(xeth.Options)
- opts.From = args.From
- opts.To = args.To
- opts.Topics = args.Topics
- opts.Fn = func(msg xeth.WhisperMessage) {
- p.messagesMut.Lock()
- defer p.messagesMut.Unlock()
- p.messages[id].add(msg) // = append(p.messages[id], msg)
- }
- id = p.xeth().Whisper().Watch(opts)
- p.messages[id] = &whisperFilter{timeout: time.Now()}
- *reply = common.ToHex(big.NewInt(int64(id)).Bytes())
- return nil
-}
-
-func (p *EthereumApi) UninstallWhisperFilter(id int, reply *interface{}) error {
- delete(p.messages, id)
- *reply = true
- return nil
-}
-
-func (self *EthereumApi) MessagesChanged(id int, reply *interface{}) error {
- self.messagesMut.Lock()
- defer self.messagesMut.Unlock()
-
- if self.messages[id] != nil {
- *reply = self.messages[id].get()
- }
-
- return nil
-}
-
-func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{}) error {
- err := p.xeth().Whisper().Post(args.Payload, args.To, args.From, args.Topics, args.Priority, args.Ttl)
- if err != nil {
- return err
- }
-
- *reply = true
- return nil
-}
-
-func (p *EthereumApi) HasWhisperIdentity(args string, reply *interface{}) error {
- *reply = p.xeth().Whisper().HasIdentity(args)
- return nil
-}
-
-func (p *EthereumApi) WhisperMessages(id int, reply *interface{}) error {
- *reply = p.xeth().Whisper().Messages(id)
- return nil
-}
-
-func (p *EthereumApi) GetTransactionByHash(hash string, reply *interface{}) error {
- tx := p.xeth().EthTransactionByHash(hash)
- if tx != nil {
- *reply = NewTransactionRes(tx)
- }
- return nil
-}
-
-func (p *EthereumApi) GetBlockByHash(blockhash string, includetx bool) (*BlockRes, error) {
- block := p.xeth().EthBlockByHash(blockhash)
- br := NewBlockRes(block)
- br.fullTx = includetx
- return br, nil
-}
-
-func (p *EthereumApi) GetBlockByNumber(blocknum int64, includetx bool) (*BlockRes, error) {
- block := p.xeth().EthBlockByNumber(blocknum)
- br := NewBlockRes(block)
- br.fullTx = includetx
- return br, nil
-}
-
-func (p *EthereumApi) GetBlockTransactionCountByHash(blockhash string) (int64, error) {
- block := p.xeth().EthBlockByHash(blockhash)
- br := NewBlockRes(block)
- return int64(len(br.Transactions)), nil
-}
-
-func (p *EthereumApi) GetBlockTransactionCountByNumber(blocknum int64) (int64, error) {
- block := p.xeth().EthBlockByNumber(blocknum)
- br := NewBlockRes(block)
- return int64(len(br.Transactions)), nil
-}
+func (self *EthereumApi) xeth() *xeth.XEth {
+ self.xethMu.RLock()
+ defer self.xethMu.RUnlock()
-func (p *EthereumApi) GetBlockUncleCountByHash(blockhash string) (int64, error) {
- block := p.xeth().EthBlockByHash(blockhash)
- br := NewBlockRes(block)
- return int64(len(br.Uncles)), nil
+ return self.eth
}
-func (p *EthereumApi) GetBlockUncleCountByNumber(blocknum int64) (int64, error) {
- block := p.xeth().EthBlockByNumber(blocknum)
- br := NewBlockRes(block)
- return int64(len(br.Uncles)), nil
+func (self *EthereumApi) xethAtStateNum(num int64) *xeth.XEth {
+ return self.xeth().AtStateNum(num)
}
func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error {
// Spec at https://github.com/ethereum/wiki/wiki/Generic-JSON-RPC
rpclogger.Debugf("%s %s", req.Method, req.Params)
+
switch req.Method {
case "web3_sha3":
args := new(Sha3Args)
@@ -504,7 +59,8 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
case "net_listening":
*reply = p.xeth().IsListening()
case "net_peerCount":
- *reply = common.ToHex(big.NewInt(int64(p.xeth().PeerCount())).Bytes())
+ v := p.xeth().PeerCount()
+ *reply = common.ToHex(big.NewInt(int64(v)).Bytes())
case "eth_coinbase":
// TODO handling of empty coinbase due to lack of accounts
res := p.xeth().Coinbase()
@@ -516,97 +72,131 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
case "eth_mining":
*reply = p.xeth().IsMining()
case "eth_gasPrice":
- *reply = common.ToHex(defaultGasPrice.Bytes())
+ v := p.xeth().DefaultGas()
+ *reply = common.ToHex(v.Bytes())
case "eth_accounts":
*reply = p.xeth().Accounts()
case "eth_blockNumber":
- *reply = common.ToHex(p.xeth().Backend().ChainManager().CurrentBlock().Number().Bytes())
+ v := p.xeth().Backend().ChainManager().CurrentBlock().Number()
+ *reply = common.ToHex(v.Bytes())
case "eth_getBalance":
args := new(GetBalanceArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.GetBalance(args, reply)
+
+ if err := args.requirements(); err != nil {
+ return err
+ }
+
+ v := p.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Balance()
+ *reply = common.ToHex(v.Bytes())
case "eth_getStorage", "eth_storageAt":
args := new(GetStorageArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.GetStorage(args, reply)
+
+ if err := args.requirements(); err != nil {
+ return err
+ }
+
+ *reply = p.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address).Storage()
case "eth_getStorageAt":
args := new(GetStorageAtArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.GetStorageAt(args, reply)
+ if err := args.requirements(); err != nil {
+ return err
+ }
+
+ state := p.xethAtStateNum(args.BlockNumber).State().SafeGet(args.Address)
+ value := state.StorageString(args.Key)
+
+ *reply = common.Bytes2Hex(value.Bytes())
case "eth_getTransactionCount":
args := new(GetTxCountArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.GetTxCountAt(args, reply)
+
+ err := args.requirements()
+ if err != nil {
+ return err
+ }
+
+ *reply = p.xethAtStateNum(args.BlockNumber).TxCountAt(args.Address)
case "eth_getBlockTransactionCountByHash":
args := new(GetBlockByHashArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- v, err := p.GetBlockTransactionCountByHash(args.BlockHash)
- if err != nil {
- return err
- }
- *reply = common.ToHex(big.NewInt(v).Bytes())
+ block := NewBlockRes(p.xeth().EthBlockByHash(args.BlockHash))
+ *reply = common.ToHex(big.NewInt(int64(len(block.Transactions))).Bytes())
case "eth_getBlockTransactionCountByNumber":
args := new(GetBlockByNumberArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- v, err := p.GetBlockTransactionCountByNumber(args.BlockNumber)
- if err != nil {
- return err
- }
- *reply = common.ToHex(big.NewInt(v).Bytes())
+ block := NewBlockRes(p.xeth().EthBlockByNumber(args.BlockNumber))
+ *reply = common.ToHex(big.NewInt(int64(len(block.Transactions))).Bytes())
case "eth_getUncleCountByBlockHash":
args := new(GetBlockByHashArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- v, err := p.GetBlockUncleCountByHash(args.BlockHash)
- if err != nil {
- return err
- }
- *reply = common.ToHex(big.NewInt(v).Bytes())
+ block := p.xeth().EthBlockByHash(args.BlockHash)
+ br := NewBlockRes(block)
+ *reply = common.ToHex(big.NewInt(int64(len(br.Uncles))).Bytes())
case "eth_getUncleCountByBlockNumber":
args := new(GetBlockByNumberArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- v, err := p.GetBlockUncleCountByNumber(args.BlockNumber)
- if err != nil {
- return err
- }
- *reply = common.ToHex(big.NewInt(v).Bytes())
+ block := p.xeth().EthBlockByNumber(args.BlockNumber)
+ br := NewBlockRes(block)
+ *reply = common.ToHex(big.NewInt(int64(len(br.Uncles))).Bytes())
case "eth_getData", "eth_getCode":
args := new(GetDataArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.GetData(args, reply)
+ if err := args.requirements(); err != nil {
+ return err
+ }
+ *reply = p.xethAtStateNum(args.BlockNumber).CodeAt(args.Address)
case "eth_sendTransaction", "eth_transact":
args := new(NewTxArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.Transact(args, reply)
+
+ if err := args.requirements(); err != nil {
+ return err
+ }
+
+ v, err := p.xeth().Transact(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
+ if err != nil {
+ return err
+ }
+ *reply = v
case "eth_call":
args := new(NewTxArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.Call(args, reply)
+
+ v, err := p.xethAtStateNum(args.BlockNumber).Call(args.From, args.To, args.Value.String(), args.Gas.String(), args.GasPrice.String(), args.Data)
+ if err != nil {
+ return err
+ }
+
+ *reply = v
case "eth_flush":
return NewNotImplementedError(req.Method)
case "eth_getBlockByHash":
@@ -615,52 +205,55 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return err
}
- v, err := p.GetBlockByHash(args.BlockHash, args.Transactions)
- if err != nil {
- return err
- }
- *reply = v
+ block := p.xeth().EthBlockByHash(args.BlockHash)
+ br := NewBlockRes(block)
+ br.fullTx = args.IncludeTxs
+
+ *reply = br
case "eth_getBlockByNumber":
args := new(GetBlockByNumberArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- v, err := p.GetBlockByNumber(args.BlockNumber, args.Transactions)
- if err != nil {
- return err
- }
- *reply = v
+ block := p.xeth().EthBlockByNumber(args.BlockNumber)
+ br := NewBlockRes(block)
+ br.fullTx = args.IncludeTxs
+
+ *reply = br
case "eth_getTransactionByHash":
// HashIndexArgs used, but only the "Hash" part we need.
args := new(HashIndexArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
}
- return p.GetTransactionByHash(args.Hash, reply)
+ tx := p.xeth().EthTransactionByHash(args.Hash)
+ if tx != nil {
+ *reply = NewTransactionRes(tx)
+ }
case "eth_getTransactionByBlockHashAndIndex":
args := new(HashIndexArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- v, err := p.GetBlockByHash(args.Hash, true)
- if err != nil {
- return err
- }
- if args.Index > int64(len(v.Transactions)) || args.Index < 0 {
+ block := p.xeth().EthBlockByHash(args.Hash)
+ br := NewBlockRes(block)
+ br.fullTx = true
+
+ if args.Index > int64(len(br.Transactions)) || args.Index < 0 {
return NewValidationError("Index", "does not exist")
}
- *reply = v.Transactions[args.Index]
+ *reply = br.Transactions[args.Index]
case "eth_getTransactionByBlockNumberAndIndex":
args := new(BlockNumIndexArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- v, err := p.GetBlockByNumber(args.BlockNumber, true)
- if err != nil {
- return err
- }
+ block := p.xeth().EthBlockByNumber(args.BlockNumber)
+ v := NewBlockRes(block)
+ v.fullTx = true
+
if args.Index > int64(len(v.Transactions)) || args.Index < 0 {
return NewValidationError("Index", "does not exist")
}
@@ -671,18 +264,15 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return err
}
- v, err := p.GetBlockByHash(args.Hash, false)
- if err != nil {
- return err
- }
- if args.Index > int64(len(v.Uncles)) || args.Index < 0 {
+ br := NewBlockRes(p.xeth().EthBlockByHash(args.Hash))
+
+ if args.Index > int64(len(br.Uncles)) || args.Index < 0 {
return NewValidationError("Index", "does not exist")
}
- uncle, err := p.GetBlockByHash(common.ToHex(v.Uncles[args.Index]), false)
- if err != nil {
- return err
- }
+ uhash := common.ToHex(br.Uncles[args.Index])
+ uncle := NewBlockRes(p.xeth().EthBlockByHash(uhash))
+
*reply = uncle
case "eth_getUncleByBlockNumberAndIndex":
args := new(BlockNumIndexArgs)
@@ -690,59 +280,68 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return err
}
- v, err := p.GetBlockByNumber(args.BlockNumber, true)
- if err != nil {
- return err
- }
+ block := p.xeth().EthBlockByNumber(args.BlockNumber)
+ v := NewBlockRes(block)
+ v.fullTx = true
+
if args.Index > int64(len(v.Uncles)) || args.Index < 0 {
return NewValidationError("Index", "does not exist")
}
- uncle, err := p.GetBlockByHash(common.ToHex(v.Uncles[args.Index]), false)
- if err != nil {
- return err
- }
+ uhash := common.ToHex(v.Uncles[args.Index])
+ uncle := NewBlockRes(p.xeth().EthBlockByHash(uhash))
+
*reply = uncle
case "eth_getCompilers":
- return p.GetCompilers(reply)
+ c := []string{""}
+ *reply = c
case "eth_compileSolidity", "eth_compileLLL", "eth_compileSerpent":
return NewNotImplementedError(req.Method)
case "eth_newFilter":
- args := new(FilterOptions)
+ args := new(BlockFilterArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.NewFilter(args, reply)
+
+ opts := toFilterOptions(args)
+ id := p.xeth().RegisterFilter(opts)
+ *reply = common.ToHex(big.NewInt(int64(id)).Bytes())
case "eth_newBlockFilter":
args := new(FilterStringArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.NewFilterString(args, reply)
+ if err := args.requirements(); err != nil {
+ return err
+ }
+
+ id := p.xeth().NewFilterString(args.Word)
+ *reply = common.ToHex(big.NewInt(int64(id)).Bytes())
case "eth_uninstallFilter":
args := new(FilterIdArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.UninstallFilter(args.Id, reply)
+ *reply = p.xeth().UninstallFilter(args.Id)
case "eth_getFilterChanges":
args := new(FilterIdArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.FilterChanged(args.Id, reply)
+ *reply = NewLogsRes(p.xeth().FilterChanged(args.Id))
case "eth_getFilterLogs":
args := new(FilterIdArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.Logs(args.Id, reply)
+ *reply = NewLogsRes(p.xeth().Logs(args.Id))
case "eth_getLogs":
- args := new(FilterOptions)
+ args := new(BlockFilterArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.AllLogs(args, reply)
+ opts := toFilterOptions(args)
+ *reply = NewLogsRes(p.xeth().AllLogs(opts))
case "eth_getWork", "eth_submitWork":
return NewNotImplementedError(req.Method)
case "db_putString":
@@ -750,13 +349,25 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.DbPut(args, reply)
+
+ if err := args.requirements(); err != nil {
+ return err
+ }
+
+ p.db.Put([]byte(args.Database+args.Key), []byte(args.Value))
+ *reply = true
case "db_getString":
args := new(DbArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.DbGet(args, reply)
+
+ if err := args.requirements(); err != nil {
+ return err
+ }
+
+ res, _ := p.db.Get([]byte(args.Database + args.Key))
+ *reply = string(res)
case "db_putHex", "db_getHex":
return NewNotImplementedError(req.Method)
case "shh_post":
@@ -764,21 +375,27 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.WhisperPost(args, reply)
+
+ err := p.xeth().Whisper().Post(args.Payload, args.To, args.From, args.Topics, args.Priority, args.Ttl)
+ if err != nil {
+ return err
+ }
+
+ *reply = true
case "shh_newIdentity":
- return p.NewWhisperIdentity(reply)
+ *reply = p.xeth().Whisper().NewIdentity()
// case "shh_removeIdentity":
// args := new(WhisperIdentityArgs)
// if err := json.Unmarshal(req.Params, &args); err != nil {
// return err
// }
- // return p.RemoveWhisperIdentity(args, reply)
+ // *reply = p.xeth().Whisper().RemoveIdentity(args.Identity)
case "shh_hasIdentity":
args := new(WhisperIdentityArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.HasWhisperIdentity(args.Identity, reply)
+ *reply = p.xeth().Whisper().HasIdentity(args.Identity)
case "shh_newGroup", "shh_addToGroup":
return NewNotImplementedError(req.Method)
case "shh_newFilter":
@@ -786,43 +403,49 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.NewWhisperFilter(args, reply)
+ opts := new(xeth.Options)
+ opts.From = args.From
+ opts.To = args.To
+ opts.Topics = args.Topics
+ id := p.xeth().NewWhisperFilter(opts)
+ *reply = common.ToHex(big.NewInt(int64(id)).Bytes())
case "shh_uninstallFilter":
args := new(FilterIdArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.UninstallWhisperFilter(args.Id, reply)
+ *reply = p.xeth().UninstallWhisperFilter(args.Id)
case "shh_getFilterChanges":
args := new(FilterIdArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.MessagesChanged(args.Id, reply)
+ *reply = p.xeth().MessagesChanged(args.Id)
case "shh_getMessages":
args := new(FilterIdArgs)
if err := json.Unmarshal(req.Params, &args); err != nil {
return err
}
- return p.WhisperMessages(args.Id, reply)
+ *reply = p.xeth().Whisper().Messages(args.Id)
// case "eth_register":
- // args, err := req.ToRegisterArgs()
- // if err != nil {
+ // // Placeholder for actual type
+ // args := new(HashIndexArgs)
+ // if err := json.Unmarshal(req.Params, &args); err != nil {
// return err
// }
- // return p.Register(args, reply)
+ // *reply = p.xeth().Register(args.Hash)
// case "eth_unregister":
- // args, err := req.ToRegisterArgs()
- // if err != nil {
+ // args := new(HashIndexArgs)
+ // if err := json.Unmarshal(req.Params, &args); err != nil {
// return err
// }
- // return p.Unregister(args, reply)
+ // *reply = p.xeth().Unregister(args.Hash)
// case "eth_watchTx":
- // args, err := req.ToWatchTxArgs()
- // if err != nil {
+ // args := new(HashIndexArgs)
+ // if err := json.Unmarshal(req.Params, &args); err != nil {
// return err
// }
- // return p.WatchTx(args, reply)
+ // *reply = p.xeth().PullWatchTx(args.Hash)
default:
return NewNotImplementedError(req.Method)
}
@@ -831,14 +454,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return nil
}
-func (self *EthereumApi) xeth() *xeth.XEth {
- self.xethMu.RLock()
- defer self.xethMu.RUnlock()
-
- return self.eth
-}
-
-func toFilterOptions(options *FilterOptions) core.FilterOptions {
+func toFilterOptions(options *BlockFilterArgs) *core.FilterOptions {
var opts core.FilterOptions
// Convert optional address slice/string to byte slice
@@ -871,38 +487,5 @@ func toFilterOptions(options *FilterOptions) core.FilterOptions {
}
opts.Topics = topics
- 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
+ return &opts
}
diff --git a/rpc/api_test.go b/rpc/api_test.go
index ec03822c5..727ade007 100644
--- a/rpc/api_test.go
+++ b/rpc/api_test.go
@@ -2,9 +2,9 @@ package rpc
import (
"encoding/json"
- "sync"
+ // "sync"
"testing"
- "time"
+ // "time"
)
func TestWeb3Sha3(t *testing.T) {
@@ -24,33 +24,33 @@ func TestWeb3Sha3(t *testing.T) {
}
}
-func TestFilterClose(t *testing.T) {
- t.Skip()
- api := &EthereumApi{
- logs: make(map[int]*logFilter),
- messages: make(map[int]*whisperFilter),
- quit: make(chan struct{}),
- }
-
- filterTickerTime = 1
- api.logs[0] = &logFilter{}
- api.messages[0] = &whisperFilter{}
- var wg sync.WaitGroup
- wg.Add(1)
- go api.start()
- go func() {
- select {
- case <-time.After(500 * time.Millisecond):
- api.stop()
- wg.Done()
- }
- }()
- wg.Wait()
- if len(api.logs) != 0 {
- t.Error("expected logs to be empty")
- }
-
- if len(api.messages) != 0 {
- t.Error("expected messages to be empty")
- }
-}
+// func TestFilterClose(t *testing.T) {
+// t.Skip()
+// api := &EthereumApi{
+// logs: make(map[int]*logFilter),
+// messages: make(map[int]*whisperFilter),
+// quit: make(chan struct{}),
+// }
+
+// filterTickerTime = 1
+// api.logs[0] = &logFilter{}
+// api.messages[0] = &whisperFilter{}
+// var wg sync.WaitGroup
+// wg.Add(1)
+// go api.start()
+// go func() {
+// select {
+// case <-time.After(500 * time.Millisecond):
+// api.stop()
+// wg.Done()
+// }
+// }()
+// wg.Wait()
+// if len(api.logs) != 0 {
+// t.Error("expected logs to be empty")
+// }
+
+// if len(api.messages) != 0 {
+// t.Error("expected messages to be empty")
+// }
+// }
diff --git a/rpc/args.go b/rpc/args.go
index ab1c40585..e50c9b1f5 100644
--- a/rpc/args.go
+++ b/rpc/args.go
@@ -35,8 +35,8 @@ func blockAge(raw interface{}, number *int64) (err error) {
}
type GetBlockByHashArgs struct {
- BlockHash string
- Transactions bool
+ BlockHash string
+ IncludeTxs bool
}
func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
@@ -57,15 +57,15 @@ func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
args.BlockHash = argstr
if len(obj) > 1 {
- args.Transactions = obj[1].(bool)
+ args.IncludeTxs = obj[1].(bool)
}
return nil
}
type GetBlockByNumberArgs struct {
- BlockNumber int64
- Transactions bool
+ BlockNumber int64
+ IncludeTxs bool
}
func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
@@ -86,7 +86,7 @@ func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
}
if len(obj) > 1 {
- args.Transactions = obj[1].(bool)
+ args.IncludeTxs = obj[1].(bool)
}
return nil
@@ -433,7 +433,7 @@ func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
return nil
}
-type FilterOptions struct {
+type BlockFilterArgs struct {
Earliest int64
Latest int64
Address interface{}
@@ -442,7 +442,7 @@ type FilterOptions struct {
Max int
}
-func (args *FilterOptions) UnmarshalJSON(b []byte) (err error) {
+func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
var obj []struct {
FromBlock interface{} `json:"fromBlock"`
ToBlock interface{} `json:"toBlock"`
@@ -609,6 +609,16 @@ func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
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 {
Id int
}
diff --git a/rpc/args_test.go b/rpc/args_test.go
index 0d8dc4085..cfdd278b8 100644
--- a/rpc/args_test.go
+++ b/rpc/args_test.go
@@ -82,7 +82,7 @@ func TestGetBlockByHashArgs(t *testing.T) {
input := `["0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331", true]`
expected := new(GetBlockByHashArgs)
expected.BlockHash = "0xe670ec64341771606e55d6b4ca35a1a6b75ee3d5145a99d05921026d1527331"
- expected.Transactions = true
+ expected.IncludeTxs = true
args := new(GetBlockByHashArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil {
@@ -93,8 +93,8 @@ func TestGetBlockByHashArgs(t *testing.T) {
t.Errorf("BlockHash should be %v but is %v", expected.BlockHash, args.BlockHash)
}
- if args.Transactions != expected.Transactions {
- t.Errorf("Transactions should be %v but is %v", expected.Transactions, args.Transactions)
+ if args.IncludeTxs != expected.IncludeTxs {
+ t.Errorf("IncludeTxs should be %v but is %v", expected.IncludeTxs, args.IncludeTxs)
}
}
@@ -112,7 +112,7 @@ func TestGetBlockByNumberArgs(t *testing.T) {
input := `["0x1b4", false]`
expected := new(GetBlockByNumberArgs)
expected.BlockNumber = 436
- expected.Transactions = false
+ expected.IncludeTxs = false
args := new(GetBlockByNumberArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil {
@@ -123,8 +123,8 @@ func TestGetBlockByNumberArgs(t *testing.T) {
t.Errorf("BlockHash should be %v but is %v", expected.BlockNumber, args.BlockNumber)
}
- if args.Transactions != expected.Transactions {
- t.Errorf("Transactions should be %v but is %v", expected.Transactions, args.Transactions)
+ if args.IncludeTxs != expected.IncludeTxs {
+ t.Errorf("IncludeTxs should be %v but is %v", expected.IncludeTxs, args.IncludeTxs)
}
}
@@ -388,7 +388,7 @@ func TestGetDataEmptyArgs(t *testing.T) {
}
}
-func TestFilterOptions(t *testing.T) {
+func TestBlockFilterArgs(t *testing.T) {
input := `[{
"fromBlock": "0x1",
"toBlock": "0x2",
@@ -396,7 +396,7 @@ func TestFilterOptions(t *testing.T) {
"offset": "0x0",
"address": "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8",
"topics": ["0x12341234"]}]`
- expected := new(FilterOptions)
+ expected := new(BlockFilterArgs)
expected.Earliest = 1
expected.Latest = 2
expected.Max = 3
@@ -404,7 +404,7 @@ func TestFilterOptions(t *testing.T) {
expected.Address = "0xd5677cf67b5aa051bb40496e68ad359eb97cfbf8"
// expected.Topics = []string{"0x12341234"}
- args := new(FilterOptions)
+ args := new(BlockFilterArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil {
t.Error(err)
}
@@ -434,16 +434,16 @@ func TestFilterOptions(t *testing.T) {
// }
}
-func TestFilterOptionsWords(t *testing.T) {
+func TestBlockFilterArgsWords(t *testing.T) {
input := `[{
"fromBlock": "latest",
"toBlock": "pending"
}]`
- expected := new(FilterOptions)
+ expected := new(BlockFilterArgs)
expected.Earliest = 0
expected.Latest = -1
- args := new(FilterOptions)
+ args := new(BlockFilterArgs)
if err := json.Unmarshal([]byte(input), &args); err != nil {
t.Error(err)
}
@@ -457,13 +457,13 @@ func TestFilterOptionsWords(t *testing.T) {
}
}
-func TestFilterOptionsNums(t *testing.T) {
+func TestBlockFilterArgsNums(t *testing.T) {
input := `[{
"fromBlock": 2,
"toBlock": 3
}]`
- args := new(FilterOptions)
+ args := new(BlockFilterArgs)
err := json.Unmarshal([]byte(input), &args)
switch err.(type) {
case *DecodeParamError:
@@ -474,10 +474,10 @@ func TestFilterOptionsNums(t *testing.T) {
}
-func TestFilterOptionsEmptyArgs(t *testing.T) {
+func TestBlockFilterArgsEmptyArgs(t *testing.T) {
input := `[]`
- args := new(FilterOptions)
+ args := new(BlockFilterArgs)
err := json.Unmarshal([]byte(input), &args)
if err == nil {
t.Error("Expected error but didn't get one")