Browse Source

removed old rpc structure and added new inproc api client

Bas van Kervel 10 năm trước cách đây
mục cha
commit
a4a4e9fcf8
22 tập tin đã thay đổi với 393 bổ sung4427 xóa
  1. 0 937
      cmd/geth/admin.go
  2. 186 3
      cmd/geth/js.go
  3. 7 2
      cmd/geth/main.go
  4. 2 2
      cmd/utils/flags.go
  5. 1 1
      core/transaction_pool.go
  6. 0 646
      rpc/api.go
  7. 4 6
      rpc/api/api.go
  8. 57 0
      rpc/api/args.go
  9. 6 5
      rpc/api/args_test.go
  10. 0 205
      rpc/api_test.go
  11. 0 1230
      rpc/args.go
  12. 17 1
      rpc/comms/comms.go
  13. 24 0
      rpc/comms/http.go
  14. 7 7
      rpc/comms/http_net.go
  15. 53 0
      rpc/comms/inproc.go
  16. 4 4
      rpc/comms/ipc.go
  17. 0 163
      rpc/http.go
  18. 25 19
      rpc/jeth.go
  19. 0 316
      rpc/responses.go
  20. 0 295
      rpc/responses_test.go
  21. 0 381
      rpc/types.go
  22. 0 204
      rpc/types_test.go

+ 0 - 937
cmd/geth/admin.go

@@ -1,937 +0,0 @@
-package main
-
-import (
-	"encoding/json"
-	"errors"
-	"fmt"
-	"math/big"
-	"strconv"
-	"time"
-
-	"github.com/ethereum/ethash"
-	"github.com/ethereum/go-ethereum/accounts"
-	"github.com/ethereum/go-ethereum/cmd/utils"
-	"github.com/ethereum/go-ethereum/common"
-	"github.com/ethereum/go-ethereum/common/compiler"
-	"github.com/ethereum/go-ethereum/common/natspec"
-	"github.com/ethereum/go-ethereum/common/resolver"
-	"github.com/ethereum/go-ethereum/core/state"
-	"github.com/ethereum/go-ethereum/core/types"
-	"github.com/ethereum/go-ethereum/core/vm"
-	"github.com/ethereum/go-ethereum/crypto"
-	"github.com/ethereum/go-ethereum/logger/glog"
-	"github.com/ethereum/go-ethereum/rlp"
-	"github.com/ethereum/go-ethereum/rpc"
-	"github.com/ethereum/go-ethereum/xeth"
-	"github.com/robertkrimen/otto"
-	"gopkg.in/fatih/set.v0"
-)
-
-/*
-node admin bindings
-*/
-
-func (js *jsre) adminBindings() {
-	ethO, _ := js.re.Get("eth")
-	eth := ethO.Object()
-	eth.Set("pendingTransactions", js.pendingTransactions)
-	eth.Set("resend", js.resend)
-	eth.Set("sign", js.sign)
-
-	js.re.Set("admin", struct{}{})
-	t, _ := js.re.Get("admin")
-	admin := t.Object()
-	admin.Set("addPeer", js.addPeer)
-	admin.Set("startRPC", js.startRPC)
-	admin.Set("stopRPC", js.stopRPC)
-	admin.Set("nodeInfo", js.nodeInfo)
-	admin.Set("peers", js.peers)
-	admin.Set("newAccount", js.newAccount)
-	admin.Set("unlock", js.unlock)
-	admin.Set("import", js.importChain)
-	admin.Set("export", js.exportChain)
-	admin.Set("verbosity", js.verbosity)
-	admin.Set("progress", js.syncProgress)
-	admin.Set("setSolc", js.setSolc)
-
-	admin.Set("contractInfo", struct{}{})
-	t, _ = admin.Get("contractInfo")
-	cinfo := t.Object()
-	// newRegistry officially not documented temporary option
-	cinfo.Set("start", js.startNatSpec)
-	cinfo.Set("stop", js.stopNatSpec)
-	cinfo.Set("newRegistry", js.newRegistry)
-	cinfo.Set("get", js.getContractInfo)
-	cinfo.Set("register", js.register)
-	cinfo.Set("registerUrl", js.registerUrl)
-	// cinfo.Set("verify", js.verify)
-
-	admin.Set("miner", struct{}{})
-	t, _ = admin.Get("miner")
-	miner := t.Object()
-	miner.Set("start", js.startMining)
-	miner.Set("stop", js.stopMining)
-	miner.Set("hashrate", js.hashrate)
-	miner.Set("setExtra", js.setExtra)
-	miner.Set("setGasPrice", js.setGasPrice)
-	miner.Set("startAutoDAG", js.startAutoDAG)
-	miner.Set("stopAutoDAG", js.stopAutoDAG)
-	miner.Set("makeDAG", js.makeDAG)
-
-	admin.Set("txPool", struct{}{})
-	t, _ = admin.Get("txPool")
-	txPool := t.Object()
-	txPool.Set("pending", js.allPendingTransactions)
-	txPool.Set("queued", js.allQueuedTransactions)
-
-	admin.Set("debug", struct{}{})
-	t, _ = admin.Get("debug")
-	debug := t.Object()
-	js.re.Set("sleep", js.sleep)
-	debug.Set("backtrace", js.backtrace)
-	debug.Set("printBlock", js.printBlock)
-	debug.Set("dumpBlock", js.dumpBlock)
-	debug.Set("getBlockRlp", js.getBlockRlp)
-	debug.Set("setHead", js.setHead)
-	debug.Set("processBlock", js.debugBlock)
-	debug.Set("seedhash", js.seedHash)
-	debug.Set("insertBlock", js.insertBlockRlp)
-	// undocumented temporary
-	debug.Set("waitForBlocks", js.waitForBlocks)
-}
-
-// generic helper to getBlock by Number/Height or Hex depending on autodetected input
-// if argument is missing the current block is returned
-// if block is not found or there is problem with decoding
-// the appropriate value is returned and block is guaranteed to be nil
-func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
-	var block *types.Block
-	if len(call.ArgumentList) > 0 {
-		if call.Argument(0).IsNumber() {
-			num, _ := call.Argument(0).ToInteger()
-			block = js.ethereum.ChainManager().GetBlockByNumber(uint64(num))
-		} else if call.Argument(0).IsString() {
-			hash, _ := call.Argument(0).ToString()
-			block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash))
-		} else {
-			return nil, errors.New("invalid argument for dump. Either hex string or number")
-		}
-	} else {
-		block = js.ethereum.ChainManager().CurrentBlock()
-	}
-
-	if block == nil {
-		return nil, errors.New("block not found")
-	}
-	return block, nil
-}
-
-func (js *jsre) seedHash(call otto.FunctionCall) otto.Value {
-	if len(call.ArgumentList) > 0 {
-		if call.Argument(0).IsNumber() {
-			num, _ := call.Argument(0).ToInteger()
-			hash, err := ethash.GetSeedHash(uint64(num))
-			if err != nil {
-				fmt.Println(err)
-				return otto.UndefinedValue()
-			}
-			v, _ := call.Otto.ToValue(fmt.Sprintf("0x%x", hash))
-			return v
-		} else {
-			fmt.Println("arg not a number")
-		}
-	} else {
-		fmt.Println("requires number argument")
-	}
-
-	return otto.UndefinedValue()
-}
-
-func (js *jsre) allPendingTransactions(call otto.FunctionCall) otto.Value {
-	txs := js.ethereum.TxPool().GetTransactions()
-
-	ltxs := make([]*tx, len(txs))
-	for i, tx := range txs {
-		// no need to check err
-		ltxs[i] = newTx(tx)
-	}
-
-	v, _ := call.Otto.ToValue(ltxs)
-	return v
-}
-
-func (js *jsre) allQueuedTransactions(call otto.FunctionCall) otto.Value {
-	txs := js.ethereum.TxPool().GetQueuedTransactions()
-
-	ltxs := make([]*tx, len(txs))
-	for i, tx := range txs {
-		// no need to check err
-		ltxs[i] = newTx(tx)
-	}
-
-	v, _ := call.Otto.ToValue(ltxs)
-	return v
-}
-
-func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value {
-	txs := js.ethereum.TxPool().GetTransactions()
-
-	// grab the accounts from the account manager. This will help with determening which
-	// transactions should be returned.
-	accounts, err := js.ethereum.AccountManager().Accounts()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	// Add the accouns to a new set
-	accountSet := set.New()
-	for _, account := range accounts {
-		accountSet.Add(account.Address)
-	}
-
-	//ltxs := make([]*tx, len(txs))
-	var ltxs []*tx
-	for _, tx := range txs {
-		if from, _ := tx.From(); accountSet.Has(from) {
-			ltxs = append(ltxs, newTx(tx))
-		}
-	}
-
-	v, _ := call.Otto.ToValue(ltxs)
-	return v
-}
-
-func (js *jsre) resend(call otto.FunctionCall) otto.Value {
-	if len(call.ArgumentList) == 0 {
-		fmt.Println("first argument must be a transaction")
-		return otto.FalseValue()
-	}
-
-	v, err := call.Argument(0).Export()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	if tx, ok := v.(*tx); ok {
-		gl, gp := tx.GasLimit, tx.GasPrice
-		if len(call.ArgumentList) > 1 {
-			gp = call.Argument(1).String()
-		}
-		if len(call.ArgumentList) > 2 {
-			gl = call.Argument(2).String()
-		}
-
-		ret, err := js.xeth.Transact(tx.From, tx.To, tx.Nonce, tx.Value, gl, gp, tx.Data)
-		if err != nil {
-			fmt.Println(err)
-			return otto.FalseValue()
-		}
-		js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx})
-
-		v, _ := call.Otto.ToValue(ret)
-		return v
-	}
-
-	fmt.Println("first argument must be a transaction")
-	return otto.FalseValue()
-}
-
-func (js *jsre) sign(call otto.FunctionCall) otto.Value {
-	if len(call.ArgumentList) != 2 {
-		fmt.Println("requires 2 arguments: eth.sign(signer, data)")
-		return otto.UndefinedValue()
-	}
-	signer, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	data, err := call.Argument(1).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-	signed, err := js.xeth.Sign(signer, data, false)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-	v, _ := call.Otto.ToValue(signed)
-	return v
-}
-
-func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
-	block, err := js.getBlock(call)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	tstart := time.Now()
-	old := vm.Debug
-
-	if len(call.ArgumentList) > 1 {
-		vm.Debug, _ = call.Argument(1).ToBoolean()
-	}
-
-	_, err = js.ethereum.BlockProcessor().RetryProcess(block)
-	if err != nil {
-		fmt.Println(err)
-		r, _ := call.Otto.ToValue(map[string]interface{}{"success": false, "time": time.Since(tstart).Seconds()})
-		return r
-	}
-	vm.Debug = old
-
-	r, _ := call.Otto.ToValue(map[string]interface{}{"success": true, "time": time.Since(tstart).Seconds()})
-	return r
-}
-
-func (js *jsre) insertBlockRlp(call otto.FunctionCall) otto.Value {
-	tstart := time.Now()
-
-	var block types.Block
-	if call.Argument(0).IsString() {
-		blockRlp, _ := call.Argument(0).ToString()
-		err := rlp.DecodeBytes(common.Hex2Bytes(blockRlp), &block)
-		if err != nil {
-			fmt.Println(err)
-			return otto.UndefinedValue()
-		}
-	}
-
-	old := vm.Debug
-	vm.Debug = true
-	_, err := js.ethereum.BlockProcessor().RetryProcess(&block)
-	if err != nil {
-		fmt.Println(err)
-		r, _ := call.Otto.ToValue(map[string]interface{}{"success": false, "time": time.Since(tstart).Seconds()})
-		return r
-	}
-	vm.Debug = old
-
-	r, _ := call.Otto.ToValue(map[string]interface{}{"success": true, "time": time.Since(tstart).Seconds()})
-	return r
-}
-
-func (js *jsre) setHead(call otto.FunctionCall) otto.Value {
-	block, err := js.getBlock(call)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	js.ethereum.ChainManager().SetHead(block)
-	return otto.UndefinedValue()
-}
-
-func (js *jsre) syncProgress(call otto.FunctionCall) otto.Value {
-	pending, cached, importing, eta := js.ethereum.Downloader().Stats()
-	v, _ := call.Otto.ToValue(map[string]interface{}{
-		"pending":   pending,
-		"cached":    cached,
-		"importing": importing,
-		"estimate":  (eta / time.Second * time.Second).String(),
-	})
-	return v
-}
-
-func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value {
-	block, err := js.getBlock(call)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-	encoded, _ := rlp.EncodeToBytes(block)
-	v, _ := call.Otto.ToValue(fmt.Sprintf("%x", encoded))
-	return v
-}
-
-func (js *jsre) setExtra(call otto.FunctionCall) otto.Value {
-	extra, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	if len(extra) > 1024 {
-		fmt.Println("error: cannot exceed 1024 bytes")
-		return otto.UndefinedValue()
-	}
-
-	js.ethereum.Miner().SetExtra([]byte(extra))
-	return otto.UndefinedValue()
-}
-
-func (js *jsre) setGasPrice(call otto.FunctionCall) otto.Value {
-	gasPrice, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	js.ethereum.Miner().SetGasPrice(common.String2Big(gasPrice))
-	return otto.UndefinedValue()
-}
-
-func (js *jsre) hashrate(call otto.FunctionCall) otto.Value {
-	v, _ := call.Otto.ToValue(js.ethereum.Miner().HashRate())
-	return v
-}
-
-func (js *jsre) makeDAG(call otto.FunctionCall) otto.Value {
-	blockNumber, err := call.Argument(1).ToInteger()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	err = ethash.MakeDAG(uint64(blockNumber), "")
-	if err != nil {
-		return otto.FalseValue()
-	}
-	return otto.TrueValue()
-}
-
-func (js *jsre) startAutoDAG(otto.FunctionCall) otto.Value {
-	js.ethereum.StartAutoDAG()
-	return otto.TrueValue()
-}
-
-func (js *jsre) stopAutoDAG(otto.FunctionCall) otto.Value {
-	js.ethereum.StopAutoDAG()
-	return otto.TrueValue()
-}
-
-func (js *jsre) backtrace(call otto.FunctionCall) otto.Value {
-	tracestr, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-	glog.GetTraceLocation().Set(tracestr)
-
-	return otto.UndefinedValue()
-}
-
-func (js *jsre) verbosity(call otto.FunctionCall) otto.Value {
-	v, err := call.Argument(0).ToInteger()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	glog.SetV(int(v))
-	return otto.UndefinedValue()
-}
-
-func (js *jsre) startMining(call otto.FunctionCall) otto.Value {
-	var (
-		threads int64
-		err     error
-	)
-
-	if len(call.ArgumentList) > 0 {
-		threads, err = call.Argument(0).ToInteger()
-		if err != nil {
-			fmt.Println(err)
-			return otto.FalseValue()
-		}
-	} else {
-		threads = int64(js.ethereum.MinerThreads)
-	}
-
-	// switch on DAG autogeneration when miner starts
-	js.ethereum.StartAutoDAG()
-
-	err = js.ethereum.StartMining(int(threads))
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	return otto.TrueValue()
-}
-
-func (js *jsre) stopMining(call otto.FunctionCall) otto.Value {
-	js.ethereum.StopMining()
-	js.ethereum.StopAutoDAG()
-	return otto.TrueValue()
-}
-
-func (js *jsre) startRPC(call otto.FunctionCall) otto.Value {
-	addr, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	port, err := call.Argument(1).ToInteger()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	corsDomain := js.corsDomain
-	if len(call.ArgumentList) > 2 {
-		corsDomain, err = call.Argument(2).ToString()
-		if err != nil {
-			fmt.Println(err)
-			return otto.FalseValue()
-		}
-	}
-
-	config := rpc.RpcConfig{
-		ListenAddress: addr,
-		ListenPort:    uint(port),
-		CorsDomain:    corsDomain,
-	}
-
-	xeth := xeth.New(js.ethereum, nil)
-	err = rpc.Start(xeth, config)
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	return otto.TrueValue()
-}
-
-func (js *jsre) stopRPC(call otto.FunctionCall) otto.Value {
-	if rpc.Stop() == nil {
-		return otto.TrueValue()
-	}
-	return otto.FalseValue()
-}
-
-func (js *jsre) addPeer(call otto.FunctionCall) otto.Value {
-	nodeURL, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-	err = js.ethereum.AddPeer(nodeURL)
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-	return otto.TrueValue()
-}
-
-func (js *jsre) unlock(call otto.FunctionCall) otto.Value {
-	addr, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-	seconds, err := call.Argument(2).ToInteger()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-	if seconds == 0 {
-		seconds = accounts.DefaultAccountUnlockDuration
-	}
-
-	arg := call.Argument(1)
-	var passphrase string
-	if arg.IsUndefined() {
-		fmt.Println("Please enter a passphrase now.")
-		passphrase, err = utils.PromptPassword("Passphrase: ", true)
-		if err != nil {
-			fmt.Println(err)
-			return otto.FalseValue()
-		}
-	} else {
-		passphrase, err = arg.ToString()
-		if err != nil {
-			fmt.Println(err)
-			return otto.FalseValue()
-		}
-	}
-	am := js.ethereum.AccountManager()
-	err = am.TimedUnlock(common.HexToAddress(addr), passphrase, time.Duration(seconds)*time.Second)
-	if err != nil {
-		fmt.Printf("Unlock account failed '%v'\n", err)
-		return otto.FalseValue()
-	}
-	return otto.TrueValue()
-}
-
-func (js *jsre) newAccount(call otto.FunctionCall) otto.Value {
-	arg := call.Argument(0)
-	var passphrase string
-	if arg.IsUndefined() {
-		fmt.Println("The new account will be encrypted with a passphrase.")
-		fmt.Println("Please enter a passphrase now.")
-		auth, err := utils.PromptPassword("Passphrase: ", true)
-		if err != nil {
-			fmt.Println(err)
-			return otto.FalseValue()
-		}
-		confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
-		if err != nil {
-			fmt.Println(err)
-			return otto.FalseValue()
-		}
-		if auth != confirm {
-			fmt.Println("Passphrases did not match.")
-			return otto.FalseValue()
-		}
-		passphrase = auth
-	} else {
-		var err error
-		passphrase, err = arg.ToString()
-		if err != nil {
-			fmt.Println(err)
-			return otto.FalseValue()
-		}
-	}
-	acct, err := js.ethereum.AccountManager().NewAccount(passphrase)
-	if err != nil {
-		fmt.Printf("Could not create the account: %v", err)
-		return otto.UndefinedValue()
-	}
-	v, _ := call.Otto.ToValue(acct.Address.Hex())
-	return v
-}
-
-func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value {
-	v, _ := call.Otto.ToValue(js.ethereum.NodeInfo())
-	return v
-}
-
-func (js *jsre) peers(call otto.FunctionCall) otto.Value {
-	v, _ := call.Otto.ToValue(js.ethereum.PeersInfo())
-	return v
-}
-
-func (js *jsre) importChain(call otto.FunctionCall) otto.Value {
-	if len(call.ArgumentList) == 0 {
-		fmt.Println("require file name. admin.importChain(filename)")
-		return otto.FalseValue()
-	}
-	fn, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-	if err := utils.ImportChain(js.ethereum.ChainManager(), fn); err != nil {
-		fmt.Println("Import error: ", err)
-		return otto.FalseValue()
-	}
-	return otto.TrueValue()
-}
-
-func (js *jsre) exportChain(call otto.FunctionCall) otto.Value {
-	if len(call.ArgumentList) == 0 {
-		fmt.Println("require file name: admin.exportChain(filename)")
-		return otto.FalseValue()
-	}
-
-	fn, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-	if err := utils.ExportChain(js.ethereum.ChainManager(), fn); err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-	return otto.TrueValue()
-}
-
-func (js *jsre) printBlock(call otto.FunctionCall) otto.Value {
-	block, err := js.getBlock(call)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	fmt.Println(block)
-
-	return otto.UndefinedValue()
-}
-
-func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
-	block, err := js.getBlock(call)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	statedb := state.New(block.Root(), js.ethereum.StateDb())
-	dump := statedb.RawDump()
-	v, _ := call.Otto.ToValue(dump)
-	return v
-}
-
-func (js *jsre) waitForBlocks(call otto.FunctionCall) otto.Value {
-	if len(call.ArgumentList) > 2 {
-		fmt.Println("requires 0, 1 or 2 arguments: admin.debug.waitForBlock(minHeight, timeout)")
-		return otto.FalseValue()
-	}
-	var n, timeout int64
-	var timer <-chan time.Time
-	var height *big.Int
-	var err error
-	args := len(call.ArgumentList)
-	if args == 2 {
-		timeout, err = call.Argument(1).ToInteger()
-		if err != nil {
-			fmt.Println(err)
-			return otto.UndefinedValue()
-		}
-		timer = time.NewTimer(time.Duration(timeout) * time.Second).C
-	}
-	if args >= 1 {
-		n, err = call.Argument(0).ToInteger()
-		if err != nil {
-			fmt.Println(err)
-			return otto.UndefinedValue()
-		}
-		height = big.NewInt(n)
-	}
-
-	if args == 0 {
-		height = js.xeth.CurrentBlock().Number()
-		height.Add(height, common.Big1)
-	}
-
-	wait := js.wait
-	js.wait <- height
-	select {
-	case <-timer:
-		// if times out make sure the xeth loop does not block
-		go func() {
-			select {
-			case wait <- nil:
-			case <-wait:
-			}
-		}()
-		return otto.UndefinedValue()
-	case height = <-wait:
-	}
-	v, _ := call.Otto.ToValue(height.Uint64())
-	return v
-}
-
-func (js *jsre) sleep(call otto.FunctionCall) otto.Value {
-	sec, err := call.Argument(0).ToInteger()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-	time.Sleep(time.Duration(sec) * time.Second)
-	return otto.UndefinedValue()
-}
-
-func (js *jsre) setSolc(call otto.FunctionCall) otto.Value {
-	if len(call.ArgumentList) != 1 {
-		fmt.Println("needs 1 argument: admin.contractInfo.setSolc(solcPath)")
-		return otto.FalseValue()
-	}
-	solcPath, err := call.Argument(0).ToString()
-	if err != nil {
-		return otto.FalseValue()
-	}
-	solc, err := js.xeth.SetSolc(solcPath)
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-	fmt.Println(solc.Info())
-	return otto.TrueValue()
-}
-
-func (js *jsre) register(call otto.FunctionCall) otto.Value {
-	if len(call.ArgumentList) != 4 {
-		fmt.Println("requires 4 arguments: admin.contractInfo.register(fromaddress, contractaddress, contract, filename)")
-		return otto.UndefinedValue()
-	}
-	sender, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	address, err := call.Argument(1).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	raw, err := call.Argument(2).Export()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-	jsonraw, err := json.Marshal(raw)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-	var contract compiler.Contract
-	err = json.Unmarshal(jsonraw, &contract)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	filename, err := call.Argument(3).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	contenthash, err := compiler.ExtractInfo(&contract, filename)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-	// sender and contract address are passed as hex strings
-	codeb := js.xeth.CodeAtBytes(address)
-	codehash := common.BytesToHash(crypto.Sha3(codeb))
-
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	registry := resolver.New(js.xeth)
-
-	_, err = registry.RegisterContentHash(common.HexToAddress(sender), codehash, contenthash)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-
-	v, _ := call.Otto.ToValue(contenthash.Hex())
-	return v
-}
-
-func (js *jsre) registerUrl(call otto.FunctionCall) otto.Value {
-	if len(call.ArgumentList) != 3 {
-		fmt.Println("requires 3 arguments: admin.contractInfo.register(fromaddress, contenthash, filename)")
-		return otto.FalseValue()
-	}
-	sender, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	contenthash, err := call.Argument(1).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	url, err := call.Argument(2).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	registry := resolver.New(js.xeth)
-
-	_, err = registry.RegisterUrl(common.HexToAddress(sender), common.HexToHash(contenthash), url)
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	return otto.TrueValue()
-}
-
-func (js *jsre) getContractInfo(call otto.FunctionCall) otto.Value {
-	if len(call.ArgumentList) != 1 {
-		fmt.Println("requires 1 argument: admin.contractInfo.register(contractaddress)")
-		return otto.FalseValue()
-	}
-	addr, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	infoDoc, err := natspec.FetchDocsForContract(addr, js.xeth, ds)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-	var info compiler.ContractInfo
-	err = json.Unmarshal(infoDoc, &info)
-	if err != nil {
-		fmt.Println(err)
-		return otto.UndefinedValue()
-	}
-	v, _ := call.Otto.ToValue(info)
-	return v
-}
-
-func (js *jsre) startNatSpec(call otto.FunctionCall) otto.Value {
-	js.ethereum.NatSpec = true
-	return otto.TrueValue()
-}
-
-func (js *jsre) stopNatSpec(call otto.FunctionCall) otto.Value {
-	js.ethereum.NatSpec = false
-	return otto.TrueValue()
-}
-
-func (js *jsre) newRegistry(call otto.FunctionCall) otto.Value {
-
-	if len(call.ArgumentList) != 1 {
-		fmt.Println("requires 1 argument: admin.contractInfo.newRegistry(adminaddress)")
-		return otto.FalseValue()
-	}
-	addr, err := call.Argument(0).ToString()
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	registry := resolver.New(js.xeth)
-	err = registry.CreateContracts(common.HexToAddress(addr))
-	if err != nil {
-		fmt.Println(err)
-		return otto.FalseValue()
-	}
-
-	return otto.TrueValue()
-}
-
-// internal transaction type which will allow us to resend transactions  using `eth.resend`
-type tx struct {
-	tx *types.Transaction
-
-	To       string
-	From     string
-	Nonce    string
-	Value    string
-	Data     string
-	GasLimit string
-	GasPrice string
-}
-
-func newTx(t *types.Transaction) *tx {
-	from, _ := t.From()
-	var to string
-	if t := t.To(); t != nil {
-		to = t.Hex()
-	}
-
-	return &tx{
-		tx:       t,
-		To:       to,
-		From:     from.Hex(),
-		Value:    t.Amount.String(),
-		Nonce:    strconv.Itoa(int(t.Nonce())),
-		Data:     "0x" + common.Bytes2Hex(t.Data()),
-		GasLimit: t.GasLimit.String(),
-		GasPrice: t.GasPrice().String(),
-	}
-}

