aboutsummaryrefslogtreecommitdiffstats
path: root/rpc
diff options
context:
space:
mode:
Diffstat (limited to 'rpc')
-rw-r--r--rpc/api.go774
-rw-r--r--rpc/api_test.go64
-rw-r--r--rpc/args.go26
-rw-r--r--rpc/args_test.go32
-rw-r--r--rpc/http.go16
-rw-r--r--rpc/messages_test.go41
-rw-r--r--rpc/miner_agest.go70
-rw-r--r--rpc/responses.go102
-rw-r--r--rpc/util.go86
9 files changed, 458 insertions, 753 deletions
diff --git a/rpc/api.go b/rpc/api.go
index fcf2ac9dc..d5e18eec8 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -2,494 +2,54 @@ 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
+ // Miner agent
+ agent *Agent
}
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,
+ agent: NewAgent(),
}
- go api.filterManager.Start()
- go api.start()
+ eth.Backend().Miner().Register(api.agent)
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 = toLogs(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 = toLogs(filter.Find())
- }
-
- return nil
-}
-
-func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error {
- filter := core.NewFilter(self.xeth().Backend())
- filter.SetOptions(toFilterOptions(args))
-
- *reply = toLogs(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 +64,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 +77,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 +210,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 +269,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 := br.Uncles[args.Index].Hex()
+ uncle := NewBlockRes(p.xeth().EthBlockByHash(uhash))
+
*reply = uncle
case "eth_getUncleByBlockNumberAndIndex":
args := new(BlockNumIndexArgs)
@@ -690,73 +285,100 @@ 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 := v.Uncles[args.Index].Hex()
+ 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)
- case "eth_getWork", "eth_submitWork":
+ opts := toFilterOptions(args)
+ *reply = NewLogsRes(p.xeth().AllLogs(opts))
+ case "eth_getWork":
+ *reply = p.getWork()
+ case "eth_submitWork":
+ // TODO what is the reply here?
+ // TODO what are the arguments?
+ p.agent.SetResult(0, common.Hash{}, common.Hash{})
+
return NewNotImplementedError(req.Method)
case "db_putString":
args := new(DbArgs)
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 +386,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 +414,50 @@ 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,24 +466,22 @@ 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 (p *EthereumApi) getWork() string {
+ p.xeth().SetMining(true)
+ return p.agent.GetWork().Hex()
}
-func toFilterOptions(options *FilterOptions) core.FilterOptions {
+func toFilterOptions(options *BlockFilterArgs) *core.FilterOptions {
var opts core.FilterOptions
// Convert optional address slice/string to byte slice
if str, ok := options.Address.(string); ok {
- opts.Address = [][]byte{common.FromHex(str)}
+ opts.Address = []common.Address{common.HexToAddress(str)}
} else if slice, ok := options.Address.([]interface{}); ok {
- bslice := make([][]byte, len(slice))
+ bslice := make([]common.Address, len(slice))
for i, addr := range slice {
if saddr, ok := addr.(string); ok {
- bslice[i] = common.FromHex(saddr)
+ bslice[i] = common.HexToAddress(saddr)
}
}
opts.Address = bslice
@@ -857,19 +490,26 @@ func toFilterOptions(options *FilterOptions) core.FilterOptions {
opts.Earliest = options.Earliest
opts.Latest = options.Latest
- topics := make([][][]byte, len(options.Topics))
+ topics := make([][]common.Hash, len(options.Topics))
for i, topicDat := range options.Topics {
if slice, ok := topicDat.([]interface{}); ok {
- topics[i] = make([][]byte, len(slice))
+ topics[i] = make([]common.Hash, len(slice))
for j, topic := range slice {
- topics[i][j] = common.FromHex(topic.(string))
+ topics[i][j] = common.HexToHash(topic.(string))
}
} else if str, ok := topicDat.(string); ok {
- topics[i] = make([][]byte, 1)
- topics[i][0] = common.FromHex(str)
+ topics[i] = []common.Hash{common.HexToHash(str)}
}
}
opts.Topics = topics
- return opts
+ return &opts
}
+
+/*
+ Work() chan<- *types.Block
+ SetWorkCh(chan<- Work)
+ Stop()
+ Start()
+ Rate() uint64
+*/
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")
diff --git a/rpc/http.go b/rpc/http.go
index 5f2445e6c..3dfb67781 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 000000000..5274c91e4
--- /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/miner_agest.go b/rpc/miner_agest.go
new file mode 100644
index 000000000..64dba82a6
--- /dev/null
+++ b/rpc/miner_agest.go
@@ -0,0 +1,70 @@
+package rpc
+
+import (
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/miner"
+)
+
+type Agent struct {
+ work *types.Block
+ currentWork *types.Block
+
+ quit chan struct{}
+ workCh chan *types.Block
+ returnCh chan<- miner.Work
+}
+
+func NewAgent() *Agent {
+ agent := &Agent{}
+ go agent.run()
+
+ return agent
+}
+
+func (a *Agent) Work() chan<- *types.Block {
+ return a.workCh
+}
+
+func (a *Agent) SetWorkCh(returnCh chan<- miner.Work) {
+ a.returnCh = returnCh
+}
+
+func (a *Agent) Start() {
+ a.quit = make(chan struct{})
+ a.workCh = make(chan *types.Block, 1)
+}
+
+func (a *Agent) Stop() {
+ close(a.quit)
+ close(a.workCh)
+}
+
+func (a *Agent) GetHashRate() int64 { return 0 }
+
+func (a *Agent) run() {
+out:
+ for {
+ select {
+ case <-a.quit:
+ break out
+ case work := <-a.workCh:
+ a.work = work
+ }
+ }
+}
+
+func (a *Agent) GetWork() common.Hash {
+ // XXX Wait here untill work != nil ?.
+ if a.work != nil {
+ return a.work.HashNoNonce()
+ }
+ return common.Hash{}
+}
+
+func (a *Agent) SetResult(nonce uint64, mixDigest, seedHash common.Hash) {
+ // Make sure the external miner was working on the right hash
+ if a.currentWork != nil && a.work != nil && a.currentWork.Hash() == a.work.Hash() {
+ a.returnCh <- miner.Work{a.currentWork.Number().Uint64(), nonce, mixDigest.Bytes(), seedHash.Bytes()}
+ }
+}
diff --git a/rpc/responses.go b/rpc/responses.go
index eec483fb7..1ec5f08eb 100644
--- a/rpc/responses.go
+++ b/rpc/responses.go
@@ -7,20 +7,21 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/state"
)
type BlockRes struct {
fullTx bool
BlockNumber int64 `json:"number"`
- BlockHash []byte `json:"hash"`
- ParentHash []byte `json:"parentHash"`
- Nonce []byte `json:"nonce"`
- Sha3Uncles []byte `json:"sha3Uncles"`
- LogsBloom []byte `json:"logsBloom"`
- TransactionRoot []byte `json:"transactionRoot"`
- StateRoot []byte `json:"stateRoot"`
- Miner []byte `json:"miner"`
+ BlockHash common.Hash `json:"hash"`
+ ParentHash common.Hash `json:"parentHash"`
+ Nonce [8]byte `json:"nonce"`
+ Sha3Uncles common.Hash `json:"sha3Uncles"`
+ LogsBloom types.Bloom `json:"logsBloom"`
+ TransactionRoot common.Hash `json:"transactionRoot"`
+ StateRoot common.Hash `json:"stateRoot"`
+ Miner common.Address `json:"miner"`
Difficulty int64 `json:"difficulty"`
TotalDifficulty int64 `json:"totalDifficulty"`
Size int64 `json:"size"`
@@ -30,7 +31,7 @@ type BlockRes struct {
GasUsed int64 `json:"gasUsed"`
UnixTimestamp int64 `json:"timestamp"`
Transactions []*TransactionRes `json:"transactions"`
- Uncles [][]byte `json:"uncles"`
+ Uncles []common.Hash `json:"uncles"`
}
func (b *BlockRes) MarshalJSON() ([]byte, error) {
@@ -58,14 +59,14 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) {
// convert strict types to hexified strings
ext.BlockNumber = common.ToHex(big.NewInt(b.BlockNumber).Bytes())
- ext.BlockHash = common.ToHex(b.BlockHash)
- ext.ParentHash = common.ToHex(b.ParentHash)
- ext.Nonce = common.ToHex(b.Nonce)
- ext.Sha3Uncles = common.ToHex(b.Sha3Uncles)
- ext.LogsBloom = common.ToHex(b.LogsBloom)
- ext.TransactionRoot = common.ToHex(b.TransactionRoot)
- ext.StateRoot = common.ToHex(b.StateRoot)
- ext.Miner = common.ToHex(b.Miner)
+ ext.BlockHash = b.BlockHash.Hex()
+ ext.ParentHash = b.ParentHash.Hex()
+ ext.Nonce = common.ToHex(b.Nonce[:])
+ ext.Sha3Uncles = b.Sha3Uncles.Hex()
+ ext.LogsBloom = common.ToHex(b.LogsBloom[:])
+ ext.TransactionRoot = b.TransactionRoot.Hex()
+ ext.StateRoot = b.StateRoot.Hex()
+ ext.Miner = b.Miner.Hex()
ext.Difficulty = common.ToHex(big.NewInt(b.Difficulty).Bytes())
ext.TotalDifficulty = common.ToHex(big.NewInt(b.TotalDifficulty).Bytes())
ext.Size = common.ToHex(big.NewInt(b.Size).Bytes())
@@ -81,12 +82,12 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) {
}
} else {
for i, tx := range b.Transactions {
- ext.Transactions[i] = common.ToHex(tx.Hash)
+ ext.Transactions[i] = tx.Hash.Hex()
}
}
ext.Uncles = make([]string, len(b.Uncles))
for i, v := range b.Uncles {
- ext.Uncles[i] = common.ToHex(v)
+ ext.Uncles[i] = v.Hex()
}
return json.Marshal(ext)
@@ -125,7 +126,7 @@ func NewBlockRes(block *types.Block) *BlockRes {
v.TxIndex = int64(i)
res.Transactions[i] = v
}
- res.Uncles = make([][]byte, len(block.Uncles()))
+ res.Uncles = make([]common.Hash, len(block.Uncles()))
for i, uncle := range block.Uncles() {
res.Uncles[i] = uncle.Hash()
}
@@ -133,17 +134,17 @@ func NewBlockRes(block *types.Block) *BlockRes {
}
type TransactionRes struct {
- Hash []byte `json:"hash"`
- Nonce int64 `json:"nonce"`
- BlockHash []byte `json:"blockHash,omitempty"`
- BlockNumber int64 `json:"blockNumber,omitempty"`
- TxIndex int64 `json:"transactionIndex,omitempty"`
- From []byte `json:"from"`
- To []byte `json:"to"`
- Value int64 `json:"value"`
- Gas int64 `json:"gas"`
- GasPrice int64 `json:"gasPrice"`
- Input []byte `json:"input"`
+ Hash common.Hash `json:"hash"`
+ Nonce int64 `json:"nonce"`
+ BlockHash common.Hash `json:"blockHash,omitempty"`
+ BlockNumber int64 `json:"blockNumber,omitempty"`
+ TxIndex int64 `json:"transactionIndex,omitempty"`
+ From common.Address `json:"from"`
+ To *common.Address `json:"to"`
+ Value int64 `json:"value"`
+ Gas int64 `json:"gas"`
+ GasPrice int64 `json:"gasPrice"`
+ Input []byte `json:"input"`
}
func (t *TransactionRes) MarshalJSON() ([]byte, error) {
@@ -161,13 +162,17 @@ func (t *TransactionRes) MarshalJSON() ([]byte, error) {
Input string `json:"input"`
}
- ext.Hash = common.ToHex(t.Hash)
+ ext.Hash = t.Hash.Hex()
ext.Nonce = common.ToHex(big.NewInt(t.Nonce).Bytes())
- ext.BlockHash = common.ToHex(t.BlockHash)
+ ext.BlockHash = t.BlockHash.Hex()
ext.BlockNumber = common.ToHex(big.NewInt(t.BlockNumber).Bytes())
ext.TxIndex = common.ToHex(big.NewInt(t.TxIndex).Bytes())
- ext.From = common.ToHex(t.From)
- ext.To = common.ToHex(t.To)
+ ext.From = t.From.Hex()
+ if t.To == nil {
+ ext.To = "0x00"
+ } else {
+ ext.To = t.To.Hex()
+ }
ext.Value = common.ToHex(big.NewInt(t.Value).Bytes())
ext.Gas = common.ToHex(big.NewInt(t.Gas).Bytes())
ext.GasPrice = common.ToHex(big.NewInt(t.GasPrice).Bytes())
@@ -180,7 +185,7 @@ func NewTransactionRes(tx *types.Transaction) *TransactionRes {
var v = new(TransactionRes)
v.Hash = tx.Hash()
v.Nonce = int64(tx.Nonce())
- v.From = tx.From()
+ v.From, _ = tx.From()
v.To = tx.To()
v.Value = tx.Value().Int64()
v.Gas = tx.Gas().Int64()
@@ -211,3 +216,28 @@ type FilterWhisperRes struct {
Payload string `json:"payload"`
WorkProved string `json:"workProved"`
}
+
+type LogRes struct {
+ Address string `json:"address"`
+ Topics []string `json:"topics"`
+ 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.Topics = 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.Topics[j] = topic.Hex()
+ }
+ ls[i] = l
+ }
+
+ return
+}
diff --git a/rpc/util.go b/rpc/util.go
deleted file mode 100644
index 0798ae1d2..000000000
--- 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 <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 = 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
-}