+ 186 - 3
cmd/geth/js.go

@@ -33,6 +33,10 @@ import (
 	"github.com/ethereum/go-ethereum/eth"
 	re "github.com/ethereum/go-ethereum/jsre"
 	"github.com/ethereum/go-ethereum/rpc"
+	"github.com/ethereum/go-ethereum/rpc/api"
+	"github.com/ethereum/go-ethereum/rpc/codec"
+	"github.com/ethereum/go-ethereum/rpc/comms"
+	"github.com/ethereum/go-ethereum/rpc/shared"
 	"github.com/ethereum/go-ethereum/xeth"
 	"github.com/peterh/liner"
 	"github.com/robertkrimen/otto"
@@ -70,10 +74,70 @@ type jsre struct {
 	ps1        string
 	atexit     func()
 	corsDomain string
+	client     comms.EthereumClient
 	prompter
 }
 
-func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain, ipcpath string, interactive bool, f xeth.Frontend) *jsre {
+var (
+	loadedModulesMethods map[string][]string
+)
+
+func keywordCompleter(line string) []string {
+	results := make([]string, 0)
+
+	if strings.Contains(line, ".") {
+		elements := strings.Split(line, ".")
+		if len(elements) == 2 {
+			module := elements[0]
+			partialMethod := elements[1]
+			if methods, found := loadedModulesMethods[module]; found {
+				for _, method := range methods {
+					if strings.HasPrefix(method, partialMethod) { // e.g. debug.se
+						results = append(results, module+"."+method)
+					}
+				}
+			}
+		}
+	} else {
+		for module, methods := range loadedModulesMethods {
+			if line == module { // user typed in full module name, show all methods
+				for _, method := range methods {
+					results = append(results, module+"."+method)
+				}
+			} else if strings.HasPrefix(module, line) { // partial method name, e.g. admi
+				results = append(results, module)
+			}
+		}
+	}
+	return results
+}
+
+func apiWordCompleter(line string, pos int) (head string, completions []string, tail string) {
+	if len(line) == 0 {
+		return "", nil, ""
+	}
+
+	i := 0
+	for i = pos - 1; i > 0; i-- {
+		if line[i] == '.' || (line[i] >= 'a' && line[i] <= 'z') || (line[i] >= 'A' && line[i] <= 'Z') {
+			continue
+		}
+		if i >= 3 && line[i] == '3' && line[i-3] == 'w' && line[i-2] == 'e' && line[i-1] == 'b' {
+			continue
+		}
+		i += 1
+		break
+	}
+
+	begin := line[:i]
+	keyword := line[i:pos]
+	end := line[pos:]
+
+	completionWords := keywordCompleter(keyword)
+	return begin, completionWords, end
+}
+
+func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, client comms.EthereumClient, interactive bool, f xeth.Frontend) *jsre {
 	js := &jsre{ethereum: ethereum, ps1: "> "}
 	// set default cors domain used by startRpc from CLI flag
 	js.corsDomain = corsDomain
@@ -82,10 +146,16 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain, ipcpath string, intera
 	}
 	js.xeth = xeth.New(ethereum, f)
 	js.wait = js.xeth.UpdateState()
+	js.client = client
+	if clt, ok := js.client.(*comms.InProcClient); ok {
+		clt.Initialize(js.xeth, ethereum)
+	}
+
 	// update state in separare forever blocks
 	js.re = re.New(libPath)
-	js.apiBindings(ipcpath, f)
-	js.adminBindings()
+	if err := js.apiBindings(f); err != nil {
+		utils.Fatalf("Unable to connect - %v", err)
+	}
 
 	if !liner.TerminalSupported() || !interactive {
 		js.prompter = dumbterm{bufio.NewReader(os.Stdin)}
@@ -93,6 +163,9 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain, ipcpath string, intera
 		lr := liner.NewLiner()
 		js.withHistory(func(hist *os.File) { lr.ReadHistory(hist) })
 		lr.SetCtrlCAborts(true)
+		js.loadAutoCompletion()
+		lr.SetWordCompleter(apiWordCompleter)
+		lr.SetTabCompletionStyle(liner.TabPrints)
 		js.prompter = lr
 		js.atexit = func() {
 			js.withHistory(func(hist *os.File) { hist.Truncate(0); lr.WriteHistory(hist) })
@@ -103,8 +176,117 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain, ipcpath string, intera
 	return js
 }
 
+func (self *jsre) loadAutoCompletion() {
+	if modules, err := self.suportedApis(); err == nil {
+		loadedModulesMethods = make(map[string][]string)
+		for module, _ := range modules {
+			loadedModulesMethods[module] = api.AutoCompletion[module]
+		}
+	}
+}
+
+func (self *jsre) suportedApis() (map[string]string, error) {
+	req := shared.Request{
+		Id:      1,
+		Jsonrpc: "2.0",
+		Method:  "modules",
+	}
+
+	err := self.client.Send(&req)
+	if err != nil {
+		return nil, err
+	}
+
+	res, err := self.client.Recv()
+	if err != nil {
+		return nil, err
+	}
+
+	if sucRes, ok := res.(map[string]string); ok {
+		if err == nil {
+			return sucRes, nil
+		}
+	}
+
+	return nil, fmt.Errorf("Unable to determine supported API's")
+}
+
+func (js *jsre) apiBindings(f xeth.Frontend) error {
+	apis, err := js.suportedApis()
+	if err != nil {
+		return err
+	}
+
+	apiNames := make([]string, 0, len(apis))
+	for a, _ := range apis {
+		apiNames = append(apiNames, a)
+	}
+
+	apiImpl, err := api.ParseApiString(strings.Join(apiNames, ","), codec.JSON, js.xeth, js.ethereum)
+	if err != nil {
+		utils.Fatalf("Unable to determine supported api's: %v", err)
+	}
+
+	jeth := rpc.NewJeth(api.Merge(apiImpl...), js.re, js.client)
+	js.re.Set("jeth", struct{}{})
+	t, _ := js.re.Get("jeth")
+	jethObj := t.Object()
+
+	jethObj.Set("send", jeth.Send)
+	jethObj.Set("sendAsync", jeth.Send)
+
+	err = js.re.Compile("bignumber.js", re.BigNumber_JS)
+	if err != nil {
+		utils.Fatalf("Error loading bignumber.js: %v", err)
+	}
+
+	err = js.re.Compile("ethereum.js", re.Web3_JS)
+	if err != nil {
+		utils.Fatalf("Error loading web3.js: %v", err)
+	}
+
+	_, err = js.re.Eval("var web3 = require('web3');")
+	if err != nil {
+		utils.Fatalf("Error requiring web3: %v", err)
+	}
+
+	_, err = js.re.Eval("web3.setProvider(jeth)")
+	if err != nil {
+		utils.Fatalf("Error setting web3 provider: %v", err)
+	}
+
+	// load only supported API's in javascript runtime
+	shortcuts := "var eth = web3.eth; "
+	for _, apiName := range apiNames {
+		if apiName == api.Web3ApiName || apiName == api.EthApiName {
+			continue // manually mapped
+		}
+
+		if err = js.re.Compile(fmt.Sprintf("%s.js", apiName), api.Javascript(apiName)); err == nil {
+			shortcuts += fmt.Sprintf("var %s = web3.%s; ", apiName, apiName)
+		} else {
+			utils.Fatalf("Error loading %s.js: %v", apiName, err)
+		}
+	}
+
+	_, err = js.re.Eval(shortcuts)
+
+	if err != nil {
+		utils.Fatalf("Error setting namespaces: %v", err)
+	}
+
+	js.re.Eval(globalRegistrar + "registrar = GlobalRegistrar.at(\"" + globalRegistrarAddr + "\");")
+	return nil
+}
+
+/*
 func (js *jsre) apiBindings(ipcpath string, f xeth.Frontend) {
 	xe := xeth.New(js.ethereum, f)
+	apiNames, err := js.suportedApis(ipcpath)
+	if err != nil {
+		return
+	}
+
 	ethApi := rpc.NewEthereumApi(xe)
 	jeth := rpc.NewJeth(ethApi, js.re, ipcpath)
 
@@ -146,6 +328,7 @@ var net = web3.net;
 
 	js.re.Eval(globalRegistrar + "registrar = GlobalRegistrar.at(\"" + globalRegistrarAddr + "\");")
 }
+*/
 
 var ds, _ = docserver.New("/")
 

+ 7 - 2
cmd/geth/main.go

@@ -38,6 +38,8 @@ import (
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/eth"
 	"github.com/ethereum/go-ethereum/logger"
+	"github.com/ethereum/go-ethereum/rpc/codec"
+	"github.com/ethereum/go-ethereum/rpc/comms"
 	"github.com/mattn/go-colorable"
 	"github.com/mattn/go-isatty"
 )
@@ -310,12 +312,14 @@ func console(ctx *cli.Context) {
 		utils.Fatalf("%v", err)
 	}
 
+	client := comms.NewInProcClient(codec.JSON)
+
 	startEth(ctx, ethereum)
 	repl := newJSRE(
 		ethereum,
 		ctx.String(utils.JSpathFlag.Name),
 		ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
-		utils.IpcSocketPath(ctx),
+		client,
 		true,
 		nil,
 	)
@@ -332,12 +336,13 @@ func execJSFiles(ctx *cli.Context) {
 		utils.Fatalf("%v", err)
 	}
 
+	client := comms.NewInProcClient(codec.JSON)
 	startEth(ctx, ethereum)
 	repl := newJSRE(
 		ethereum,
 		ctx.String(utils.JSpathFlag.Name),
 		ctx.GlobalString(utils.RPCCORSDomainFlag.Name),
-		utils.IpcSocketPath(ctx),
+		client,
 		false,
 		nil,
 	)

+ 2 - 2
cmd/utils/flags.go

@@ -211,7 +211,7 @@ var (
 	RpcApiFlag = cli.StringFlag{
 		Name:  "rpcapi",
 		Usage: "Specify the API's which are offered over the HTTP RPC interface",
-		Value: api.DefaultHttpRpcApis,
+		Value: comms.DefaultHttpRpcApis,
 	}
 	IPCDisabledFlag = cli.BoolFlag{
 		Name:  "ipcdisable",
@@ -220,7 +220,7 @@ var (
 	IPCApiFlag = cli.StringFlag{
 		Name:  "ipcapi",
 		Usage: "Specify the API's which are offered over the IPC interface",
-		Value: api.DefaultIpcApis,
+		Value: comms.DefaultIpcApis,
 	}
 	IPCPathFlag = DirectoryFlag{
 		Name:  "ipcpath",

+ 1 - 1
core/transaction_pool.go

@@ -149,7 +149,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
 		return ErrInvalidSender
 	}
 
-	// Make sure the account exist. Non existant accounts
+	// Make sure the account exist. Non existent accounts
 	// haven't got funds and well therefor never pass.
 	if !pool.currentState().HasAccount(from) {
 		return ErrNonExistentAccount

+ 0 - 646
rpc/api.go

@@ -1,646 +0,0 @@
-package rpc
-
-import (
-	"bytes"
-	"encoding/json"
-	"math/big"
-
-	"github.com/ethereum/go-ethereum/common"
-	"github.com/ethereum/go-ethereum/core/vm"
-	"github.com/ethereum/go-ethereum/crypto"
-	"github.com/ethereum/go-ethereum/logger"
-	"github.com/ethereum/go-ethereum/logger/glog"
-	"github.com/ethereum/go-ethereum/xeth"
-)
-
-type EthereumApi struct {
-	eth *xeth.XEth
-}
-
-func NewEthereumApi(xeth *xeth.XEth) *EthereumApi {
-	api := &EthereumApi{
-		eth: xeth,
-	}
-
-	return api
-}
-
-func (api *EthereumApi) xeth() *xeth.XEth {
-	return api.eth
-}
-
-func (api *EthereumApi) xethAtStateNum(num int64) *xeth.XEth {
-	return api.xeth().AtStateNum(num)
-}
-
-func (api *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error {
-	// Spec at https://github.com/ethereum/wiki/wiki/JSON-RPC
-	glog.V(logger.Debug).Infof("%s %s", req.Method, req.Params)
-
-	switch req.Method {
-	case "web3_sha3":
-		args := new(Sha3Args)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		*reply = common.ToHex(crypto.Sha3(common.FromHex(args.Data)))
-	case "web3_clientVersion":
-		*reply = api.xeth().ClientVersion()
-	case "net_version":
-		*reply = api.xeth().NetworkVersion()
-	case "net_listening":
-		*reply = api.xeth().IsListening()
-	case "net_peerCount":
-		*reply = newHexNum(api.xeth().PeerCount())
-	case "eth_protocolVersion":
-		*reply = api.xeth().EthVersion()
-	case "eth_coinbase":
-		*reply = newHexData(api.xeth().Coinbase())
-	case "eth_mining":
-		*reply = api.xeth().IsMining()
-	case "eth_gasPrice":
-		v := api.xeth().DefaultGasPrice()
-		*reply = newHexNum(v.Bytes())
-	case "eth_accounts":
-		*reply = api.xeth().Accounts()
-	case "eth_blockNumber":
-		v := api.xeth().CurrentBlock().Number()
-		*reply = newHexNum(v.Bytes())
-	case "eth_getBalance":
-		args := new(GetBalanceArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		*reply = api.xethAtStateNum(args.BlockNumber).BalanceAt(args.Address)
-		//v := api.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
-		}
-
-		*reply = api.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
-		}
-
-		*reply = api.xethAtStateNum(args.BlockNumber).StorageAt(args.Address, args.Key)
-	case "eth_getTransactionCount":
-		args := new(GetTxCountArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		count := api.xethAtStateNum(args.BlockNumber).TxCountAt(args.Address)
-		*reply = newHexNum(big.NewInt(int64(count)).Bytes())
-	case "eth_getBlockTransactionCountByHash":
-		args := new(HashArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		block := NewBlockRes(api.xeth().EthBlockByHash(args.Hash), false)
-		if block == nil {
-			*reply = nil
-		} else {
-			*reply = newHexNum(big.NewInt(int64(len(block.Transactions))).Bytes())
-		}
-	case "eth_getBlockTransactionCountByNumber":
-		args := new(BlockNumArg)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		block := NewBlockRes(api.xeth().EthBlockByNumber(args.BlockNumber), false)
-		if block == nil {
-			*reply = nil
-			break
-		}
-
-		*reply = newHexNum(big.NewInt(int64(len(block.Transactions))).Bytes())
-	case "eth_getUncleCountByBlockHash":
-		args := new(HashArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		block := api.xeth().EthBlockByHash(args.Hash)
-		br := NewBlockRes(block, false)
-		if br == nil {
-			*reply = nil
-			break
-		}
-
-		*reply = newHexNum(big.NewInt(int64(len(br.Uncles))).Bytes())
-	case "eth_getUncleCountByBlockNumber":
-		args := new(BlockNumArg)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		block := api.xeth().EthBlockByNumber(args.BlockNumber)
-		br := NewBlockRes(block, false)
-		if br == nil {
-			*reply = nil
-			break
-		}
-
-		*reply = newHexNum(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
-		}
-		v := api.xethAtStateNum(args.BlockNumber).CodeAtBytes(args.Address)
-		*reply = newHexData(v)
-
-	case "eth_sign":
-		args := new(NewSigArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		v, err := api.xeth().Sign(args.From, args.Data, false)
-		if err != nil {
-			return err
-		}
-		*reply = v
-
-	case "eth_sendRawTransaction":
-		args := new(NewDataArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		v, err := api.xeth().PushTx(args.Data)
-		if err != nil {
-			return err
-		}
-		*reply = v
-
-	case "eth_sendTransaction", "eth_transact":
-		args := new(NewTxArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		// nonce may be nil ("guess" mode)
-		var nonce string
-		if args.Nonce != nil {
-			nonce = args.Nonce.String()
-		}
-
-		var gas string
-		if args.Gas == nil {
-			gas = ""
-		} else {
-			gas = args.Gas.String()
-		}
-
-		var gasprice string
-		if args.GasPrice == nil {
-			gasprice = ""
-		} else {
-			gasprice = args.GasPrice.String()
-		}
-
-		v, err := api.xeth().Transact(args.From, args.To, nonce, args.Value.String(), gas, gasprice, args.Data)
-		if err != nil {
-			return err
-		}
-		*reply = v
-	case "eth_estimateGas":
-		_, gas, err := api.doCall(req.Params)
-		if err != nil {
-			return err
-		}
-
-		// TODO unwrap the parent method's ToHex call
-		if len(gas) == 0 {
-			*reply = newHexNum(0)
-		} else {
-			*reply = newHexNum(gas)
-		}
-	case "eth_call":
-		v, _, err := api.doCall(req.Params)
-		if err != nil {
-			return err
-		}
-
-		// TODO unwrap the parent method's ToHex call
-		if v == "0x0" {
-			*reply = newHexData([]byte{})
-		} else {
-			*reply = newHexData(common.FromHex(v))
-		}
-	case "eth_flush":
-		return NewNotImplementedError(req.Method)
-	case "eth_getBlockByHash":
-		args := new(GetBlockByHashArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		block := api.xeth().EthBlockByHash(args.BlockHash)
-		br := NewBlockRes(block, args.IncludeTxs)
-
-		*reply = br
-	case "eth_getBlockByNumber":
-		args := new(GetBlockByNumberArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		block := api.xeth().EthBlockByNumber(args.BlockNumber)
-		br := NewBlockRes(block, args.IncludeTxs)
-		// If request was for "pending", nil nonsensical fields
-		if args.BlockNumber == -2 {
-			br.BlockHash = nil
-			br.BlockNumber = nil
-			br.Miner = nil
-			br.Nonce = nil
-			br.LogsBloom = nil
-		}
-		*reply = br
-	case "eth_getTransactionByHash":
-		args := new(HashArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		tx, bhash, bnum, txi := api.xeth().EthTransactionByHash(args.Hash)
-		if tx != nil {
-			v := NewTransactionRes(tx)
-			// if the blockhash is 0, assume this is a pending transaction
-			if bytes.Compare(bhash.Bytes(), bytes.Repeat([]byte{0}, 32)) != 0 {
-				v.BlockHash = newHexData(bhash)
-				v.BlockNumber = newHexNum(bnum)
-				v.TxIndex = newHexNum(txi)
-			}
-			*reply = v
-		}
-	case "eth_getTransactionByBlockHashAndIndex":
-		args := new(HashIndexArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		block := api.xeth().EthBlockByHash(args.Hash)
-		br := NewBlockRes(block, true)
-		if br == nil {
-			*reply = nil
-			break
-		}
-
-		if args.Index >= int64(len(br.Transactions)) || args.Index < 0 {
-			// return NewValidationError("Index", "does not exist")
-			*reply = nil
-		} else {
-			*reply = br.Transactions[args.Index]
-		}
-	case "eth_getTransactionByBlockNumberAndIndex":
-		args := new(BlockNumIndexArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		block := api.xeth().EthBlockByNumber(args.BlockNumber)
-		v := NewBlockRes(block, true)
-		if v == nil {
-			*reply = nil
-			break
-		}
-
-		if args.Index >= int64(len(v.Transactions)) || args.Index < 0 {
-			// return NewValidationError("Index", "does not exist")
-			*reply = nil
-		} else {
-			*reply = v.Transactions[args.Index]
-		}
-	case "eth_getUncleByBlockHashAndIndex":
-		args := new(HashIndexArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		br := NewBlockRes(api.xeth().EthBlockByHash(args.Hash), false)
-		if br == nil {
-			*reply = nil
-			return nil
-		}
-
-		if args.Index >= int64(len(br.Uncles)) || args.Index < 0 {
-			// return NewValidationError("Index", "does not exist")
-			*reply = nil
-		} else {
-			*reply = br.Uncles[args.Index]
-		}
-	case "eth_getUncleByBlockNumberAndIndex":
-		args := new(BlockNumIndexArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		block := api.xeth().EthBlockByNumber(args.BlockNumber)
-		v := NewBlockRes(block, true)
-
-		if v == nil {
-			*reply = nil
-			return nil
-		}
-
-		if args.Index >= int64(len(v.Uncles)) || args.Index < 0 {
-			// return NewValidationError("Index", "does not exist")
-			*reply = nil
-		} else {
-			*reply = v.Uncles[args.Index]
-		}
-
-	case "eth_getCompilers":
-		var lang string
-		if solc, _ := api.xeth().Solc(); solc != nil {
-			lang = "Solidity"
-		}
-		c := []string{lang}
-		*reply = c
-
-	case "eth_compileLLL", "eth_compileSerpent":
-		return NewNotImplementedError(req.Method)
-
-	case "eth_compileSolidity":
-		solc, _ := api.xeth().Solc()
-		if solc == nil {
-			return NewNotAvailableError(req.Method, "solc (solidity compiler) not found")
-		}
-
-		args := new(SourceArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		contracts, err := solc.Compile(args.Source)
-		if err != nil {
-			return err
-		}
-		*reply = contracts
-
-	case "eth_newFilter":
-		args := new(BlockFilterArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		id := api.xeth().NewLogFilter(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics)
-		*reply = newHexNum(big.NewInt(int64(id)).Bytes())
-
-	case "eth_newBlockFilter":
-		*reply = newHexNum(api.xeth().NewBlockFilter())
-	case "eth_newPendingTransactionFilter":
-		*reply = newHexNum(api.xeth().NewTransactionFilter())
-	case "eth_uninstallFilter":
-		args := new(FilterIdArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		*reply = api.xeth().UninstallFilter(args.Id)
-	case "eth_getFilterChanges":
-		args := new(FilterIdArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		switch api.xeth().GetFilterType(args.Id) {
-		case xeth.BlockFilterTy:
-			*reply = NewHashesRes(api.xeth().BlockFilterChanged(args.Id))
-		case xeth.TransactionFilterTy:
-			*reply = NewHashesRes(api.xeth().TransactionFilterChanged(args.Id))
-		case xeth.LogFilterTy:
-			*reply = NewLogsRes(api.xeth().LogFilterChanged(args.Id))
-		default:
-			*reply = []string{} // reply empty string slice
-		}
-	case "eth_getFilterLogs":
-		args := new(FilterIdArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		*reply = NewLogsRes(api.xeth().Logs(args.Id))
-	case "eth_getLogs":
-		args := new(BlockFilterArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		*reply = NewLogsRes(api.xeth().AllLogs(args.Earliest, args.Latest, args.Skip, args.Max, args.Address, args.Topics))
-	case "eth_getWork":
-		api.xeth().SetMining(true, 0)
-		*reply = api.xeth().RemoteMining().GetWork()
-	case "eth_submitWork":
-		args := new(SubmitWorkArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		*reply = api.xeth().RemoteMining().SubmitWork(args.Nonce, common.HexToHash(args.Digest), common.HexToHash(args.Header))
-	case "db_putString":
-		args := new(DbArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		if err := args.requirements(); err != nil {
-			return err
-		}
-
-		api.xeth().DbPut([]byte(args.Database+args.Key), args.Value)
-
-		*reply = true
-	case "db_getString":
-		args := new(DbArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		if err := args.requirements(); err != nil {
-			return err
-		}
-
-		res, _ := api.xeth().DbGet([]byte(args.Database + args.Key))
-		*reply = string(res)
-	case "db_putHex":
-		args := new(DbHexArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		if err := args.requirements(); err != nil {
-			return err
-		}
-
-		api.xeth().DbPut([]byte(args.Database+args.Key), args.Value)
-		*reply = true
-	case "db_getHex":
-		args := new(DbHexArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		if err := args.requirements(); err != nil {
-			return err
-		}
-
-		res, _ := api.xeth().DbGet([]byte(args.Database + args.Key))
-		*reply = newHexData(res)
-
-	case "shh_version":
-		// Short circuit if whisper is not running
-		if api.xeth().Whisper() == nil {
-			return NewNotAvailableError(req.Method, "whisper offline")
-		}
-		// Retrieves the currently running whisper protocol version
-		*reply = api.xeth().WhisperVersion()
-
-	case "shh_post":
-		// Short circuit if whisper is not running
-		if api.xeth().Whisper() == nil {
-			return NewNotAvailableError(req.Method, "whisper offline")
-		}
-		// Injects a new message into the whisper network
-		args := new(WhisperMessageArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		err := api.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":
-		// Short circuit if whisper is not running
-		if api.xeth().Whisper() == nil {
-			return NewNotAvailableError(req.Method, "whisper offline")
-		}
-		// Creates a new whisper identity to use for sending/receiving messages
-		*reply = api.xeth().Whisper().NewIdentity()
-
-	case "shh_hasIdentity":
-		// Short circuit if whisper is not running
-		if api.xeth().Whisper() == nil {
-			return NewNotAvailableError(req.Method, "whisper offline")
-		}
-		// Checks if an identity if owned or not
-		args := new(WhisperIdentityArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		*reply = api.xeth().Whisper().HasIdentity(args.Identity)
-
-	case "shh_newFilter":
-		// Short circuit if whisper is not running
-		if api.xeth().Whisper() == nil {
-			return NewNotAvailableError(req.Method, "whisper offline")
-		}
-		// Create a new filter to watch and match messages with
-		args := new(WhisperFilterArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		id := api.xeth().NewWhisperFilter(args.To, args.From, args.Topics)
-		*reply = newHexNum(big.NewInt(int64(id)).Bytes())
-
-	case "shh_uninstallFilter":
-		// Short circuit if whisper is not running
-		if api.xeth().Whisper() == nil {
-			return NewNotAvailableError(req.Method, "whisper offline")
-		}
-		// Remove an existing filter watching messages
-		args := new(FilterIdArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		*reply = api.xeth().UninstallWhisperFilter(args.Id)
-
-	case "shh_getFilterChanges":
-		// Short circuit if whisper is not running
-		if api.xeth().Whisper() == nil {
-			return NewNotAvailableError(req.Method, "whisper offline")
-		}
-		// Retrieve all the new messages arrived since the last request
-		args := new(FilterIdArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		*reply = api.xeth().WhisperMessagesChanged(args.Id)
-
-	case "shh_getMessages":
-		// Short circuit if whisper is not running
-		if api.xeth().Whisper() == nil {
-			return NewNotAvailableError(req.Method, "whisper offline")
-		}
-		// Retrieve all the cached messages matching a specific, existing filter
-		args := new(FilterIdArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-		*reply = api.xeth().WhisperMessages(args.Id)
-
-	case "eth_hashrate":
-		*reply = newHexNum(api.xeth().HashRate())
-	case "ext_disasm":
-		args := new(SourceArgs)
-		if err := json.Unmarshal(req.Params, &args); err != nil {
-			return err
-		}
-
-		*reply = vm.Disasm(common.FromHex(args.Source))
-
-	// case "eth_register":
-	// 	// Placeholder for actual type
-	// 	args := new(HashIndexArgs)
-	// 	if err := json.Unmarshal(req.Params, &args); err != nil {
-	// 		return err
-	// 	}
-	// 	*reply = api.xeth().Register(args.Hash)
-	// case "eth_unregister":
-	// 	args := new(HashIndexArgs)
-	// 	if err := json.Unmarshal(req.Params, &args); err != nil {
-	// 		return err
-	// 	}
-	// 	*reply = api.xeth().Unregister(args.Hash)
-	// case "eth_watchTx":
-	// 	args := new(HashIndexArgs)
-	// 	if err := json.Unmarshal(req.Params, &args); err != nil {
-	// 		return err
-	// 	}
-	// 	*reply = api.xeth().PullWatchTx(args.Hash)
-	default:
-		return NewNotImplementedError(req.Method)
-	}
-
-	// glog.V(logger.Detail).Infof("Reply: %v\n", reply)
-	return nil
-}
-
-func (api *EthereumApi) doCall(params json.RawMessage) (string, string, error) {
-	args := new(CallArgs)
-	if err := json.Unmarshal(params, &args); err != nil {
-		return "", "", err
-	}
-
-	var gas string
-	if args.Gas == nil {
-		gas = ""
-	} else {
-		gas = args.Gas.String()
-	}
-
-	var gasprice string
-	if args.GasPrice == nil {
-		gasprice = ""
-	} else {
-		gasprice = args.GasPrice.String()
-	}
-
-	return api.xethAtStateNum(args.BlockNumber).Call(args.From, args.To, args.Value.String(), gas, gasprice, args.Data)
-}

+ 4 - 6
rpc/api/api.go

@@ -18,15 +18,13 @@ const (
 	TxPoolApiName   = "txpool"
 	PersonalApiName = "personal"
 	Web3ApiName     = "web3"
+
+	JsonRpcVersion = "2.0"
 )
 
 var (
-	DefaultHttpRpcApis = strings.Join([]string{
-		DbApiName, EthApiName, NetApiName, Web3ApiName,
-	}, ",")
-
-	// List with all API's which are offered over the IPC interface by default
-	DefaultIpcApis = strings.Join([]string{
+	// All API's
+	AllApis = strings.Join([]string{
 		AdminApiName, DbApiName, EthApiName, DebugApiName, MinerApiName, NetApiName,
 		ShhApiName, TxPoolApiName, PersonalApiName, Web3ApiName,
 	}, ",")

+ 57 - 0
rpc/api/args.go

@@ -0,0 +1,57 @@
+package api
+
+import (
+	"encoding/json"
+	"github.com/ethereum/go-ethereum/rpc/shared"
+)
+
+type CompileArgs struct {
+	Source string
+}
+
+func (args *CompileArgs) UnmarshalJSON(b []byte) (err error) {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	if len(obj) < 1 {
+		return shared.NewInsufficientParamsError(len(obj), 1)
+	}
+	argstr, ok := obj[0].(string)
+	if !ok {
+		return shared.NewInvalidTypeError("arg0", "is not a string")
+	}
+	args.Source = argstr
+
+	return nil
+}
+
+type FilterStringArgs struct {
+	Word string
+}
+
+func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
+	var obj []interface{}
+	if err := json.Unmarshal(b, &obj); err != nil {
+		return shared.NewDecodeParamError(err.Error())
+	}
+
+	if len(obj) < 1 {
+		return shared.NewInsufficientParamsError(len(obj), 1)
+	}
+
+	var argstr string
+	argstr, ok := obj[0].(string)
+	if !ok {
+		return shared.NewInvalidTypeError("filter", "not a string")
+	}
+	switch argstr {
+	case "latest", "pending":
+		break
+	default:
+		return shared.NewValidationError("Word", "Must be `latest` or `pending`")
+	}
+	args.Word = argstr
+	return nil
+}

+ 6 - 5
rpc/args_test.go → rpc/api/args_test.go

@@ -1,4 +1,4 @@
-package rpc
+package api
 
 import (
 	"bytes"
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"math/big"
 	"testing"
+	"github.com/ethereum/go-ethereum/rpc/shared"
 )
 
 func TestBlockheightInvalidString(t *testing.T) {
@@ -68,7 +69,7 @@ func ExpectValidationError(err error) string {
 	switch err.(type) {
 	case nil:
 		str = "Expected error but didn't get one"
-	case *ValidationError:
+	case *shared.ValidationError:
 		break
 	default:
 		str = fmt.Sprintf("Expected *rpc.ValidationError but got %T with message `%s`", err, err.Error())
@@ -81,7 +82,7 @@ func ExpectInvalidTypeError(err error) string {
 	switch err.(type) {
 	case nil:
 		str = "Expected error but didn't get one"
-	case *InvalidTypeError:
+	case *shared.InvalidTypeError:
 		break
 	default:
 		str = fmt.Sprintf("Expected *rpc.InvalidTypeError but got %T with message `%s`", err, err.Error())
@@ -94,7 +95,7 @@ func ExpectInsufficientParamsError(err error) string {
 	switch err.(type) {
 	case nil:
 		str = "Expected error but didn't get one"
-	case *InsufficientParamsError:
+	case *shared.InsufficientParamsError:
 		break
 	default:
 		str = fmt.Sprintf("Expected *rpc.InsufficientParamsError but got %T with message %s", err, err.Error())
@@ -107,7 +108,7 @@ func ExpectDecodeParamError(err error) string {
 	switch err.(type) {
 	case nil:
 		str = "Expected error but didn't get one"
-	case *DecodeParamError:
+	case *shared.DecodeParamError:
 		break
 	default:
 		str = fmt.Sprintf("Expected *rpc.DecodeParamError but got %T with message `%s`", err, err.Error())

+ 0 - 205
rpc/api_test.go

@@ -1,205 +0,0 @@
-package rpc
-
-import (
-	"encoding/json"
-	"strconv"
-	"testing"
-
-	"github.com/ethereum/go-ethereum/common/compiler"
-	"github.com/ethereum/go-ethereum/eth"
-	"github.com/ethereum/go-ethereum/xeth"
-)
-
-func TestWeb3Sha3(t *testing.T) {
-	jsonstr := `{"jsonrpc":"2.0","method":"web3_sha3","params":["0x68656c6c6f20776f726c64"],"id":64}`
-	expected := "0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"
-
-	api := &EthereumApi{}
-
-	var req RpcRequest
-	json.Unmarshal([]byte(jsonstr), &req)
-
-	var response interface{}
-	_ = api.GetRequestReply(&req, &response)
-
-	if response.(string) != expected {
-		t.Errorf("Expected %s got %s", expected, response)
-	}
-}
-
-const solcVersion = "0.9.23"
-
-func TestCompileSolidity(t *testing.T) {
-
-	solc, err := compiler.New("")
-	if solc == nil {
-		t.Skip("no solc found: skip")
-	} else if solc.Version() != solcVersion {
-		t.Skip("WARNING: skipping test because of solc different version (%v, test written for %v, may need to update)", solc.Version(), solcVersion)
-	}
-	source := `contract test {\n` +
-		"   /// @notice Will multiply `a` by 7." + `\n` +
-		`   function multiply(uint a) returns(uint d) {\n` +
-		`       return a * 7;\n` +
-		`   }\n` +
-		`}\n`
-
-	jsonstr := `{"jsonrpc":"2.0","method":"eth_compileSolidity","params":["` + source + `"],"id":64}`
-
-	expCode := "0x605880600c6000396000f3006000357c010000000000000000000000000000000000000000000000000000000090048063c6888fa114602e57005b603d6004803590602001506047565b8060005260206000f35b60006007820290506053565b91905056"
-	expAbiDefinition := `[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}]`
-	expUserDoc := `{"methods":{"multiply(uint256)":{"notice":"Will multiply ` + "`a`" + ` by 7."}}}`
-	expDeveloperDoc := `{"methods":{}}`
-	expCompilerVersion := solc.Version()
-	expLanguage := "Solidity"
-	expLanguageVersion := "0"
-	expSource := source
-
-	api := NewEthereumApi(xeth.NewTest(&eth.Ethereum{}, nil))
-
-	var req RpcRequest
-	json.Unmarshal([]byte(jsonstr), &req)
-
-	var response interface{}
-	err = api.GetRequestReply(&req, &response)
-	if err != nil {
-		t.Errorf("expected no error, got %v", err)
-	}
-	respjson, err := json.Marshal(response)
-	if err != nil {
-		t.Errorf("expected no error, got %v", err)
-	}
-
-	var contracts = make(map[string]*compiler.Contract)
-	err = json.Unmarshal(respjson, &contracts)
-	if err != nil {
-		t.Errorf("expected no error, got %v", err)
-	}
-
-	if len(contracts) != 1 {
-		t.Errorf("expected one contract, got %v", len(contracts))
-	}
-
-	contract := contracts["test"]
-
-	if contract.Code != expCode {
-		t.Errorf("Expected \n%s got \n%s", expCode, contract.Code)
-	}
-
-	if strconv.Quote(contract.Info.Source) != `"`+expSource+`"` {
-		t.Errorf("Expected \n'%s' got \n'%s'", expSource, strconv.Quote(contract.Info.Source))
-	}
-
-	if contract.Info.Language != expLanguage {
-		t.Errorf("Expected %s got %s", expLanguage, contract.Info.Language)
-	}
-
-	if contract.Info.LanguageVersion != expLanguageVersion {
-		t.Errorf("Expected %s got %s", expLanguageVersion, contract.Info.LanguageVersion)
-	}
-
-	if contract.Info.CompilerVersion != expCompilerVersion {
-		t.Errorf("Expected %s got %s", expCompilerVersion, contract.Info.CompilerVersion)
-	}
-
-	userdoc, err := json.Marshal(contract.Info.UserDoc)
-	if err != nil {
-		t.Errorf("expected no error, got %v", err)
-	}
-
-	devdoc, err := json.Marshal(contract.Info.DeveloperDoc)
-	if err != nil {
-		t.Errorf("expected no error, got %v", err)
-	}
-
-	abidef, err := json.Marshal(contract.Info.AbiDefinition)
-	if err != nil {
-		t.Errorf("expected no error, got %v", err)
-	}
-
-	if string(abidef) != expAbiDefinition {
-		t.Errorf("Expected \n'%s' got \n'%s'", expAbiDefinition, string(abidef))
-	}
-
-	if string(userdoc) != expUserDoc {
-		t.Errorf("Expected \n'%s' got \n'%s'", expUserDoc, string(userdoc))
-	}
-
-	if string(devdoc) != expDeveloperDoc {
-		t.Errorf("Expected %s got %s", expDeveloperDoc, string(devdoc))
-	}
-}
-
-// func TestDbStr(t *testing.T) {
-// 	jsonput := `{"jsonrpc":"2.0","method":"db_putString","params":["testDB","myKey","myString"],"id":64}`
-// 	jsonget := `{"jsonrpc":"2.0","method":"db_getString","params":["testDB","myKey"],"id":64}`
-// 	expected := "myString"
-
-// 	xeth := &xeth.XEth{}
-// 	api := NewEthereumApi(xeth)
-// 	var response interface{}
-
-// 	var req RpcRequest
-// 	json.Unmarshal([]byte(jsonput), &req)
-// 	_ = api.GetRequestReply(&req, &response)
-
-// 	json.Unmarshal([]byte(jsonget), &req)
-// 	_ = api.GetRequestReply(&req, &response)
-
-// 	if response.(string) != expected {
-// 		t.Errorf("Expected %s got %s", expected, response)
-// 	}
-// }
-
-// func TestDbHexStr(t *testing.T) {
-// 	jsonput := `{"jsonrpc":"2.0","method":"db_putHex","params":["testDB","beefKey","0xbeef"],"id":64}`
-// 	jsonget := `{"jsonrpc":"2.0","method":"db_getHex","params":["testDB","beefKey"],"id":64}`
-// 	expected := "0xbeef"
-
-// 	xeth := &xeth.XEth{}
-// 	api := NewEthereumApi(xeth)
-// 	defer api.db.Close()
-// 	var response interface{}
-
-// 	var req RpcRequest
-// 	json.Unmarshal([]byte(jsonput), &req)
-// 	_ = api.GetRequestReply(&req, &response)
-
-// 	json.Unmarshal([]byte(jsonget), &req)
-// 	_ = api.GetRequestReply(&req, &response)
-
-// 	if response.(string) != expected {
-// 		t.Errorf("Expected %s got %s", expected, response)
-// 	}
-// }
-
-// 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")
-// 	}
-// }

+ 0 - 1230
rpc/args.go

@@ -1,1230 +0,0 @@
-package rpc
-
-import (
-	"encoding/json"
-	"fmt"
-	"math/big"
-
-	"github.com/ethereum/go-ethereum/common"
-)
-
-const (
-	defaultLogLimit  = 100
-	defaultLogOffset = 0
-)
-
-func blockHeightFromJson(msg json.RawMessage, number *int64) error {
-	var raw interface{}
-	if err := json.Unmarshal(msg, &raw); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-	return blockHeight(raw, number)
-}
-
-func blockHeight(raw interface{}, number *int64) error {
-	// Parse as integer
-	num, ok := raw.(float64)
-	if ok {
-		*number = int64(num)
-		return nil
-	}
-
-	// Parse as string/hexstring
-	str, ok := raw.(string)
-	if !ok {
-		return NewInvalidTypeError("", "not a number or string")
-	}
-
-	switch str {
-	case "earliest":
-		*number = 0
-	case "latest":
-		*number = -1
-	case "pending":
-		*number = -2
-	default:
-		if common.HasHexPrefix(str) {
-			*number = common.String2Big(str).Int64()
-		} else {
-			return NewInvalidTypeError("blockNumber", "is not a valid string")
-		}
-	}
-
-	return nil
-}
-
-func numString(raw interface{}) (*big.Int, error) {
-	var number *big.Int
-	// Parse as integer
-	num, ok := raw.(float64)
-	if ok {
-		number = big.NewInt(int64(num))
-		return number, nil
-	}
-
-	// Parse as string/hexstring
-	str, ok := raw.(string)
-	if ok {
-		number = common.String2Big(str)
-		return number, nil
-	}
-
-	return nil, NewInvalidTypeError("", "not a number or string")
-}
-
-// func toNumber(v interface{}) (int64, error) {
-// 	var str string
-// 	if v != nil {
-// 		var ok bool
-// 		str, ok = v.(string)
-// 		if !ok {
-// 			return 0, errors.New("is not a string or undefined")
-// 		}
-// 	} else {
-// 		str = "latest"
-// 	}
-
-// 	switch str {
-// 	case "latest":
-// 		return -1, nil
-// 	default:
-// 		return int64(common.Big(v.(string)).Int64()), nil
-// 	}
-// }
-
-// func hashString(raw interface{}, hash *string) error {
-// 	argstr, ok := raw.(string)
-// 	if !ok {
-// 		return NewInvalidTypeError("", "not a string")
-// 	}
-// 	v := common.IsHex(argstr)
-// 	hash = &argstr
-
-// 	return nil
-// }
-
-type GetBlockByHashArgs struct {
-	BlockHash  string
-	IncludeTxs bool
-}
-
-func (args *GetBlockByHashArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 2 {
-		return NewInsufficientParamsError(len(obj), 2)
-	}
-
-	argstr, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("blockHash", "not a string")
-	}
-	args.BlockHash = argstr
-
-	args.IncludeTxs = obj[1].(bool)
-
-	return nil
-}
-
-type GetBlockByNumberArgs struct {
-	BlockNumber int64
-	IncludeTxs  bool
-}
-
-func (args *GetBlockByNumberArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 2 {
-		return NewInsufficientParamsError(len(obj), 2)
-	}
-
-	if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
-		return err
-	}
-
-	args.IncludeTxs = obj[1].(bool)
-
-	return nil
-}
-
-type NewDataArgs struct {
-    Data string
-}
-
-func (args *NewDataArgs) UnmarshalJSON(b []byte) (err error) {
-    var obj []interface{}
-
-    if err := json.Unmarshal(b, &obj); err != nil {
-        return NewDecodeParamError(err.Error())
-    }
-
-    // Check for sufficient params
-    if len(obj) < 1 {
-        return NewInsufficientParamsError(len(obj), 1)
-    }
-
-    data, ok := obj[0].(string)
-    if !ok {
-        return NewInvalidTypeError("data", "not a string")
-    }
-    args.Data = data
-
-    if len(args.Data) == 0 {
-        return NewValidationError("data", "is required")
-    }
-
-    return nil
-}
-
-type NewTxArgs struct {
-	From     string
-	To       string
-	Nonce    *big.Int
-	Value    *big.Int
-	Gas      *big.Int
-	GasPrice *big.Int
-	Data     string
-
-	BlockNumber int64
-}
-
-type NewSigArgs struct {
-	From string
-	Data string
-}
-
-func (args *NewSigArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	// Check for sufficient params
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	from, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("from", "not a string")
-	}
-	args.From = from
-
-	if len(args.From) == 0 {
-		return NewValidationError("from", "is required")
-	}
-
-	data, ok := obj[1].(string)
-	if !ok {
-		return NewInvalidTypeError("data", "not a string")
-	}
-	args.Data = data
-
-	if len(args.Data) == 0 {
-		return NewValidationError("data", "is required")
-	}
-
-	return nil
-}
-
-func (args *NewTxArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []json.RawMessage
-	var ext struct {
-		From     string
-		To       string
-		Nonce    interface{}
-		Value    interface{}
-		Gas      interface{}
-		GasPrice interface{}
-		Data     string
-	}
-
-	// Decode byte slice to array of RawMessages
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	// Check for sufficient params
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	// Decode 0th RawMessage to temporary struct
-	if err := json.Unmarshal(obj[0], &ext); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(ext.From) == 0 {
-		return NewValidationError("from", "is required")
-	}
-
-	args.From = ext.From
-	args.To = ext.To
-	args.Data = ext.Data
-
-	var num *big.Int
-	if ext.Nonce != nil {
-		num, err = numString(ext.Nonce)
-		if err != nil {
-			return err
-		}
-	}
-	args.Nonce = num
-
-	if ext.Value == nil {
-		num = big.NewInt(0)
-	} else {
-		num, err = numString(ext.Value)
-		if err != nil {
-			return err
-		}
-	}
-	args.Value = num
-
-	num = nil
-	if ext.Gas != nil {
-		if num, err = numString(ext.Gas); err != nil {
-			return err
-		}
-	} else {
-		num = nil
-	}
-	args.Gas = num
-
-	num = nil
-	if ext.GasPrice != nil {
-		if num, err = numString(ext.GasPrice); err != nil {
-			return err
-		}
-	} else {
-		num = nil
-	}
-	args.GasPrice = num
-
-	// Check for optional BlockNumber param
-	if len(obj) > 1 {
-		if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
-			return err
-		}
-	} else {
-		args.BlockNumber = -1
-	}
-
-	return nil
-}
-
-type CallArgs struct {
-	From     string
-	To       string
-	Value    *big.Int
-	Gas      *big.Int
-	GasPrice *big.Int
-	Data     string
-
-	BlockNumber int64
-}
-
-func (args *CallArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []json.RawMessage
-	var ext struct {
-		From     string
-		To       string
-		Value    interface{}
-		Gas      interface{}
-		GasPrice interface{}
-		Data     string
-	}
-
-	// Decode byte slice to array of RawMessages
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	// Check for sufficient params
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	// Decode 0th RawMessage to temporary struct
-	if err := json.Unmarshal(obj[0], &ext); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	args.From = ext.From
-
-	if len(ext.To) == 0 {
-		return NewValidationError("to", "is required")
-	}
-	args.To = ext.To
-
-	var num *big.Int
-	if ext.Value == nil {
-		num = big.NewInt(0)
-	} else {
-		if num, err = numString(ext.Value); err != nil {
-			return err
-		}
-	}
-	args.Value = num
-
-	if ext.Gas != nil {
-		if num, err = numString(ext.Gas); err != nil {
-			return err
-		}
-	} else {
-		num = nil
-	}
-	args.Gas = num
-
-	if ext.GasPrice != nil {
-		if num, err = numString(ext.GasPrice); err != nil {
-			return err
-		}
-	} else {
-		num = nil
-	}
-	args.GasPrice = num
-
-	args.Data = ext.Data
-
-	// Check for optional BlockNumber param
-	if len(obj) > 1 {
-		if err := blockHeightFromJson(obj[1], &args.BlockNumber); err != nil {
-			return err
-		}
-	} else {
-		args.BlockNumber = -1
-	}
-
-	return nil
-}
-
-type GetStorageArgs struct {
-	Address     string
-	BlockNumber int64
-}
-
-func (args *GetStorageArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	addstr, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("address", "not a string")
-	}
-	args.Address = addstr
-
-	if len(obj) > 1 {
-		if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
-			return err
-		}
-	} else {
-		args.BlockNumber = -1
-	}
-
-	return nil
-}
-
-type GetStorageAtArgs struct {
-	Address     string
-	Key         string
-	BlockNumber int64
-}
-
-func (args *GetStorageAtArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 2 {
-		return NewInsufficientParamsError(len(obj), 2)
-	}
-
-	addstr, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("address", "not a string")
-	}
-	args.Address = addstr
-
-	keystr, ok := obj[1].(string)
-	if !ok {
-		return NewInvalidTypeError("key", "not a string")
-	}
-	args.Key = keystr
-
-	if len(obj) > 2 {
-		if err := blockHeight(obj[2], &args.BlockNumber); err != nil {
-			return err
-		}
-	} else {
-		args.BlockNumber = -1
-	}
-
-	return nil
-}
-
-type GetTxCountArgs struct {
-	Address     string
-	BlockNumber int64
-}
-
-func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	addstr, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("address", "not a string")
-	}
-	args.Address = addstr
-
-	if len(obj) > 1 {
-		if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
-			return err
-		}
-	} else {
-		args.BlockNumber = -1
-	}
-
-	return nil
-}
-
-type GetBalanceArgs struct {
-	Address     string
-	BlockNumber int64
-}
-
-func (args *GetBalanceArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	addstr, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("address", "not a string")
-	}
-	args.Address = addstr
-
-	if len(obj) > 1 {
-		if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
-			return err
-		}
-	} else {
-		args.BlockNumber = -1
-	}
-
-	return nil
-}
-
-type GetDataArgs struct {
-	Address     string
-	BlockNumber int64
-}
-
-func (args *GetDataArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	addstr, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("address", "not a string")
-	}
-	args.Address = addstr
-
-	if len(obj) > 1 {
-		if err := blockHeight(obj[1], &args.BlockNumber); err != nil {
-			return err
-		}
-	} else {
-		args.BlockNumber = -1
-	}
-
-	return nil
-}
-
-type BlockNumArg struct {
-	BlockNumber int64
-}
-
-func (args *BlockNumArg) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
-		return err
-	}
-
-	return nil
-}
-
-type BlockNumIndexArgs struct {
-	BlockNumber int64
-	Index       int64
-}
-
-func (args *BlockNumIndexArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 2 {
-		return NewInsufficientParamsError(len(obj), 2)
-	}
-
-	if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
-		return err
-	}
-
-	var arg1 *big.Int
-	if arg1, err = numString(obj[1]); err != nil {
-		return err
-	}
-	args.Index = arg1.Int64()
-
-	return nil
-}
-
-type HashArgs struct {
-	Hash string
-}
-
-func (args *HashArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	arg0, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("hash", "not a string")
-	}
-	args.Hash = arg0
-
-	return nil
-}
-
-type HashIndexArgs struct {
-	Hash  string
-	Index int64
-}
-
-func (args *HashIndexArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 2 {
-		return NewInsufficientParamsError(len(obj), 2)
-	}
-
-	arg0, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("hash", "not a string")
-	}
-	args.Hash = arg0
-
-	arg1, ok := obj[1].(string)
-	if !ok {
-		return NewInvalidTypeError("index", "not a string")
-	}
-	args.Index = common.Big(arg1).Int64()
-
-	return nil
-}
-
-type Sha3Args struct {
-	Data string
-}
-
-func (args *Sha3Args) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	argstr, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("data", "is not a string")
-	}
-	args.Data = argstr
-	return nil
-}
-
-type BlockFilterArgs struct {
-	Earliest int64
-	Latest   int64
-	Address  []string
-	Topics   [][]string
-	Skip     int
-	Max      int
-}
-
-func (args *BlockFilterArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []struct {
-		FromBlock interface{} `json:"fromBlock"`
-		ToBlock   interface{} `json:"toBlock"`
-		Limit     interface{} `json:"limit"`
-		Offset    interface{} `json:"offset"`
-		Address   interface{} `json:"address"`
-		Topics    interface{} `json:"topics"`
-	}
-
-	if err = json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	// args.Earliest, err = toNumber(obj[0].ToBlock)
-	// if err != nil {
-	// 	return NewDecodeParamError(fmt.Sprintf("FromBlock %v", err))
-	// }
-	// args.Latest, err = toNumber(obj[0].FromBlock)
-	// if err != nil {
-	// 	return NewDecodeParamError(fmt.Sprintf("ToBlock %v", err))
-
-	var num int64
-	var numBig *big.Int
-
-	// if blank then latest
-	if obj[0].FromBlock == nil {
-		num = -1
-	} else {
-		if err := blockHeight(obj[0].FromBlock, &num); err != nil {
-			return err
-		}
-	}
-	// if -2 or other "silly" number, use latest
-	if num < 0 {
-		args.Earliest = -1 //latest block
-	} else {
-		args.Earliest = num
-	}
-
-	// if blank than latest
-	if obj[0].ToBlock == nil {
-		num = -1
-	} else {
-		if err := blockHeight(obj[0].ToBlock, &num); err != nil {
-			return err
-		}
-	}
-	args.Latest = num
-
-	if obj[0].Limit == nil {
-		numBig = big.NewInt(defaultLogLimit)
-	} else {
-		if numBig, err = numString(obj[0].Limit); err != nil {
-			return err
-		}
-	}
-	args.Max = int(numBig.Int64())
-
-	if obj[0].Offset == nil {
-		numBig = big.NewInt(defaultLogOffset)
-	} else {
-		if numBig, err = numString(obj[0].Offset); err != nil {
-			return err
-		}
-	}
-	args.Skip = int(numBig.Int64())
-
-	if obj[0].Address != nil {
-		marg, ok := obj[0].Address.([]interface{})
-		if ok {
-			v := make([]string, len(marg))
-			for i, arg := range marg {
-				argstr, ok := arg.(string)
-				if !ok {
-					return NewInvalidTypeError(fmt.Sprintf("address[%d]", i), "is not a string")
-				}
-				v[i] = argstr
-			}
-			args.Address = v
-		} else {
-			argstr, ok := obj[0].Address.(string)
-			if ok {
-				v := make([]string, 1)
-				v[0] = argstr
-				args.Address = v
-			} else {
-				return NewInvalidTypeError("address", "is not a string or array")
-			}
-		}
-	}
-
-	if obj[0].Topics != nil {
-		other, ok := obj[0].Topics.([]interface{})
-		if ok {
-			topicdbl := make([][]string, len(other))
-			for i, iv := range other {
-				if argstr, ok := iv.(string); ok {
-					// Found a string, push into first element of array
-					topicsgl := make([]string, 1)
-					topicsgl[0] = argstr
-					topicdbl[i] = topicsgl
-				} else if argarray, ok := iv.([]interface{}); ok {
-					// Found an array of other
-					topicdbl[i] = make([]string, len(argarray))
-					for j, jv := range argarray {
-						if v, ok := jv.(string); ok {
-							topicdbl[i][j] = v
-						} else if jv == nil {
-							topicdbl[i][j] = ""
-						} else {
-							return NewInvalidTypeError(fmt.Sprintf("topic[%d][%d]", i, j), "is not a string")
-						}
-					}
-				} else if iv == nil {
-					topicdbl[i] = []string{""}
-				} else {
-					return NewInvalidTypeError(fmt.Sprintf("topic[%d]", i), "not a string or array")
-				}
-			}
-			args.Topics = topicdbl
-			return nil
-		} else {
-			return NewInvalidTypeError("topic", "is not a string or array")
-		}
-	}
-
-	return nil
-}
-
-type DbArgs struct {
-	Database string
-	Key      string
-	Value    []byte
-}
-
-func (args *DbArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 2 {
-		return NewInsufficientParamsError(len(obj), 2)
-	}
-
-	var objstr string
-	var ok bool
-
-	if objstr, ok = obj[0].(string); !ok {
-		return NewInvalidTypeError("database", "not a string")
-	}
-	args.Database = objstr
-
-	if objstr, ok = obj[1].(string); !ok {
-		return NewInvalidTypeError("key", "not a string")
-	}
-	args.Key = objstr
-
-	if len(obj) > 2 {
-		objstr, ok = obj[2].(string)
-		if !ok {
-			return NewInvalidTypeError("value", "not a string")
-		}
-
-		args.Value = []byte(objstr)
-	}
-
-	return nil
-}
-
-func (a *DbArgs) requirements() error {
-	if len(a.Database) == 0 {
-		return NewValidationError("Database", "cannot be blank")
-	}
-	if len(a.Key) == 0 {
-		return NewValidationError("Key", "cannot be blank")
-	}
-	return nil
-}
-
-type DbHexArgs struct {
-	Database string
-	Key      string
-	Value    []byte
-}
-
-func (args *DbHexArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 2 {
-		return NewInsufficientParamsError(len(obj), 2)
-	}
-
-	var objstr string
-	var ok bool
-
-	if objstr, ok = obj[0].(string); !ok {
-		return NewInvalidTypeError("database", "not a string")
-	}
-	args.Database = objstr
-
-	if objstr, ok = obj[1].(string); !ok {
-		return NewInvalidTypeError("key", "not a string")
-	}
-	args.Key = objstr
-
-	if len(obj) > 2 {
-		objstr, ok = obj[2].(string)
-		if !ok {
-			return NewInvalidTypeError("value", "not a string")
-		}
-
-		args.Value = common.FromHex(objstr)
-	}
-
-	return nil
-}
-
-func (a *DbHexArgs) requirements() error {
-	if len(a.Database) == 0 {
-		return NewValidationError("Database", "cannot be blank")
-	}
-	if len(a.Key) == 0 {
-		return NewValidationError("Key", "cannot be blank")
-	}
-	return nil
-}
-
-type WhisperMessageArgs struct {
-	Payload  string
-	To       string
-	From     string
-	Topics   []string
-	Priority uint32
-	Ttl      uint32
-}
-
-func (args *WhisperMessageArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []struct {
-		Payload  string
-		To       string
-		From     string
-		Topics   []string
-		Priority interface{}
-		Ttl      interface{}
-	}
-
-	if err = json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-	args.Payload = obj[0].Payload
-	args.To = obj[0].To
-	args.From = obj[0].From
-	args.Topics = obj[0].Topics
-
-	var num *big.Int
-	if num, err = numString(obj[0].Priority); err != nil {
-		return err
-	}
-	args.Priority = uint32(num.Int64())
-
-	if num, err = numString(obj[0].Ttl); err != nil {
-		return err
-	}
-	args.Ttl = uint32(num.Int64())
-
-	return nil
-}
-
-type CompileArgs struct {
-	Source string
-}
-
-func (args *CompileArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-	argstr, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("arg0", "is not a string")
-	}
-	args.Source = argstr
-
-	return nil
-}
-
-type FilterStringArgs struct {
-	Word string
-}
-
-func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	var argstr string
-	argstr, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("filter", "not a string")
-	}
-	switch argstr {
-	case "latest", "pending":
-		break
-	default:
-		return NewValidationError("Word", "Must be `latest` or `pending`")
-	}
-	args.Word = argstr
-	return nil
-}
-
-type FilterIdArgs struct {
-	Id int
-}
-
-func (args *FilterIdArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	var num *big.Int
-	if num, err = numString(obj[0]); err != nil {
-		return err
-	}
-	args.Id = int(num.Int64())
-
-	return nil
-}
-
-type WhisperIdentityArgs struct {
-	Identity string
-}
-
-func (args *WhisperIdentityArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	argstr, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("arg0", "not a string")
-	}
-	// if !common.IsHex(argstr) {
-	// 	return NewValidationError("arg0", "not a hexstring")
-	// }
-	args.Identity = argstr
-
-	return nil
-}
-
-type WhisperFilterArgs struct {
-	To     string
-	From   string
-	Topics [][]string
-}
-
-// UnmarshalJSON implements the json.Unmarshaler interface, invoked to convert a
-// JSON message blob into a WhisperFilterArgs structure.
-func (args *WhisperFilterArgs) UnmarshalJSON(b []byte) (err error) {
-	// Unmarshal the JSON message and sanity check
-	var obj []struct {
-		To     interface{} `json:"to"`
-		From   interface{} `json:"from"`
-		Topics interface{} `json:"topics"`
-	}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-	// Retrieve the simple data contents of the filter arguments
-	if obj[0].To == nil {
-		args.To = ""
-	} else {
-		argstr, ok := obj[0].To.(string)
-		if !ok {
-			return NewInvalidTypeError("to", "is not a string")
-		}
-		args.To = argstr
-	}
-	if obj[0].From == nil {
-		args.From = ""
-	} else {
-		argstr, ok := obj[0].From.(string)
-		if !ok {
-			return NewInvalidTypeError("from", "is not a string")
-		}
-		args.From = argstr
-	}
-	// Construct the nested topic array
-	if obj[0].Topics != nil {
-		// Make sure we have an actual topic array
-		list, ok := obj[0].Topics.([]interface{})
-		if !ok {
-			return NewInvalidTypeError("topics", "is not an array")
-		}
-		// Iterate over each topic and handle nil, string or array
-		topics := make([][]string, len(list))
-		for idx, field := range list {
-			switch value := field.(type) {
-			case nil:
-				topics[idx] = []string{}
-
-			case string:
-				topics[idx] = []string{value}
-
-			case []interface{}:
-				topics[idx] = make([]string, len(value))
-				for i, nested := range value {
-					switch value := nested.(type) {
-					case nil:
-						topics[idx][i] = ""
-
-					case string:
-						topics[idx][i] = value
-
-					default:
-						return NewInvalidTypeError(fmt.Sprintf("topic[%d][%d]", idx, i), "is not a string")
-					}
-				}
-			default:
-				return NewInvalidTypeError(fmt.Sprintf("topic[%d]", idx), "not a string or array")
-			}
-		}
-		args.Topics = topics
-	}
-	return nil
-}
-
-type SubmitWorkArgs struct {
-	Nonce  uint64
-	Header string
-	Digest string
-}
-
-func (args *SubmitWorkArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err = json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 3 {
-		return NewInsufficientParamsError(len(obj), 3)
-	}
-
-	var objstr string
-	var ok bool
-	if objstr, ok = obj[0].(string); !ok {
-		return NewInvalidTypeError("nonce", "not a string")
-	}
-
-	args.Nonce = common.String2Big(objstr).Uint64()
-	if objstr, ok = obj[1].(string); !ok {
-		return NewInvalidTypeError("header", "not a string")
-	}
-
-	args.Header = objstr
-
-	if objstr, ok = obj[2].(string); !ok {
-		return NewInvalidTypeError("digest", "not a string")
-	}
-
-	args.Digest = objstr
-
-	return nil
-}
-
-type SourceArgs struct {
-	Source string
-}
-
-func (args *SourceArgs) UnmarshalJSON(b []byte) (err error) {
-	var obj []interface{}
-	if err := json.Unmarshal(b, &obj); err != nil {
-		return NewDecodeParamError(err.Error())
-	}
-
-	if len(obj) < 1 {
-		return NewInsufficientParamsError(len(obj), 1)
-	}
-
-	arg0, ok := obj[0].(string)
-	if !ok {
-		return NewInvalidTypeError("source code", "not a string")
-	}
-	args.Source = arg0
-
-	return nil
-}

+ 17 - 1
rpc/comms/comms.go

@@ -9,16 +9,32 @@ import (
 	"github.com/ethereum/go-ethereum/rpc/api"
 	"github.com/ethereum/go-ethereum/rpc/codec"
 	"github.com/ethereum/go-ethereum/rpc/shared"
+	"strings"
 )
 
 const (
-	jsonrpcver           = "2.0"
 	maxHttpSizeReqLength = 1024 * 1024 // 1MB
 )
 
+var (
+	// List with all API's which are offered over the in proc interface by default
+	DefaultInProcApis = api.AllApis
+
+	// List with all API's which are offered over the IPC interface by default
+	DefaultIpcApis = api.AllApis
+
+	// List with API's which are offered over thr HTTP/RPC interface by default
+	DefaultHttpRpcApis = strings.Join([]string{
+		api.DbApiName, api.EthApiName, api.NetApiName, api.Web3ApiName,
+		}, ",")
+)
+
 type EthereumClient interface {
+	// Close underlaying connection
 	Close()
+	// Send request
 	Send(interface{}) error
+	// Receive response
 	Recv() (interface{}, error)
 }
 

+ 24 - 0
rpc/comms/http.go

@@ -63,3 +63,27 @@ func StopHttp() {
 		httpListener = nil
 	}
 }
+
+
+type httpClient struct {
+	codec codec.ApiCoder
+}
+
+// Create a new in process client
+func NewHttpClient(cfg HttpConfig, codec codec.Codec) *httpClient {
+	return &httpClient{
+		codec: codec.New(nil),
+	}
+}
+
+func (self *httpClient) Close() {
+	// do nothing
+}
+
+func (self *httpClient) Send(req interface{}) error {
+	return nil
+}
+
+func (self *httpClient) Recv() (interface{}, error) {
+	return nil, nil
+}

+ 7 - 7
rpc/comms/http_net.go

@@ -90,7 +90,7 @@ func newStoppableHandler(h http.Handler, stop chan struct{}) http.Handler {
 		case <-stop:
 			w.Header().Set("Content-Type", "application/json")
 			err := fmt.Errorf("RPC service stopped")
-			response := shared.NewRpcResponse(-1, jsonrpcver, nil, err)
+			response := shared.NewRpcResponse(-1, api.JsonRpcVersion, nil, err)
 			httpSend(w, response)
 		default:
 			h.ServeHTTP(w, r)
@@ -110,14 +110,14 @@ func httpSend(writer io.Writer, v interface{}) (n int, err error) {
 	return writer.Write(payload)
 }
 
-func gethHttpHandler(codec codec.Codec, api api.EthereumApi) http.Handler {
+func gethHttpHandler(codec codec.Codec, a api.EthereumApi) http.Handler {
 	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 		w.Header().Set("Content-Type", "application/json")
 
 		// Limit request size to resist DoS
 		if req.ContentLength > maxHttpSizeReqLength {
 			err := fmt.Errorf("Request too large")
-			response := shared.NewRpcErrorResponse(-1, jsonrpcver, -32700, err)
+			response := shared.NewRpcErrorResponse(-1, api.JsonRpcVersion, -32700, err)
 			httpSend(w, &response)
 			return
 		}
@@ -126,7 +126,7 @@ func gethHttpHandler(codec codec.Codec, api api.EthereumApi) http.Handler {
 		payload, err := ioutil.ReadAll(req.Body)
 		if err != nil {
 			err := fmt.Errorf("Could not read request body")
-			response := shared.NewRpcErrorResponse(-1, jsonrpcver, -32700, err)
+			response := shared.NewRpcErrorResponse(-1, api.JsonRpcVersion, -32700, err)
 			httpSend(w, &response)
 			return
 		}
@@ -134,7 +134,7 @@ func gethHttpHandler(codec codec.Codec, api api.EthereumApi) http.Handler {
 		c := codec.New(nil)
 		var rpcReq shared.Request
 		if err = c.Decode(payload, &rpcReq); err == nil {
-			reply, err := api.Execute(&rpcReq)
+			reply, err := a.Execute(&rpcReq)
 			res := shared.NewRpcResponse(rpcReq.Id, rpcReq.Jsonrpc, reply, err)
 			httpSend(w, &res)
 			return
@@ -146,7 +146,7 @@ func gethHttpHandler(codec codec.Codec, api api.EthereumApi) http.Handler {
 			resCount := 0
 
 			for i, rpcReq := range reqBatch {
-				reply, err := api.Execute(&rpcReq)
+				reply, err := a.Execute(&rpcReq)
 				if rpcReq.Id != nil { // this leaves nil entries in the response batch for later removal
 					resBatch[i] = shared.NewRpcResponse(rpcReq.Id, rpcReq.Jsonrpc, reply, err)
 					resCount += 1
@@ -161,7 +161,7 @@ func gethHttpHandler(codec codec.Codec, api api.EthereumApi) http.Handler {
 
 		// invalid request
 		err = fmt.Errorf("Could not decode request")
-		res := shared.NewRpcErrorResponse(-1, jsonrpcver, -32600, err)
+		res := shared.NewRpcErrorResponse(-1, api.JsonRpcVersion, -32600, err)
 		httpSend(w, res)
 	})
 }

+ 53 - 0
rpc/comms/inproc.go

@@ -0,0 +1,53 @@
+package comms
+
+import (
+	"github.com/ethereum/go-ethereum/rpc/api"
+	"github.com/ethereum/go-ethereum/rpc/shared"
+	"fmt"
+	"github.com/ethereum/go-ethereum/rpc/codec"
+	"github.com/ethereum/go-ethereum/xeth"
+	"github.com/ethereum/go-ethereum/eth"
+)
+
+type InProcClient struct {
+	api api.EthereumApi
+	codec codec.Codec
+	lastId interface{}
+	lastJsonrpc string
+	lastErr error
+	lastRes interface{}
+}
+
+// Create a new in process client
+func NewInProcClient(codec codec.Codec) *InProcClient {
+	return &InProcClient{
+		codec: codec,
+	}
+}
+
+func (self *InProcClient) Close() {
+	// do nothing
+}
+
+// Need to setup api support
+func (self *InProcClient) Initialize(xeth *xeth.XEth, eth *eth.Ethereum) {
+	if apis, err := api.ParseApiString(api.AllApis, self.codec, xeth, eth); err == nil {
+		self.api = api.Merge(apis...)
+	}
+}
+
+func (self *InProcClient) Send(req interface{}) error {
+	if r, ok := req.(*shared.Request); ok {
+		self.lastId = r.Id
+		self.lastJsonrpc = r.Jsonrpc
+		self.lastRes, self.lastErr = self.api.Execute(r)
+		return self.lastErr
+	}
+
+	return fmt.Errorf("Invalid request (%T)", req)
+}
+
+func (self *InProcClient) Recv() (interface{}, error) {
+	return self.lastRes, self.lastErr
+	//return *shared.NewRpcResponse(self.lastId, self.lastJsonrpc, self.lastRes, self.lastErr), nil
+}

+ 4 - 4
rpc/comms/ipc.go

@@ -10,19 +10,19 @@ type IpcConfig struct {
 }
 
 type ipcClient struct {
-	c codec.ApiCoder
+	codec codec.ApiCoder
 }
 
 func (self *ipcClient) Close() {
-	self.c.Close()
+	self.codec.Close()
 }
 
 func (self *ipcClient) Send(req interface{}) error {
-	return self.c.WriteResponse(req)
+	return self.codec.WriteResponse(req)
 }
 
 func (self *ipcClient) Recv() (interface{}, error) {
-	return self.c.ReadResponse()
+	return self.codec.ReadResponse()
 }
 
 // Create a new IPC client, UNIX domain socket on posix, named pipe on Windows

+ 0 - 163
rpc/http.go

@@ -1,163 +0,0 @@
-package rpc
-
-import (
-	"encoding/json"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"net/http"
-	"strings"
-
-	"github.com/ethereum/go-ethereum/logger"
-	"github.com/ethereum/go-ethereum/logger/glog"
-	"github.com/ethereum/go-ethereum/xeth"
-	"github.com/rs/cors"
-)
-
-var rpclistener *stoppableTCPListener
-
-const (
-	jsonrpcver       = "2.0"
-	maxSizeReqLength = 1024 * 1024 // 1MB
-)
-
-func Start(pipe *xeth.XEth, config RpcConfig) error {
-	if rpclistener != nil {
-		if fmt.Sprintf("%s:%d", config.ListenAddress, config.ListenPort) != rpclistener.Addr().String() {
-			return fmt.Errorf("RPC service already running on %s ", rpclistener.Addr().String())
-		}
-		return nil // RPC service already running on given host/port
-	}
-
-	l, err := newStoppableTCPListener(fmt.Sprintf("%s:%d", config.ListenAddress, config.ListenPort))
-	if err != nil {
-		glog.V(logger.Error).Infof("Can't listen on %s:%d: %v", config.ListenAddress, config.ListenPort, err)
-		return err
-	}
-	rpclistener = l
-
-	var handler http.Handler
-	if len(config.CorsDomain) > 0 {
-		var opts cors.Options
-		opts.AllowedMethods = []string{"POST"}
-		opts.AllowedOrigins = strings.Split(config.CorsDomain, " ")
-
-		c := cors.New(opts)
-		handler = newStoppableHandler(c.Handler(JSONRPC(pipe)), l.stop)
-	} else {
-		handler = newStoppableHandler(JSONRPC(pipe), l.stop)
-	}
-
-	go http.Serve(l, handler)
-
-	return nil
-}
-
-func Stop() error {
-	if rpclistener != nil {
-		rpclistener.Stop()
-		rpclistener = nil
-	}
-
-	return nil
-}
-
-// JSONRPC returns a handler that implements the Ethereum JSON-RPC API.
-func JSONRPC(pipe *xeth.XEth) http.Handler {
-	api := NewEthereumApi(pipe)
-
-	return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
-		w.Header().Set("Content-Type", "application/json")
-
-		// 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})
-			return
-		}
-
-		// Read request body
-		defer req.Body.Close()
-		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})
-		}
-
-		// Try to parse the request as a single
-		var reqSingle RpcRequest
-		if err := json.Unmarshal(body, &reqSingle); err == nil {
-			response := RpcResponse(api, &reqSingle)
-			if reqSingle.Id != nil {
-				send(w, &response)
-			}
-			return
-		}
-
-		// Try to parse the request to batch
-		var reqBatch []RpcRequest
-		if err := json.Unmarshal(body, &reqBatch); err == nil {
-			// Build response batch
-			resBatch := make([]*interface{}, len(reqBatch))
-			resCount := 0
-
-			for i, request := range reqBatch {
-				response := RpcResponse(api, &request)
-				// this leaves nil entries in the response batch for later removal
-				if request.Id != nil {
-					resBatch[i] = response
-					resCount = resCount + 1
-				}
-			}
-
-			// make response omitting nil entries
-			respBatchComp := make([]*interface{}, resCount)
-			for _, v := range resBatch {
-				if v != nil {
-					respBatchComp[len(respBatchComp)-resCount] = v
-					resCount = resCount - 1
-				}
-			}
-
-			send(w, respBatchComp)
-			return
-		}
-
-		// Not a batch or single request, error
-		jsonerr := &RpcErrorObject{-32600, "Could not decode request"}
-		send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr})
-	})
-}
-
-func RpcResponse(api *EthereumApi, request *RpcRequest) *interface{} {
-	var reply, response interface{}
-	reserr := api.GetRequestReply(request, &reply)
-	switch reserr.(type) {
-	case nil:
-		response = &RpcSuccessResponse{Jsonrpc: jsonrpcver, Id: request.Id, Result: reply}
-	case *NotImplementedError, *NotAvailableError:
-		jsonerr := &RpcErrorObject{-32601, reserr.Error()}
-		response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr}
-	case *DecodeParamError, *InsufficientParamsError, *ValidationError, *InvalidTypeError:
-		jsonerr := &RpcErrorObject{-32602, reserr.Error()}
-		response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr}
-	default:
-		jsonerr := &RpcErrorObject{-32603, reserr.Error()}
-		response = &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: request.Id, Error: jsonerr}
-	}
-
-	glog.V(logger.Detail).Infof("Generated response: %T %s", response, response)
-	return &response
-}
-
-func send(writer io.Writer, v interface{}) (n int, err error) {
-	var payload []byte
-	payload, err = json.MarshalIndent(v, "", "\t")
-	if err != nil {
-		glog.V(logger.Error).Infoln("Error marshalling JSON", err)
-		return 0, err
-	}
-	glog.V(logger.Detail).Infof("Sending payload: %s", payload)
-
-	return writer.Write(payload)
-}

+ 25 - 19
rpc/jeth.go

@@ -1,31 +1,28 @@
 package rpc
 
 import (
-	"encoding/json"
-	"fmt"
-
-	"reflect"
-
 	"github.com/ethereum/go-ethereum/jsre"
-	"github.com/ethereum/go-ethereum/rpc/codec"
+	"github.com/ethereum/go-ethereum/rpc/api"
 	"github.com/ethereum/go-ethereum/rpc/comms"
 	"github.com/ethereum/go-ethereum/rpc/shared"
 	"github.com/robertkrimen/otto"
+	"encoding/json"
+	"fmt"
 )
 
 type Jeth struct {
-	ethApi  *EthereumApi
-	re      *jsre.JSRE
-	ipcpath string
+	ethApi api.EthereumApi
+	re     *jsre.JSRE
+	client comms.EthereumClient
 }
 
-func NewJeth(ethApi *EthereumApi, re *jsre.JSRE, ipcpath string) *Jeth {
-	return &Jeth{ethApi, re, ipcpath}
+func NewJeth(ethApi api.EthereumApi, re *jsre.JSRE, client comms.EthereumClient) *Jeth {
+	return &Jeth{ethApi, re, client}
 }
 
 func (self *Jeth) err(call otto.FunctionCall, code int, msg string, id interface{}) (response otto.Value) {
-	rpcerr := &RpcErrorObject{code, msg}
-	call.Otto.Set("ret_jsonrpc", jsonrpcver)
+	rpcerr := &shared.ErrorObject{code, msg}
+	call.Otto.Set("ret_jsonrpc", api.JsonRpcVersion)
 	call.Otto.Set("ret_id", id)
 	call.Otto.Set("ret_error", rpcerr)
 	response, _ = call.Otto.Run(`
@@ -34,6 +31,7 @@ func (self *Jeth) err(call otto.FunctionCall, code int, msg string, id interface
 	return
 }
 
+
 func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
 	reqif, err := call.Argument(0).Export()
 	if err != nil {
@@ -41,11 +39,11 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
 	}
 
 	jsonreq, err := json.Marshal(reqif)
-	var reqs []RpcRequest
+	var reqs []shared.Request
 	batch := true
 	err = json.Unmarshal(jsonreq, &reqs)
 	if err != nil {
-		reqs = make([]RpcRequest, 1)
+		reqs = make([]shared.Request, 1)
 		err = json.Unmarshal(jsonreq, &reqs[0])
 		batch = false
 	}
@@ -55,12 +53,18 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
 
 	for i, req := range reqs {
 		var respif interface{}
-		err = self.ethApi.GetRequestReply(&req, &respif)
+		err := self.client.Send(&req)//self.ethApi.Execute(&req)
+		if err != nil {
+			fmt.Println("Error request:", err)
+			return self.err(call, -32603, err.Error(), req.Id)
+		}
+		respif, err = self.client.Recv()
 		if err != nil {
 			fmt.Println("Error response:", err)
 			return self.err(call, -32603, err.Error(), req.Id)
 		}
-		call.Otto.Set("ret_jsonrpc", jsonrpcver)
+
+		call.Otto.Set("ret_jsonrpc", api.JsonRpcVersion)
 		call.Otto.Set("ret_id", req.Id)
 
 		res, _ := json.Marshal(respif)
@@ -88,6 +92,7 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) {
 	return
 }
 
+/*
 func (self *Jeth) SendIpc(call otto.FunctionCall) (response otto.Value) {
 	reqif, err := call.Argument(0).Export()
 	if err != nil {
@@ -102,11 +107,11 @@ func (self *Jeth) SendIpc(call otto.FunctionCall) (response otto.Value) {
 	defer client.Close()
 
 	jsonreq, err := json.Marshal(reqif)
-	var reqs []RpcRequest
+	var reqs []shared.Request
 	batch := true
 	err = json.Unmarshal(jsonreq, &reqs)
 	if err != nil {
-		reqs = make([]RpcRequest, 1)
+		reqs = make([]shared.Request, 1)
 		err = json.Unmarshal(jsonreq, &reqs[0])
 		batch = false
 	}
@@ -169,3 +174,4 @@ func (self *Jeth) SendIpc(call otto.FunctionCall) (response otto.Value) {
 
 	return
 }
+*/

+ 0 - 316
rpc/responses.go

@@ -1,316 +0,0 @@
-package rpc
-
-import (
-	"encoding/json"
-
-	"github.com/ethereum/go-ethereum/common"
-	"github.com/ethereum/go-ethereum/core/state"
-	"github.com/ethereum/go-ethereum/core/types"
-)
-
-type BlockRes struct {
-	fullTx bool
-
-	BlockNumber     *hexnum           `json:"number"`
-	BlockHash       *hexdata          `json:"hash"`
-	ParentHash      *hexdata          `json:"parentHash"`
-	Nonce           *hexdata          `json:"nonce"`
-	Sha3Uncles      *hexdata          `json:"sha3Uncles"`
-	LogsBloom       *hexdata          `json:"logsBloom"`
-	TransactionRoot *hexdata          `json:"transactionsRoot"`
-	StateRoot       *hexdata          `json:"stateRoot"`
-	Miner           *hexdata          `json:"miner"`
-	Difficulty      *hexnum           `json:"difficulty"`
-	TotalDifficulty *hexnum           `json:"totalDifficulty"`
-	Size            *hexnum           `json:"size"`
-	ExtraData       *hexdata          `json:"extraData"`
-	GasLimit        *hexnum           `json:"gasLimit"`
-	GasUsed         *hexnum           `json:"gasUsed"`
-	UnixTimestamp   *hexnum           `json:"timestamp"`
-	Transactions    []*TransactionRes `json:"transactions"`
-	Uncles          []*UncleRes       `json:"uncles"`
-}
-
-func (b *BlockRes) MarshalJSON() ([]byte, error) {
-	if b.fullTx {
-		var ext struct {
-			BlockNumber     *hexnum           `json:"number"`
-			BlockHash       *hexdata          `json:"hash"`
-			ParentHash      *hexdata          `json:"parentHash"`
-			Nonce           *hexdata          `json:"nonce"`
-			Sha3Uncles      *hexdata          `json:"sha3Uncles"`
-			LogsBloom       *hexdata          `json:"logsBloom"`
-			TransactionRoot *hexdata          `json:"transactionsRoot"`
-			StateRoot       *hexdata          `json:"stateRoot"`
-			Miner           *hexdata          `json:"miner"`
-			Difficulty      *hexnum           `json:"difficulty"`
-			TotalDifficulty *hexnum           `json:"totalDifficulty"`
-			Size            *hexnum           `json:"size"`
-			ExtraData       *hexdata          `json:"extraData"`
-			GasLimit        *hexnum           `json:"gasLimit"`
-			GasUsed         *hexnum           `json:"gasUsed"`
-			UnixTimestamp   *hexnum           `json:"timestamp"`
-			Transactions    []*TransactionRes `json:"transactions"`
-			Uncles          []*hexdata        `json:"uncles"`
-		}
-
-		ext.BlockNumber = b.BlockNumber
-		ext.BlockHash = b.BlockHash
-		ext.ParentHash = b.ParentHash
-		ext.Nonce = b.Nonce
-		ext.Sha3Uncles = b.Sha3Uncles
-		ext.LogsBloom = b.LogsBloom
-		ext.TransactionRoot = b.TransactionRoot
-		ext.StateRoot = b.StateRoot
-		ext.Miner = b.Miner
-		ext.Difficulty = b.Difficulty
-		ext.TotalDifficulty = b.TotalDifficulty
-		ext.Size = b.Size
-		ext.ExtraData = b.ExtraData
-		ext.GasLimit = b.GasLimit
-		ext.GasUsed = b.GasUsed
-		ext.UnixTimestamp = b.UnixTimestamp
-		ext.Transactions = b.Transactions
-		ext.Uncles = make([]*hexdata, len(b.Uncles))
-		for i, u := range b.Uncles {
-			ext.Uncles[i] = u.BlockHash
-		}
-		return json.Marshal(ext)
-	} else {
-		var ext struct {
-			BlockNumber     *hexnum    `json:"number"`
-			BlockHash       *hexdata   `json:"hash"`
-			ParentHash      *hexdata   `json:"parentHash"`
-			Nonce           *hexdata   `json:"nonce"`
-			Sha3Uncles      *hexdata   `json:"sha3Uncles"`
-			LogsBloom       *hexdata   `json:"logsBloom"`
-			TransactionRoot *hexdata   `json:"transactionsRoot"`
-			StateRoot       *hexdata   `json:"stateRoot"`
-			Miner           *hexdata   `json:"miner"`
-			Difficulty      *hexnum    `json:"difficulty"`
-			TotalDifficulty *hexnum    `json:"totalDifficulty"`
-			Size            *hexnum    `json:"size"`
-			ExtraData       *hexdata   `json:"extraData"`
-			GasLimit        *hexnum    `json:"gasLimit"`
-			GasUsed         *hexnum    `json:"gasUsed"`
-			UnixTimestamp   *hexnum    `json:"timestamp"`
-			Transactions    []*hexdata `json:"transactions"`
-			Uncles          []*hexdata `json:"uncles"`
-		}
-
-		ext.BlockNumber = b.BlockNumber
-		ext.BlockHash = b.BlockHash
-		ext.ParentHash = b.ParentHash
-		ext.Nonce = b.Nonce
-		ext.Sha3Uncles = b.Sha3Uncles
-		ext.LogsBloom = b.LogsBloom
-		ext.TransactionRoot = b.TransactionRoot
-		ext.StateRoot = b.StateRoot
-		ext.Miner = b.Miner
-		ext.Difficulty = b.Difficulty
-		ext.TotalDifficulty = b.TotalDifficulty
-		ext.Size = b.Size
-		ext.ExtraData = b.ExtraData
-		ext.GasLimit = b.GasLimit
-		ext.GasUsed = b.GasUsed
-		ext.UnixTimestamp = b.UnixTimestamp
-		ext.Transactions = make([]*hexdata, len(b.Transactions))
-		for i, tx := range b.Transactions {
-			ext.Transactions[i] = tx.Hash
-		}
-		ext.Uncles = make([]*hexdata, len(b.Uncles))
-		for i, u := range b.Uncles {
-			ext.Uncles[i] = u.BlockHash
-		}
-		return json.Marshal(ext)
-	}
-}
-
-func NewBlockRes(block *types.Block, fullTx bool) *BlockRes {
-	if block == nil {
-		return nil
-	}
-
-	res := new(BlockRes)
-	res.fullTx = fullTx
-	res.BlockNumber = newHexNum(block.Number())
-	res.BlockHash = newHexData(block.Hash())
-	res.ParentHash = newHexData(block.ParentHash())
-	res.Nonce = newHexData(block.Nonce())
-	res.Sha3Uncles = newHexData(block.Header().UncleHash)
-	res.LogsBloom = newHexData(block.Bloom())
-	res.TransactionRoot = newHexData(block.Header().TxHash)
-	res.StateRoot = newHexData(block.Root())
-	res.Miner = newHexData(block.Header().Coinbase)
-	res.Difficulty = newHexNum(block.Difficulty())
-	res.TotalDifficulty = newHexNum(block.Td)
-	res.Size = newHexNum(block.Size().Int64())
-	res.ExtraData = newHexData(block.Header().Extra)
-	res.GasLimit = newHexNum(block.GasLimit())
-	res.GasUsed = newHexNum(block.GasUsed())
-	res.UnixTimestamp = newHexNum(block.Time())
-
-	res.Transactions = make([]*TransactionRes, len(block.Transactions()))
-	for i, tx := range block.Transactions() {
-		res.Transactions[i] = NewTransactionRes(tx)
-		res.Transactions[i].BlockHash = res.BlockHash
-		res.Transactions[i].BlockNumber = res.BlockNumber
-		res.Transactions[i].TxIndex = newHexNum(i)
-	}
-
-	res.Uncles = make([]*UncleRes, len(block.Uncles()))
-	for i, uncle := range block.Uncles() {
-		res.Uncles[i] = NewUncleRes(uncle)
-	}
-
-	return res
-}
-
-type TransactionRes struct {
-	Hash        *hexdata `json:"hash"`
-	Nonce       *hexnum  `json:"nonce"`
-	BlockHash   *hexdata `json:"blockHash"`
-	BlockNumber *hexnum  `json:"blockNumber"`
-	TxIndex     *hexnum  `json:"transactionIndex"`
-	From        *hexdata `json:"from"`
-	To          *hexdata `json:"to"`
-	Value       *hexnum  `json:"value"`
-	Gas         *hexnum  `json:"gas"`
-	GasPrice    *hexnum  `json:"gasPrice"`
-	Input       *hexdata `json:"input"`
-}
-
-func NewTransactionRes(tx *types.Transaction) *TransactionRes {
-	if tx == nil {
-		return nil
-	}
-
-	var v = new(TransactionRes)
-	v.Hash = newHexData(tx.Hash())
-	v.Nonce = newHexNum(tx.Nonce())
-	// v.BlockHash =
-	// v.BlockNumber =
-	// v.TxIndex =
-	from, _ := tx.From()
-	v.From = newHexData(from)
-	v.To = newHexData(tx.To())
-	v.Value = newHexNum(tx.Value())
-	v.Gas = newHexNum(tx.Gas())
-	v.GasPrice = newHexNum(tx.GasPrice())
-	v.Input = newHexData(tx.Data())
-	return v
-}
-
-type UncleRes struct {
-	BlockNumber     *hexnum  `json:"number"`
-	BlockHash       *hexdata `json:"hash"`
-	ParentHash      *hexdata `json:"parentHash"`
-	Nonce           *hexdata `json:"nonce"`
-	Sha3Uncles      *hexdata `json:"sha3Uncles"`
-	ReceiptHash     *hexdata `json:"receiptHash"`
-	LogsBloom       *hexdata `json:"logsBloom"`
-	TransactionRoot *hexdata `json:"transactionsRoot"`
-	StateRoot       *hexdata `json:"stateRoot"`
-	Miner           *hexdata `json:"miner"`
-	Difficulty      *hexnum  `json:"difficulty"`
-	ExtraData       *hexdata `json:"extraData"`
-	GasLimit        *hexnum  `json:"gasLimit"`
-	GasUsed         *hexnum  `json:"gasUsed"`
-	UnixTimestamp   *hexnum  `json:"timestamp"`
-}
-
-func NewUncleRes(h *types.Header) *UncleRes {
-	if h == nil {
-		return nil
-	}
-
-	var v = new(UncleRes)
-	v.BlockNumber = newHexNum(h.Number)
-	v.BlockHash = newHexData(h.Hash())
-	v.ParentHash = newHexData(h.ParentHash)
-	v.Sha3Uncles = newHexData(h.UncleHash)
-	v.Nonce = newHexData(h.Nonce[:])
-	v.LogsBloom = newHexData(h.Bloom)
-	v.TransactionRoot = newHexData(h.TxHash)
-	v.StateRoot = newHexData(h.Root)
-	v.Miner = newHexData(h.Coinbase)
-	v.Difficulty = newHexNum(h.Difficulty)
-	v.ExtraData = newHexData(h.Extra)
-	v.GasLimit = newHexNum(h.GasLimit)
-	v.GasUsed = newHexNum(h.GasUsed)
-	v.UnixTimestamp = newHexNum(h.Time)
-	v.ReceiptHash = newHexData(h.ReceiptHash)
-
-	return v
-}
-
-// type FilterLogRes struct {
-// 	Hash             string `json:"hash"`
-// 	Address          string `json:"address"`
-// 	Data             string `json:"data"`
-// 	BlockNumber      string `json:"blockNumber"`
-// 	TransactionHash  string `json:"transactionHash"`
-// 	BlockHash        string `json:"blockHash"`
-// 	TransactionIndex string `json:"transactionIndex"`
-// 	LogIndex         string `json:"logIndex"`
-// }
-
-// type FilterWhisperRes struct {
-// 	Hash       string `json:"hash"`
-// 	From       string `json:"from"`
-// 	To         string `json:"to"`
-// 	Expiry     string `json:"expiry"`
-// 	Sent       string `json:"sent"`
-// 	Ttl        string `json:"ttl"`
-// 	Topics     string `json:"topics"`
-// 	Payload    string `json:"payload"`
-// 	WorkProved string `json:"workProved"`
-// }
-
-type LogRes struct {
-	Address          *hexdata   `json:"address"`
-	Topics           []*hexdata `json:"topics"`
-	Data             *hexdata   `json:"data"`
-	BlockNumber      *hexnum    `json:"blockNumber"`
-	LogIndex         *hexnum    `json:"logIndex"`
-	BlockHash        *hexdata   `json:"blockHash"`
-	TransactionHash  *hexdata   `json:"transactionHash"`
-	TransactionIndex *hexnum    `json:"transactionIndex"`
-}
-
-func NewLogRes(log *state.Log) LogRes {
-	var l LogRes
-	l.Topics = make([]*hexdata, len(log.Topics))
-	for j, topic := range log.Topics {
-		l.Topics[j] = newHexData(topic)
-	}
-	l.Address = newHexData(log.Address)
-	l.Data = newHexData(log.Data)
-	l.BlockNumber = newHexNum(log.Number)
-	l.LogIndex = newHexNum(log.Index)
-	l.TransactionHash = newHexData(log.TxHash)
-	l.TransactionIndex = newHexNum(log.TxIndex)
-	l.BlockHash = newHexData(log.BlockHash)
-
-	return l
-}
-
-func NewLogsRes(logs state.Logs) (ls []LogRes) {
-	ls = make([]LogRes, len(logs))
-
-	for i, log := range logs {
-		ls[i] = NewLogRes(log)
-	}
-
-	return
-}
-
-func NewHashesRes(hs []common.Hash) []string {
-	hashes := make([]string, len(hs))
-
-	for i, hash := range hs {
-		hashes[i] = hash.Hex()
-	}
-
-	return hashes
-}

+ 0 - 295
rpc/responses_test.go

@@ -1,295 +0,0 @@
-package rpc
-
-import (
-	"encoding/json"
-	"fmt"
-	"math/big"
-	"regexp"
-	"testing"
-
-	"github.com/ethereum/go-ethereum/common"
-	"github.com/ethereum/go-ethereum/core/state"
-	"github.com/ethereum/go-ethereum/core/types"
-)
-
-const (
-	reHash       = `"0x[0-9a-f]{64}"`                    // 32 bytes
-	reHashOpt    = `"(0x[0-9a-f]{64})"|null`             // 32 bytes or null
-	reAddress    = `"0x[0-9a-f]{40}"`                    // 20 bytes
-	reAddressOpt = `"0x[0-9a-f]{40}"|null`               // 20 bytes or null
-	reNum        = `"0x([1-9a-f][0-9a-f]{0,15})|0"`      // must not have left-padded zeros
-	reNumNonZero = `"0x([1-9a-f][0-9a-f]{0,15})"`        // non-zero required must not have left-padded zeros
-	reNumOpt     = `"0x([1-9a-f][0-9a-f]{0,15})|0"|null` // must not have left-padded zeros or null
-	reData       = `"0x[0-9a-f]*"`                       // can be "empty"
-	// reListHash   = `[("\w":"0x[0-9a-f]{64}",?)*]`
-	// reListObj    = `[("\w":(".+"|null),?)*]`
-)
-
-func TestNewBlockRes(t *testing.T) {
-	tests := map[string]string{
-		"number":           reNum,
-		"hash":             reHash,
-		"parentHash":       reHash,
-		"nonce":            reData,
-		"sha3Uncles":       reHash,
-		"logsBloom":        reData,
-		"transactionsRoot": reHash,
-		"stateRoot":        reHash,
-		"miner":            reAddress,
-		"difficulty":       `"0x1"`,
-		"totalDifficulty":  reNum,
-		"size":             reNumNonZero,
-		"extraData":        reData,
-		"gasLimit":         reNum,
-		// "minGasPrice":  "0x",
-		"gasUsed":   reNum,
-		"timestamp": reNum,
-		// "transactions": reListHash,
-		// "uncles":       reListHash,
-	}
-
-	block := makeBlock()
-	v := NewBlockRes(block, false)
-	j, _ := json.Marshal(v)
-
-	for k, re := range tests {
-		match, _ := regexp.MatchString(fmt.Sprintf(`{.*"%s":%s.*}`, k, re), string(j))
-		if !match {
-			t.Error(fmt.Sprintf("%s output json does not match format %s. Got %s", k, re, j))
-		}
-	}
-}
-
-func TestNewBlockResTxFull(t *testing.T) {
-	tests := map[string]string{
-		"number":           reNum,
-		"hash":             reHash,
-		"parentHash":       reHash,
-		"nonce":            reData,
-		"sha3Uncles":       reHash,
-		"logsBloom":        reData,
-		"transactionsRoot": reHash,
-		"stateRoot":        reHash,
-		"miner":            reAddress,
-		"difficulty":       `"0x1"`,
-		"totalDifficulty":  reNum,
-		"size":             reNumNonZero,
-		"extraData":        reData,
-		"gasLimit":         reNum,
-		// "minGasPrice":  "0x",
-		"gasUsed":   reNum,
-		"timestamp": reNum,
-		// "transactions": reListHash,
-		// "uncles":       reListHash,
-	}
-
-	block := makeBlock()
-	v := NewBlockRes(block, true)
-	j, _ := json.Marshal(v)
-
-	for k, re := range tests {
-		match, _ := regexp.MatchString(fmt.Sprintf(`{.*"%s":%s.*}`, k, re), string(j))
-		if !match {
-			t.Error(fmt.Sprintf("%s output json does not match format %s. Got %s", k, re, j))
-		}
-	}
-}
-
-func TestBlockNil(t *testing.T) {
-	var block *types.Block
-	block = nil
-	u := NewBlockRes(block, false)
-	j, _ := json.Marshal(u)
-	if string(j) != "null" {
-		t.Errorf("Expected null but got %v", string(j))
-	}
-}
-
-func TestNewTransactionRes(t *testing.T) {
-	to := common.HexToAddress("0x02")
-	amount := big.NewInt(1)
-	gasAmount := big.NewInt(1)
-	gasPrice := big.NewInt(1)
-	data := []byte{1, 2, 3}
-	tx := types.NewTransactionMessage(to, amount, gasAmount, gasPrice, data)
-
-	tests := map[string]string{
-		"hash":             reHash,
-		"nonce":            reNum,
-		"blockHash":        reHashOpt,
-		"blockNum":         reNumOpt,
-		"transactionIndex": reNumOpt,
-		"from":             reAddress,
-		"to":               reAddressOpt,
-		"value":            reNum,
-		"gas":              reNum,
-		"gasPrice":         reNum,
-		"input":            reData,
-	}
-
-	v := NewTransactionRes(tx)
-	v.BlockHash = newHexData(common.HexToHash("0x030201"))
-	v.BlockNumber = newHexNum(5)
-	v.TxIndex = newHexNum(0)
-	j, _ := json.Marshal(v)
-	for k, re := range tests {
-		match, _ := regexp.MatchString(fmt.Sprintf(`{.*"%s":%s.*}`, k, re), string(j))
-		if !match {
-			t.Error(fmt.Sprintf("`%s` output json does not match format %s. Source %s", k, re, j))
-		}
-	}
-
-}
-
-func TestTransactionNil(t *testing.T) {
-	var tx *types.Transaction
-	tx = nil
-	u := NewTransactionRes(tx)
-	j, _ := json.Marshal(u)
-	if string(j) != "null" {
-		t.Errorf("Expected null but got %v", string(j))
-	}
-}
-
-func TestNewUncleRes(t *testing.T) {
-	header := makeHeader()
-	u := NewUncleRes(header)
-	tests := map[string]string{
-		"number":           reNum,
-		"hash":             reHash,
-		"parentHash":       reHash,
-		"nonce":            reData,
-		"sha3Uncles":       reHash,
-		"receiptHash":      reHash,
-		"transactionsRoot": reHash,
-		"stateRoot":        reHash,
-		"miner":            reAddress,
-		"difficulty":       reNum,
-		"extraData":        reData,
-		"gasLimit":         reNum,
-		"gasUsed":          reNum,
-		"timestamp":        reNum,
-	}
-
-	j, _ := json.Marshal(u)
-	for k, re := range tests {
-		match, _ := regexp.MatchString(fmt.Sprintf(`{.*"%s":%s.*}`, k, re), string(j))
-		if !match {
-			t.Error(fmt.Sprintf("`%s` output json does not match format %s. Source %s", k, re, j))
-		}
-	}
-}
-
-func TestUncleNil(t *testing.T) {
-	var header *types.Header
-	header = nil
-	u := NewUncleRes(header)
-	j, _ := json.Marshal(u)
-	if string(j) != "null" {
-		t.Errorf("Expected null but got %v", string(j))
-	}
-}
-
-func TestNewLogRes(t *testing.T) {
-	log := makeStateLog(0)
-	tests := map[string]string{
-		"address": reAddress,
-		// "topics": "[.*]"
-		"data":        reData,
-		"blockNumber": reNum,
-		// "hash":             reHash,
-		// "logIndex":         reNum,
-		// "blockHash":        reHash,
-		// "transactionHash":  reHash,
-		"transactionIndex": reNum,
-	}
-
-	v := NewLogRes(log)
-	j, _ := json.Marshal(v)
-
-	for k, re := range tests {
-		match, _ := regexp.MatchString(fmt.Sprintf(`{.*"%s":%s.*}`, k, re), string(j))
-		if !match {
-			t.Error(fmt.Sprintf("`%s` output json does not match format %s. Got %s", k, re, j))
-		}
-	}
-
-}
-
-func TestNewLogsRes(t *testing.T) {
-	logs := make([]*state.Log, 3)
-	logs[0] = makeStateLog(1)
-	logs[1] = makeStateLog(2)
-	logs[2] = makeStateLog(3)
-	tests := map[string]string{}
-
-	v := NewLogsRes(logs)
-	j, _ := json.Marshal(v)
-
-	for k, re := range tests {
-		match, _ := regexp.MatchString(fmt.Sprintf(`[{.*"%s":%s.*}]`, k, re), string(j))
-		if !match {
-			t.Error(fmt.Sprintf("%s output json does not match format %s. Got %s", k, re, j))
-		}
-	}
-
-}
-
-func makeStateLog(num int) *state.Log {
-	address := common.HexToAddress("0x0")
-	data := []byte{1, 2, 3}
-	number := uint64(num)
-	topics := make([]common.Hash, 3)
-	topics = append(topics, common.HexToHash("0x00"))
-	topics = append(topics, common.HexToHash("0x10"))
-	topics = append(topics, common.HexToHash("0x20"))
-	log := state.NewLog(address, topics, data, number)
-	return log
-}
-
-func makeHeader() *types.Header {
-	header := &types.Header{
-		ParentHash:  common.StringToHash("0x00"),
-		UncleHash:   common.StringToHash("0x00"),
-		Coinbase:    common.StringToAddress("0x00"),
-		Root:        common.StringToHash("0x00"),
-		TxHash:      common.StringToHash("0x00"),
-		ReceiptHash: common.StringToHash("0x00"),
-		// Bloom:
-		Difficulty: big.NewInt(88888888),
-		Number:     big.NewInt(16),
-		GasLimit:   big.NewInt(70000),
-		GasUsed:    big.NewInt(25000),
-		Time:       124356789,
-		Extra:      nil,
-		MixDigest:  common.StringToHash("0x00"),
-		Nonce:      [8]byte{0, 1, 2, 3, 4, 5, 6, 7},
-	}
-	return header
-}
-
-func makeBlock() *types.Block {
-	parentHash := common.HexToHash("0x01")
-	coinbase := common.HexToAddress("0x01")
-	root := common.HexToHash("0x01")
-	difficulty := common.Big1
-	nonce := uint64(1)
-	block := types.NewBlock(parentHash, coinbase, root, difficulty, nonce, nil)
-
-	txto := common.HexToAddress("0x02")
-	txamount := big.NewInt(1)
-	txgasAmount := big.NewInt(1)
-	txgasPrice := big.NewInt(1)
-	txdata := []byte{1, 2, 3}
-
-	tx := types.NewTransactionMessage(txto, txamount, txgasAmount, txgasPrice, txdata)
-	txs := make([]*types.Transaction, 1)
-	txs[0] = tx
-	block.SetTransactions(txs)
-
-	uncles := make([]*types.Header, 1)
-	uncles[0] = makeHeader()
-	block.SetUncles(uncles)
-
-	return block
-}

+ 0 - 381
rpc/types.go

@@ -1,381 +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 (
-	"encoding/binary"
-	"encoding/hex"
-	"encoding/json"
-	"fmt"
-	"math/big"
-	"strings"
-
-	"errors"
-	"net"
-	"net/http"
-	"time"
-
-	"io"
-
-	"github.com/ethereum/go-ethereum/common"
-	"github.com/ethereum/go-ethereum/core/types"
-)
-
-type hexdata struct {
-	data  []byte
-	isNil bool
-}
-
-func (d *hexdata) String() string {
-	return "0x" + common.Bytes2Hex(d.data)
-}
-
-func (d *hexdata) MarshalJSON() ([]byte, error) {
-	if d.isNil {
-		return json.Marshal(nil)
-	}
-	return json.Marshal(d.String())
-}
-
-func newHexData(input interface{}) *hexdata {
-	d := new(hexdata)
-
-	if input == nil {
-		d.isNil = true
-		return d
-	}
-	switch input := input.(type) {
-	case []byte:
-		d.data = input
-	case common.Hash:
-		d.data = input.Bytes()
-	case *common.Hash:
-		if input == nil {
-			d.isNil = true
-		} else {
-			d.data = input.Bytes()
-		}
-	case common.Address:
-		d.data = input.Bytes()
-	case *common.Address:
-		if input == nil {
-			d.isNil = true
-		} else {
-			d.data = input.Bytes()
-		}
-	case types.Bloom:
-		d.data = input.Bytes()
-	case *types.Bloom:
-		if input == nil {
-			d.isNil = true
-		} else {
-			d.data = input.Bytes()
-		}
-	case *big.Int:
-		if input == nil {
-			d.isNil = true
-		} else {
-			d.data = input.Bytes()
-		}
-	case int64:
-		d.data = big.NewInt(input).Bytes()
-	case uint64:
-		buff := make([]byte, 8)
-		binary.BigEndian.PutUint64(buff, input)
-		d.data = buff
-	case int:
-		d.data = big.NewInt(int64(input)).Bytes()
-	case uint:
-		d.data = big.NewInt(int64(input)).Bytes()
-	case int8:
-		d.data = big.NewInt(int64(input)).Bytes()
-	case uint8:
-		d.data = big.NewInt(int64(input)).Bytes()
-	case int16:
-		d.data = big.NewInt(int64(input)).Bytes()
-	case uint16:
-		buff := make([]byte, 2)
-		binary.BigEndian.PutUint16(buff, input)
-		d.data = buff
-	case int32:
-		d.data = big.NewInt(int64(input)).Bytes()
-	case uint32:
-		buff := make([]byte, 4)
-		binary.BigEndian.PutUint32(buff, input)
-		d.data = buff
-	case string: // hexstring
-		// aaargh ffs TODO: avoid back-and-forth hex encodings where unneeded
-		bytes, err := hex.DecodeString(strings.TrimPrefix(input, "0x"))
-		if err != nil {
-			d.isNil = true
-		} else {
-			d.data = bytes
-		}
-	default:
-		d.isNil = true
-	}
-
-	return d
-}
-
-type hexnum struct {
-	data  []byte
-	isNil bool
-}
-
-func (d *hexnum) String() string {
-	// Get hex string from bytes
-	out := common.Bytes2Hex(d.data)
-	// Trim leading 0s
-	out = strings.TrimLeft(out, "0")
-	// Output "0x0" when value is 0
-	if len(out) == 0 {
-		out = "0"
-	}
-	return "0x" + out
-}
-
-func (d *hexnum) MarshalJSON() ([]byte, error) {
-	if d.isNil {
-		return json.Marshal(nil)
-	}
-	return json.Marshal(d.String())
-}
-
-func newHexNum(input interface{}) *hexnum {
-	d := new(hexnum)
-
-	d.data = newHexData(input).data
-
-	return d
-}
-
-type RpcConfig struct {
-	ListenAddress string
-	ListenPort    uint
-	CorsDomain    string
-}
-
-type InvalidTypeError struct {
-	method string
-	msg    string
-}
-
-func (e *InvalidTypeError) Error() string {
-	return fmt.Sprintf("invalid type on field %s: %s", e.method, e.msg)
-}
-
-func NewInvalidTypeError(method, msg string) *InvalidTypeError {
-	return &InvalidTypeError{
-		method: method,
-		msg:    msg,
-	}
-}
-
-type InsufficientParamsError struct {
-	have int
-	want int
-}
-
-func (e *InsufficientParamsError) Error() string {
-	return fmt.Sprintf("insufficient params, want %d have %d", e.want, e.have)
-}
-
-func NewInsufficientParamsError(have int, want int) *InsufficientParamsError {
-	return &InsufficientParamsError{
-		have: have,
-		want: want,
-	}
-}
-
-type NotImplementedError struct {
-	Method string
-}
-
-func (e *NotImplementedError) Error() string {
-	return fmt.Sprintf("%s method not implemented", e.Method)
-}
-
-func NewNotImplementedError(method string) *NotImplementedError {
-	return &NotImplementedError{
-		Method: method,
-	}
-}
-
-type NotAvailableError struct {
-	Method string
-	Reason string
-}
-
-func (e *NotAvailableError) Error() string {
-	return fmt.Sprintf("%s method not available: %s", e.Method, e.Reason)
-}
-
-func NewNotAvailableError(method string, reason string) *NotAvailableError {
-	return &NotAvailableError{
-		Method: method,
-		Reason: reason,
-	}
-}
-
-type DecodeParamError struct {
-	err string
-}
-
-func (e *DecodeParamError) Error() string {
-	return fmt.Sprintf("could not decode, %s", e.err)
-
-}
-
-func NewDecodeParamError(errstr string) error {
-	return &DecodeParamError{
-		err: errstr,
-	}
-}
-
-type ValidationError struct {
-	ParamName string
-	msg       string
-}
-
-func (e *ValidationError) Error() string {
-	return fmt.Sprintf("%s not valid, %s", e.ParamName, e.msg)
-}
-
-func NewValidationError(param string, msg string) error {
-	return &ValidationError{
-		ParamName: param,
-		msg:       msg,
-	}
-}
-
-type RpcRequest struct {
-	Id      interface{}     `json:"id"`
-	Jsonrpc string          `json:"jsonrpc"`
-	Method  string          `json:"method"`
-	Params  json.RawMessage `json:"params"`
-}
-
-type RpcSuccessResponse struct {
-	Id      interface{} `json:"id"`
-	Jsonrpc string      `json:"jsonrpc"`
-	Result  interface{} `json:"result"`
-}
-
-type RpcErrorResponse struct {
-	Id      interface{}     `json:"id"`
-	Jsonrpc string          `json:"jsonrpc"`
-	Error   *RpcErrorObject `json:"error"`
-}
-
-type RpcErrorObject struct {
-	Code    int    `json:"code"`
-	Message string `json:"message"`
-	// Data    interface{} `json:"data"`
-}
-
-type listenerHasStoppedError struct {
-	msg string
-}
-
-func (self listenerHasStoppedError) Error() string {
-	return self.msg
-}
-
-var listenerStoppedError = listenerHasStoppedError{"Listener stopped"}
-
-// When https://github.com/golang/go/issues/4674 is fixed this could be replaced
-type stoppableTCPListener struct {
-	*net.TCPListener
-	stop chan struct{} // closed when the listener must stop
-}
-
-// Wraps the default handler and checks if the RPC service was stopped. In that case it returns an
-// error indicating that the service was stopped. This will only happen for connections which are
-// kept open (HTTP keep-alive) when the RPC service was shutdown.
-func newStoppableHandler(h http.Handler, stop chan struct{}) http.Handler {
-	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		select {
-		case <-stop:
-			w.Header().Set("Content-Type", "application/json")
-			jsonerr := &RpcErrorObject{-32603, "RPC service stopped"}
-			send(w, &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: nil, Error: jsonerr})
-		default:
-			h.ServeHTTP(w, r)
-		}
-	})
-}
-
-// Stop the listener and all accepted and still active connections.
-func (self *stoppableTCPListener) Stop() {
-	close(self.stop)
-}
-
-func newStoppableTCPListener(addr string) (*stoppableTCPListener, error) {
-	wl, err := net.Listen("tcp", addr)
-	if err != nil {
-		return nil, err
-	}
-
-	if tcpl, ok := wl.(*net.TCPListener); ok {
-		stop := make(chan struct{})
-		l := &stoppableTCPListener{tcpl, stop}
-		return l, nil
-	}
-
-	return nil, errors.New("Unable to create TCP listener for RPC service")
-}
-
-func (self *stoppableTCPListener) Accept() (net.Conn, error) {
-	for {
-		self.SetDeadline(time.Now().Add(time.Duration(1 * time.Second)))
-		c, err := self.TCPListener.AcceptTCP()
-
-		select {
-		case <-self.stop:
-			if c != nil { // accept timeout
-				c.Close()
-			}
-			self.TCPListener.Close()
-			return nil, listenerStoppedError
-		default:
-		}
-
-		if err != nil {
-			if netErr, ok := err.(net.Error); ok && netErr.Timeout() && netErr.Temporary() {
-				continue // regular timeout
-			}
-		}
-
-		return &closableConnection{c, self.stop}, err
-	}
-}
-
-type closableConnection struct {
-	*net.TCPConn
-	closed chan struct{}
-}
-
-func (self *closableConnection) Read(b []byte) (n int, err error) {
-	select {
-	case <-self.closed:
-		self.TCPConn.Close()
-		return 0, io.EOF
-	default:
-		return self.TCPConn.Read(b)
-	}
-}

+ 0 - 204
rpc/types_test.go

@@ -1,204 +0,0 @@
-package rpc
-
-import (
-	"bytes"
-	"encoding/json"
-	"math/big"
-	"testing"
-
-	"github.com/ethereum/go-ethereum/common"
-	"github.com/ethereum/go-ethereum/core/types"
-)
-
-func TestInvalidTypeError(t *testing.T) {
-	err := NewInvalidTypeError("testField", "not string")
-	expected := "invalid type on field testField: not string"
-
-	if err.Error() != expected {
-		t.Error(err.Error())
-	}
-}
-
-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())
-	}
-}
-
-func TestHexdataMarshalNil(t *testing.T) {
-	hd := newHexData([]byte{})
-	hd.isNil = true
-	v, _ := json.Marshal(hd)
-	if string(v) != "null" {
-		t.Errorf("Expected null, got %s", v)
-	}
-}
-
-func TestHexnumMarshalNil(t *testing.T) {
-	hn := newHexNum([]byte{})
-	hn.isNil = true
-	v, _ := json.Marshal(hn)
-	if string(v) != "null" {
-		t.Errorf("Expected null, got %s", v)
-	}
-}
-
-func TestHexdataNil(t *testing.T) {
-	v := newHexData(nil)
-	if v.isNil != true {
-		t.Errorf("Expected isNil to be true, but is %v", v.isNil)
-	}
-}
-
-func TestHexdataPtrHash(t *testing.T) {
-	in := common.Hash{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}
-	v := newHexData(&in)
-	if bytes.Compare(in.Bytes(), v.data) != 0 {
-		t.Errorf("Got % x expected % x", in, v.data)
-	}
-}
-
-func TestHexdataPtrHashNil(t *testing.T) {
-	var in *common.Hash
-	in = nil
-	v := newHexData(in)
-	if !v.isNil {
-		t.Errorf("Expect isNil to be true, but is %v", v.isNil)
-	}
-}
-
-func TestHexdataPtrAddress(t *testing.T) {
-	in := common.Address{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
-	v := newHexData(&in)
-	if bytes.Compare(in.Bytes(), v.data) != 0 {
-		t.Errorf("Got % x expected % x", in, v.data)
-	}
-}
-
-func TestHexdataPtrAddressNil(t *testing.T) {
-	var in *common.Address
-	in = nil
-	v := newHexData(in)
-	if !v.isNil {
-		t.Errorf("Expect isNil to be true, but is %v", v.isNil)
-	}
-}
-
-func TestHexdataPtrBloom(t *testing.T) {
-	in := types.Bloom{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}
-	v := newHexData(&in)
-	if bytes.Compare(in.Bytes(), v.data) != 0 {
-		t.Errorf("Got % x expected % x", in, v.data)
-	}
-}
-
-func TestHexdataPtrBloomNil(t *testing.T) {
-	var in *types.Bloom
-	in = nil
-	v := newHexData(in)
-	if !v.isNil {
-		t.Errorf("Expect isNil to be true, but is %v", v.isNil)
-	}
-}
-
-func TestHexdataBigintNil(t *testing.T) {
-	var in *big.Int
-	in = nil
-	v := newHexData(in)
-	if !v.isNil {
-		t.Errorf("Expect isNil to be true, but is %v", v.isNil)
-	}
-}
-
-func TestHexdataUint(t *testing.T) {
-	var in = uint(16)
-	var expected = []byte{0x10}
-	v := newHexData(in)
-	if bytes.Compare(expected, v.data) != 0 {
-		t.Errorf("Expected % x got % x", expected, v.data)
-	}
-}
-
-func TestHexdataInt8(t *testing.T) {
-	var in = int8(16)
-	var expected = []byte{0x10}
-	v := newHexData(in)
-	if bytes.Compare(expected, v.data) != 0 {
-		t.Errorf("Expected % x got % x", expected, v.data)
-	}
-}
-
-func TestHexdataUint8(t *testing.T) {
-	var in = uint8(16)
-	var expected = []byte{0x10}
-	v := newHexData(in)
-	if bytes.Compare(expected, v.data) != 0 {
-		t.Errorf("Expected % x got % x", expected, v.data)
-	}
-}
-
-func TestHexdataInt16(t *testing.T) {
-	var in = int16(16)
-	var expected = []byte{0x10}
-	v := newHexData(in)
-	if bytes.Compare(expected, v.data) != 0 {
-		t.Errorf("Expected % x got % x", expected, v.data)
-	}
-}
-
-func TestHexdataUint16(t *testing.T) {
-	var in = uint16(16)
-	var expected = []byte{0x0, 0x10}
-	v := newHexData(in)
-	if bytes.Compare(expected, v.data) != 0 {
-		t.Errorf("Expected % x got % x", expected, v.data)
-	}
-}
-
-func TestHexdataInt32(t *testing.T) {
-	var in = int32(16)
-	var expected = []byte{0x10}
-	v := newHexData(in)
-	if bytes.Compare(expected, v.data) != 0 {
-		t.Errorf("Expected % x got % x", expected, v.data)
-	}
-}
-
-func TestHexdataUint32(t *testing.T) {
-	var in = uint32(16)
-	var expected = []byte{0x0, 0x0, 0x0, 0x10}
-	v := newHexData(in)
-	if bytes.Compare(expected, v.data) != 0 {
-		t.Errorf("Expected % x got % x", expected, v.data)
-	}
-}