From 1c62de0e962ecf97d26ea8302e82f6009a2cb17c Mon Sep 17 00:00:00 2001
From: Ethan Buchman <ethan@coinculture.info>
Date: Thu, 28 Apr 2016 13:12:20 -0400
Subject: [PATCH] working on the rpc. replace client

---
 erisdb/serve.go                   |   54 +-
 rpc/client/client.go              |  171 +++++
 rpc/core/accounts.go              |    3 +-
 rpc/core/mempool.go               |   38 ++
 rpc/core/routes.go                |  145 +++-
 rpc/core/types/responses.go       |   21 +-
 rpc/core_client/client.go         |  236 -------
 rpc/core_client/client_methods.go | 1042 -----------------------------
 rpc/core_client/log.go            |    7 -
 rpc/core_client/ws_client.go      |  119 ----
 state/types/genesis.go            |   10 +-
 tmsp/erisdb.go                    |    5 +-
 txs/tx.go                         |    7 +
 13 files changed, 418 insertions(+), 1440 deletions(-)
 create mode 100644 rpc/client/client.go
 create mode 100644 rpc/core/mempool.go
 delete mode 100644 rpc/core_client/client.go
 delete mode 100644 rpc/core_client/client_methods.go
 delete mode 100644 rpc/core_client/log.go
 delete mode 100644 rpc/core_client/ws_client.go

diff --git a/erisdb/serve.go b/erisdb/serve.go
index 63794326..0aa849a0 100644
--- a/erisdb/serve.go
+++ b/erisdb/serve.go
@@ -6,26 +6,34 @@ import (
 	"bytes"
 	"fmt"
 	"io/ioutil"
+	"net"
+	"net/http"
 	"path"
 	"strings"
 	"sync"
 
+	// tendermint support libs
 	. "github.com/tendermint/go-common"
 	cfg "github.com/tendermint/go-config"
 	dbm "github.com/tendermint/go-db"
 	"github.com/tendermint/go-events"
-	"github.com/tendermint/go-p2p"
+	rpcserver "github.com/tendermint/go-rpc/server"
 	"github.com/tendermint/go-wire"
 	"github.com/tendermint/log15"
 
+	// for inproc tendermint
+	"github.com/tendermint/go-p2p"
 	"github.com/tendermint/tendermint/node"
 	"github.com/tendermint/tendermint/proxy"
 	"github.com/tendermint/tendermint/types"
 	tmspcli "github.com/tendermint/tmsp/client"
+
+	// tmsp server
 	tmsp "github.com/tendermint/tmsp/server"
 
 	edbcfg "github.com/eris-ltd/eris-db/config"
 	ep "github.com/eris-ltd/eris-db/erisdb/pipe"
+	rpccore "github.com/eris-ltd/eris-db/rpc/core"
 	"github.com/eris-ltd/eris-db/server"
 	sm "github.com/eris-ltd/eris-db/state"
 	stypes "github.com/eris-ltd/eris-db/state/types"
@@ -126,7 +134,8 @@ func ServeErisDB(workDir string, inProc bool) (*server.ServeProcess, error) {
 	app.SetHostAddress(edbConf.Tendermint.Host)
 	if inProc {
 		fmt.Println("Starting tm node in proc")
-		startTMNode(app)
+		// will also start the go-rpc server (46657 api)
+		startTMNode(app, workDir)
 	} else {
 		fmt.Println("Starting tmsp listener")
 		// Start the tmsp listener for state update commands
@@ -161,7 +170,7 @@ func ServeErisDB(workDir string, inProc bool) (*server.ServeProcess, error) {
 }
 
 // start an inproc tendermint node
-func startTMNode(app *edbapp.ErisDBApp) {
+func startTMNode(app *edbapp.ErisDBApp, workDir string) {
 	// get the genesis
 	genDocFile := config.GetString("tm.genesis_file")
 	jsonBlob, err := ioutil.ReadFile(genDocFile)
@@ -199,9 +208,46 @@ func startTMNode(app *edbapp.ErisDBApp) {
 
 	// Run the RPC server.
 	if config.GetString("tm.rpc_laddr") != "" {
-		_, err := nd.StartRPC()
+		_, err := StartRPC(nd, app)
 		if err != nil {
 			PanicCrisis(err)
 		}
 	}
 }
+
+func StartRPC(n *node.Node, edbApp *edbapp.ErisDBApp) ([]net.Listener, error) {
+	rpccore.SetErisDBApp(edbApp)
+	rpccore.SetBlockStore(n.BlockStore())
+	rpccore.SetConsensusState(n.ConsensusState())
+	rpccore.SetConsensusReactor(n.ConsensusReactor())
+	rpccore.SetMempoolReactor(n.MempoolReactor())
+	rpccore.SetSwitch(n.Switch())
+	rpccore.SetPrivValidator(n.PrivValidator())
+	rpccore.SetGenDoc(LoadGenDoc())
+
+	listenAddrs := strings.Split(config.GetString("tm.rpc_laddr"), ",")
+
+	// we may expose the rpc over both a unix and tcp socket
+	listeners := make([]net.Listener, len(listenAddrs))
+	for i, listenAddr := range listenAddrs {
+		mux := http.NewServeMux()
+		wm := rpcserver.NewWebsocketManager(rpccore.Routes, n.EventSwitch())
+		mux.HandleFunc("/websocket", wm.WebsocketHandler)
+		rpcserver.RegisterRPCFuncs(mux, rpccore.Routes)
+		listener, err := rpcserver.StartHTTPServer(listenAddr, mux)
+		if err != nil {
+			return nil, err
+		}
+		listeners[i] = listener
+	}
+	return listeners, nil
+}
+
+func LoadGenDoc() *stypes.GenesisDoc {
+	genDocFile := config.GetString("tm.genesis_file")
+	jsonBlob, err := ioutil.ReadFile(genDocFile)
+	if err != nil {
+		Exit(Fmt("Couldn't read GenesisDoc file: %v", err))
+	}
+	return stypes.GenesisDocFromJSON(jsonBlob)
+}
diff --git a/rpc/client/client.go b/rpc/client/client.go
new file mode 100644
index 00000000..ac3cd270
--- /dev/null
+++ b/rpc/client/client.go
@@ -0,0 +1,171 @@
+package client
+
+import (
+	rpcclient "github.com/tendermint/go-rpc/client"
+
+	acm "github.com/eris-ltd/eris-db/account"
+	ctypes "github.com/eris-ltd/eris-db/rpc/core/types"
+	"github.com/eris-ltd/eris-db/txs"
+)
+
+func Status(client rpcclient.Client) (*ctypes.ResultStatus, error) {
+	var res ctypes.ErisDBResult //ResultStatus)
+	var err error
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call("status", []interface{}{}, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call("status", map[string]interface{}{}, &res)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return res.(*ctypes.ResultStatus), nil
+}
+
+func GenPrivAccount(client rpcclient.Client) (*acm.PrivAccount, error) {
+	var res ctypes.ErisDBResult
+	var err error
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call("unsafe/gen_priv_account", []interface{}{}, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call("unsafe/gen_priv_account", map[string]interface{}{}, &res)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return res.(*ctypes.ResultGenPrivAccount).PrivAccount, nil
+}
+
+func GetAccount(client rpcclient.Client, addr []byte) (*acm.Account, error) {
+	var res ctypes.ErisDBResult
+	var err error
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call("get_account", []interface{}{addr}, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call("get_account", map[string]interface{}{"address": addr}, &res)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return res.(*ctypes.ResultGetAccount).Account, nil
+}
+
+func SignTx(client rpcclient.Client, tx types.Tx, privAccs []*acm.PrivAccount) (types.Tx, error) {
+	wrapTx := struct {
+		types.Tx `json:"unwrap"`
+	}{tx}
+	var res ctypes.ErisDBResult
+	var err error
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call("unsafe/sign_tx", []interface{}{wrapTx, privAccs}, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call("unsafe/sign_tx", map[string]interface{}{"tx": wrapTx, "privAccounts": privAccs}, &res)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return res.(*ctypes.ResultSignTx).Tx, nil
+}
+
+func BroadcastTx(client rpcclient.Client, tx types.Tx) (ctypes.Receipt, error) {
+	wrapTx := struct {
+		types.Tx `json:"unwrap"`
+	}{tx}
+	var res ctypes.ErisDBResult
+	var err error
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call("broadcast_tx", []interface{}{wrapTx}, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call("broadcast_tx", map[string]interface{}{"tx": wrapTx}, &res)
+	}
+	if err != nil {
+		return ctypes.Receipt{}, err
+	}
+	data := res.(*ctypes.ResultBroadcastTx).Data
+	// TODO: unmarshal data to receuipt
+	_ = data
+	return ctypes.Receipt{}, err
+
+}
+
+func DumpStorage(client rpcclient.Client, addr []byte) (*ctypes.ResultDumpStorage, error) {
+	var res ctypes.ErisDBResult
+	var err error
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call("dump_storage", []interface{}{addr}, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call("dump_storage", map[string]interface{}{"address": addr}, &res)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return res.(*ctypes.ResultDumpStorage), err
+}
+
+func GetStorage(client rpcclient.Client, addr, key []byte) ([]byte, error) {
+	var res ctypes.ErisDBResult
+	var err error
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call("get_storage", []interface{}{addr, key}, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call("get_storage", map[string]interface{}{"address": addr, "key": key}, &res)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return res.(*ctypes.ResultGetStorage).Value, nil
+}
+
+func CallCode(client rpcclient.Client, fromAddress, code, data []byte) (*ctypes.ResultCall, error) {
+	var res ctypes.ErisDBResult
+	var err error
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call("call_code", []interface{}{fromAddress, code, data}, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call("call_code", map[string]interface{}{"fromAddress": fromAddress, "code": code, "data": data}, &res)
+
+	}
+	if err != nil {
+		return nil, err
+	}
+	return res.(*ctypes.ResultCall), err
+}
+
+func Call(client rpcclient.Client, fromAddress, toAddress, data []byte) (*ctypes.ResultCall, error) {
+	var res ctypes.ErisDBResult
+	var err error
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call("call", []interface{}{fromAddress, toAddress, data}, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call("call", map[string]interface{}{"fromAddress": fromAddress, "toAddress": toAddress, "data": data}, &res)
+
+	}
+	if err != nil {
+		return nil, err
+	}
+	return res.(*ctypes.ResultCall), err
+}
+
+func GetName(client rpcclient.Client, name string) (*types.NameRegEntry, error) {
+	var res ctypes.ErisDBResult
+	var err error
+	switch cli := client.(type) {
+	case *rpcclient.ClientJSONRPC:
+		_, err = cli.Call("get_name", []interface{}{name}, &res)
+	case *rpcclient.ClientURI:
+		_, err = cli.Call("get_name", map[string]interface{}{"name": name}, &res)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return res.(*ctypes.ResultGetName).Entry, nil
+}
diff --git a/rpc/core/accounts.go b/rpc/core/accounts.go
index 161a14af..ca236cfb 100644
--- a/rpc/core/accounts.go
+++ b/rpc/core/accounts.go
@@ -17,7 +17,8 @@ func GetAccount(address []byte) (*ctypes.ResultGetAccount, error) {
 	// cache := mempoolReactor.Mempool.GetCache()
 	account := cache.GetAccount(address)
 	if account == nil {
-		return nil, nil
+		log.Warn("Nil Account")
+		return &ctypes.ResultGetAccount{nil}, nil
 	}
 	return &ctypes.ResultGetAccount{account}, nil
 }
diff --git a/rpc/core/mempool.go b/rpc/core/mempool.go
new file mode 100644
index 00000000..47025a08
--- /dev/null
+++ b/rpc/core/mempool.go
@@ -0,0 +1,38 @@
+package core
+
+import (
+	"fmt"
+	ctypes "github.com/eris-ltd/eris-db/rpc/core/types"
+	txs "github.com/eris-ltd/eris-db/txs"
+	"github.com/tendermint/tendermint/types"
+	tmsp "github.com/tendermint/tmsp/types"
+)
+
+//-----------------------------------------------------------------------------
+
+// NOTE: tx must be signed
+func BroadcastTxAsync(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
+	err := mempoolReactor.BroadcastTx(tx, nil)
+	if err != nil {
+		return nil, fmt.Errorf("Error broadcasting transaction: %v", err)
+	}
+	return &ctypes.ResultBroadcastTx{}, nil
+}
+
+// Note: tx must be signed
+func BroadcastTxSync(tx txs.Tx) (*ctypes.ResultBroadcastTx, error) {
+	fmt.Println("BROADCAST!", tx)
+	resCh := make(chan *tmsp.Response, 1)
+	err := mempoolReactor.BroadcastTx(txs.EncodeTx(tx), func(res *tmsp.Response) {
+		resCh <- res
+	})
+	if err != nil {
+		return nil, fmt.Errorf("Error broadcasting transaction: %v", err)
+	}
+	res := <-resCh
+	return &ctypes.ResultBroadcastTx{
+		Code: res.Code,
+		Data: res.Data,
+		Log:  res.Log,
+	}, nil
+}
diff --git a/rpc/core/routes.go b/rpc/core/routes.go
index 9d8bf8f5..80eee8a2 100644
--- a/rpc/core/routes.go
+++ b/rpc/core/routes.go
@@ -1,29 +1,146 @@
 package core
 
 import (
+	acm "github.com/eris-ltd/eris-db/account"
+	ctypes "github.com/eris-ltd/eris-db/rpc/core/types"
+	"github.com/eris-ltd/eris-db/txs"
 	rpc "github.com/tendermint/go-rpc/server"
 )
 
 // TODO: eliminate redundancy between here and reading code from core/
 var Routes = map[string]*rpc.RPCFunc{
-	"status":   rpc.NewRPCFunc(Status, ""),
-	"net_info": rpc.NewRPCFunc(NetInfo, ""),
+	"status":                  rpc.NewRPCFunc(StatusResult, ""),
+	"net_info":                rpc.NewRPCFunc(NetInfoResult, ""),
+	"genesis":                 rpc.NewRPCFunc(GenesisResult, ""),
+	"get_account":             rpc.NewRPCFunc(GetAccountResult, "address"),
+	"get_storage":             rpc.NewRPCFunc(GetStorageResult, "address,key"),
+	"call":                    rpc.NewRPCFunc(CallResult, "fromAddress,toAddress,data"),
+	"call_code":               rpc.NewRPCFunc(CallCodeResult, "fromAddress,code,data"),
+	"dump_storage":            rpc.NewRPCFunc(DumpStorageResult, "address"),
+	"list_accounts":           rpc.NewRPCFunc(ListAccountsResult, ""),
+	"get_name":                rpc.NewRPCFunc(GetNameResult, "name"),
+	"list_names":              rpc.NewRPCFunc(ListNamesResult, ""),
+	"broadcast_tx":            rpc.NewRPCFunc(BroadcastTxResult, "tx"),
+	"unsafe/gen_priv_account": rpc.NewRPCFunc(GenPrivAccountResult, ""),
+	"unsafe/sign_tx":          rpc.NewRPCFunc(SignTxResult, "tx,privAccounts"),
+
+	// TODO: hookup
 	//	"blockchain":              rpc.NewRPCFunc(BlockchainInfo, "minHeight,maxHeight"),
-	"genesis": rpc.NewRPCFunc(Genesis, ""),
 	//	"get_block":               rpc.NewRPCFunc(GetBlock, "height"),
-	"get_account": rpc.NewRPCFunc(GetAccount, "address"),
-	"get_storage": rpc.NewRPCFunc(GetStorage, "address,key"),
-	"call":        rpc.NewRPCFunc(Call, "fromAddress,toAddress,data"),
-	"call_code":   rpc.NewRPCFunc(CallCode, "fromAddress,code,data"),
 	//"list_validators":         rpc.NewRPCFunc(ListValidators, ""),
 	// "dump_consensus_state":    rpc.NewRPCFunc(DumpConsensusState, ""),
-	"dump_storage": rpc.NewRPCFunc(DumpStorage, "address"),
-	// "broadcast_tx":            rpc.NewRPCFunc(BroadcastTx, "tx"),
 	// "list_unconfirmed_txs":    rpc.NewRPCFunc(ListUnconfirmedTxs, ""),
-	"list_accounts":           rpc.NewRPCFunc(ListAccounts, ""),
-	"get_name":                rpc.NewRPCFunc(GetName, "name"),
-	"list_names":              rpc.NewRPCFunc(ListNames, ""),
-	"unsafe/gen_priv_account": rpc.NewRPCFunc(GenPrivAccount, ""),
-	"unsafe/sign_tx":          rpc.NewRPCFunc(SignTx, "tx,privAccounts"),
 	// subscribe/unsubscribe are reserved for websocket events.
 }
+
+func StatusResult() (ctypes.ErisDBResult, error) {
+	if r, err := Status(); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func NetInfoResult() (ctypes.ErisDBResult, error) {
+	if r, err := NetInfo(); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func GenesisResult() (ctypes.ErisDBResult, error) {
+	if r, err := Genesis(); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func GetAccountResult(address []byte) (ctypes.ErisDBResult, error) {
+	if r, err := GetAccount(address); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func GetStorageResult(address, key []byte) (ctypes.ErisDBResult, error) {
+	if r, err := GetStorage(address, key); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func CallResult(fromAddress, toAddress, data []byte) (ctypes.ErisDBResult, error) {
+	if r, err := Call(fromAddress, toAddress, data); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func CallCodeResult(fromAddress, code, data []byte) (ctypes.ErisDBResult, error) {
+	if r, err := CallCode(fromAddress, code, data); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func DumpStorageResult(address []byte) (ctypes.ErisDBResult, error) {
+	if r, err := DumpStorage(address); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func ListAccountsResult() (ctypes.ErisDBResult, error) {
+	if r, err := ListAccounts(); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func GetNameResult(name string) (ctypes.ErisDBResult, error) {
+	if r, err := GetName(name); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func ListNamesResult() (ctypes.ErisDBResult, error) {
+	if r, err := ListNames(); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func GenPrivAccountResult() (ctypes.ErisDBResult, error) {
+	if r, err := GenPrivAccount(); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func SignTxResult(tx types.Tx, privAccounts []*acm.PrivAccount) (ctypes.ErisDBResult, error) {
+	if r, err := SignTx(tx, privAccounts); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
+
+func BroadcastTxResult(tx types.Tx) (ctypes.ErisDBResult, error) {
+	if r, err := BroadcastTxSync(tx); err != nil {
+		return nil, err
+	} else {
+		return r, nil
+	}
+}
diff --git a/rpc/core/types/responses.go b/rpc/core/types/responses.go
index c1718dbe..d8a9a61b 100644
--- a/rpc/core/types/responses.go
+++ b/rpc/core/types/responses.go
@@ -8,7 +8,9 @@ import (
 
 	"github.com/tendermint/go-crypto"
 	"github.com/tendermint/go-p2p"
+	"github.com/tendermint/go-rpc/types"
 	"github.com/tendermint/go-wire"
+	tmsptypes "github.com/tendermint/tmsp/types"
 )
 
 type ResultGetStorage struct {
@@ -92,7 +94,9 @@ type ResultGetAccount struct {
 }
 
 type ResultBroadcastTx struct {
-	Receipt Receipt `json:"receipt"`
+	Code tmsptypes.CodeType `json:"code"`
+	Data []byte             `json:"data"`
+	Log  string             `json:"log"`
 }
 
 type Receipt struct {
@@ -124,14 +128,7 @@ type ResultEvent struct {
 }
 
 //----------------------------------------
-// response & result types
-
-type Response struct {
-	JSONRPC string `json:"jsonrpc"`
-	ID      string `json:"id"`
-	Result  Result `json:"result"`
-	Error   string `json:"error"`
-}
+// result types
 
 const (
 	ResultTypeGetStorage         = byte(0x01)
@@ -155,11 +152,13 @@ const (
 	ResultTypeEvent              = byte(0x13) // so websockets can respond to rpc functions
 )
 
-type Result interface{}
+type ErisDBResult interface {
+	rpctypes.Result
+}
 
 // for wire.readReflect
 var _ = wire.RegisterInterface(
-	struct{ Result }{},
+	struct{ ErisDBResult }{},
 	wire.ConcreteType{&ResultGetStorage{}, ResultTypeGetStorage},
 	wire.ConcreteType{&ResultCall{}, ResultTypeCall},
 	wire.ConcreteType{&ResultListAccounts{}, ResultTypeListAccounts},
diff --git a/rpc/core_client/client.go b/rpc/core_client/client.go
deleted file mode 100644
index f95eadfb..00000000
--- a/rpc/core_client/client.go
+++ /dev/null
@@ -1,236 +0,0 @@
-package core_client
-
-import (
-	"bytes"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"net/url"
-
-	ctypes "github.com/eris-ltd/eris-db/rpc/core/types"
-	rpctypes "github.com/tendermint/go-rpc/types"
-	"github.com/tendermint/go-wire"
-	//"reflect"
-	// Uncomment to use go:generate
-	// _ "github.com/tendermint/go-rpc-gen"
-)
-
-// maps camel-case function names to lower case rpc version
-var reverseFuncMap = map[string]string{
-	"Status":             "status",
-	"NetInfo":            "net_info",
-	"BlockchainInfo":     "blockchain",
-	"Genesis":            "genesis",
-	"GetBlock":           "get_block",
-	"GetAccount":         "get_account",
-	"GetStorage":         "get_storage",
-	"Call":               "call",
-	"CallCode":           "call_code",
-	"ListValidators":     "list_validators",
-	"DumpConsensusState": "dump_consensus_state",
-	"DumpStorage":        "dump_storage",
-	"BroadcastTx":        "broadcast_tx",
-	"ListUnconfirmedTxs": "list_unconfirmed_txs",
-	"ListAccounts":       "list_accounts",
-	"GetName":            "get_name",
-	"ListNames":          "list_names",
-	"GenPrivAccount":     "unsafe/gen_priv_account",
-	"SignTx":             "unsafe/sign_tx",
-}
-
-/*
-// fill the map from camelcase to lowercase
-func fillReverseFuncMap() map[string]string {
-	fMap := make(map[string]string)
-	for name, f := range core.Routes {
-		camelName := runtime.FuncForPC(f.f.Pointer()).Name()
-		spl := strings.Split(camelName, ".")
-		if len(spl) > 1 {
-			camelName = spl[len(spl)-1]
-		}
-		fMap[camelName] = name
-	}
-	return fMap
-}
-*/
-
-type Response struct {
-	Status string
-	Data   interface{}
-	Error  string
-}
-
-//go:generate go-rpc-gen -interface Client -dir ../core -pkg core -type *ClientHTTP,*ClientJSON -exclude pipe.go -out-pkg core_client
-
-type ClientJSON struct {
-	addr string
-}
-
-type ClientHTTP struct {
-	addr string
-}
-
-func NewClient(addr, typ string) Client {
-	switch typ {
-	case "HTTP":
-		return &ClientHTTP{addr}
-	case "JSONRPC":
-		return &ClientJSON{addr}
-	default:
-		panic("Unknown client type " + typ + ". Select HTTP or JSONRPC")
-	}
-	return nil
-}
-
-func argsToJson(args ...interface{}) ([]string, error) {
-	l := len(args)
-	jsons := make([]string, l)
-	n, err := new(int), new(error)
-	for i, a := range args {
-		buf := new(bytes.Buffer)
-		wire.WriteJSON(a, buf, n, err)
-		if *err != nil {
-			return nil, *err
-		}
-		jsons[i] = string(buf.Bytes())
-	}
-	return jsons, nil
-}
-
-func (c *ClientJSON) RequestResponse(s rpctypes.RPCRequest) (b []byte, err error) {
-	b = wire.JSONBytes(s)
-	buf := bytes.NewBuffer(b)
-	resp, err := http.Post(c.addr, "text/json", buf)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	return ioutil.ReadAll(resp.Body)
-}
-
-/*
-	What follows is used by `rpc-gen` when `go generate` is called
-	to populate the rpc client methods
-*/
-
-// first we define the base interface, which rpc-gen will further populate with generated methods
-
-/*rpc-gen:define-interface Client
-type Client interface {
-	Address() string // returns the remote address
-}
-*/
-
-// encoding functions
-
-func binaryWriter(args ...interface{}) ([]interface{}, error) {
-	list := []interface{}{}
-	for _, a := range args {
-		buf, n, err := new(bytes.Buffer), new(int), new(error)
-		wire.WriteJSON(a, buf, n, err)
-		if *err != nil {
-			return nil, *err
-		}
-		list = append(list, buf.Bytes())
-
-	}
-	return list, nil
-}
-
-func argsToURLValues(argNames []string, args ...interface{}) (url.Values, error) {
-	values := make(url.Values)
-	if len(argNames) == 0 {
-		return values, nil
-	}
-	if len(argNames) != len(args) {
-		return nil, fmt.Errorf("argNames and args have different lengths: %d, %d", len(argNames), len(args))
-	}
-	slice, err := argsToJson(args...)
-	if err != nil {
-		return nil, err
-	}
-	for i, name := range argNames {
-		s := slice[i]
-		values.Set(name, s) // s[0]
-		/*for j := 1; j < len(s); j++ {
-			values.Add(name, s[j])
-		}*/
-	}
-	return values, nil
-}
-
-func unmarshalCheckResponse(body []byte) (response *ctypes.Response, err error) {
-	response = new(ctypes.Response)
-	wire.ReadJSON(response, body, &err)
-	if err != nil {
-		return nil, err
-	}
-	if response.Error != "" {
-		return nil, fmt.Errorf(response.Error)
-	}
-	return response, nil
-}
-
-// import statements we will need for the templates
-
-/*rpc-gen:imports:
-rpctypes github.com/tendermint/tendermint/rpc/types
-net/http
-io/ioutil
-fmt
-*/
-
-// Template functions to be filled in
-
-/*rpc-gen:template:*ClientJSON func (c *ClientJSON) {{name}}({{args.def}}) ({{response}}) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["{{name}}"],
-		Params:  []interface{}{ {{args.ident}} },
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil{
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil{
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.({{response.0}})
-	if !ok{
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}*/
-
-/*rpc-gen:template:*ClientHTTP func (c *ClientHTTP) {{name}}({{args.def}}) ({{response}}){
-	values, err := argsToURLValues({{args.name}}, {{args.ident}})
-	if err != nil{
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["{{name}}"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil{
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.({{response.0}})
-	if !ok{
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}*/
diff --git a/rpc/core_client/client_methods.go b/rpc/core_client/client_methods.go
deleted file mode 100644
index dd1848c4..00000000
--- a/rpc/core_client/client_methods.go
+++ /dev/null
@@ -1,1042 +0,0 @@
-// File generated by github.com/ebuchman/rpc-gen
-
-package core_client
-
-import (
-	"fmt"
-	acm "github.com/eris-ltd/eris-db/account"
-	ctypes "github.com/eris-ltd/eris-db/rpc/core/types"
-	"github.com/eris-ltd/eris-db/txs"
-	rpctypes "github.com/tendermint/go-rpc/types"
-	"io/ioutil"
-	"net/http"
-)
-
-type Client interface {
-	BlockchainInfo(minHeight int, maxHeight int) (*ctypes.ResultBlockchainInfo, error)
-	BroadcastTx(tx types.Tx) (*ctypes.ResultBroadcastTx, error)
-	Call(fromAddress []byte, toAddress []byte, data []byte) (*ctypes.ResultCall, error)
-	CallCode(fromAddress []byte, code []byte, data []byte) (*ctypes.ResultCall, error)
-	DumpConsensusState() (*ctypes.ResultDumpConsensusState, error)
-	DumpStorage(address []byte) (*ctypes.ResultDumpStorage, error)
-	GenPrivAccount() (*ctypes.ResultGenPrivAccount, error)
-	Genesis() (*ctypes.ResultGenesis, error)
-	GetAccount(address []byte) (*ctypes.ResultGetAccount, error)
-	GetBlock(height int) (*ctypes.ResultGetBlock, error)
-	GetName(name string) (*ctypes.ResultGetName, error)
-	GetStorage(address []byte, key []byte) (*ctypes.ResultGetStorage, error)
-	ListAccounts() (*ctypes.ResultListAccounts, error)
-	ListNames() (*ctypes.ResultListNames, error)
-	ListUnconfirmedTxs() (*ctypes.ResultListUnconfirmedTxs, error)
-	ListValidators() (*ctypes.ResultListValidators, error)
-	NetInfo() (*ctypes.ResultNetInfo, error)
-	SignTx(tx types.Tx, privAccounts []*acm.PrivAccount) (*ctypes.ResultSignTx, error)
-	Status() (*ctypes.ResultStatus, error)
-}
-
-func (c *ClientHTTP) BlockchainInfo(minHeight int, maxHeight int) (*ctypes.ResultBlockchainInfo, error) {
-	values, err := argsToURLValues([]string{"minHeight", "maxHeight"}, minHeight, maxHeight)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["BlockchainInfo"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultBlockchainInfo)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) BroadcastTx(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
-	values, err := argsToURLValues([]string{"tx"}, tx)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["BroadcastTx"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultBroadcastTx)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) Call(fromAddress []byte, toAddress []byte, data []byte) (*ctypes.ResultCall, error) {
-	values, err := argsToURLValues([]string{"fromAddress", "toAddress", "data"}, fromAddress, toAddress, data)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["Call"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultCall)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) CallCode(fromAddress []byte, code []byte, data []byte) (*ctypes.ResultCall, error) {
-	values, err := argsToURLValues([]string{"fromAddress", "code", "data"}, fromAddress, code, data)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["CallCode"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultCall)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) {
-	values, err := argsToURLValues(nil)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["DumpConsensusState"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultDumpConsensusState)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) DumpStorage(address []byte) (*ctypes.ResultDumpStorage, error) {
-	values, err := argsToURLValues([]string{"address"}, address)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["DumpStorage"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultDumpStorage)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) GenPrivAccount() (*ctypes.ResultGenPrivAccount, error) {
-	values, err := argsToURLValues(nil)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["GenPrivAccount"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGenPrivAccount)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) Genesis() (*ctypes.ResultGenesis, error) {
-	values, err := argsToURLValues(nil)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["Genesis"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGenesis)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) GetAccount(address []byte) (*ctypes.ResultGetAccount, error) {
-	values, err := argsToURLValues([]string{"address"}, address)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["GetAccount"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGetAccount)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) GetBlock(height int) (*ctypes.ResultGetBlock, error) {
-	values, err := argsToURLValues([]string{"height"}, height)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["GetBlock"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGetBlock)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) GetName(name string) (*ctypes.ResultGetName, error) {
-	values, err := argsToURLValues([]string{"name"}, name)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["GetName"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGetName)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) GetStorage(address []byte, key []byte) (*ctypes.ResultGetStorage, error) {
-	values, err := argsToURLValues([]string{"address", "key"}, address, key)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["GetStorage"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGetStorage)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) ListAccounts() (*ctypes.ResultListAccounts, error) {
-	values, err := argsToURLValues(nil)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["ListAccounts"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultListAccounts)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) ListNames() (*ctypes.ResultListNames, error) {
-	values, err := argsToURLValues(nil)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["ListNames"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultListNames)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) ListUnconfirmedTxs() (*ctypes.ResultListUnconfirmedTxs, error) {
-	values, err := argsToURLValues(nil)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["ListUnconfirmedTxs"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultListUnconfirmedTxs)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) ListValidators() (*ctypes.ResultListValidators, error) {
-	values, err := argsToURLValues(nil)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["ListValidators"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultListValidators)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) NetInfo() (*ctypes.ResultNetInfo, error) {
-	values, err := argsToURLValues(nil)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["NetInfo"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultNetInfo)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) SignTx(tx types.Tx, privAccounts []*acm.PrivAccount) (*ctypes.ResultSignTx, error) {
-	values, err := argsToURLValues([]string{"tx", "privAccounts"}, tx, privAccounts)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["SignTx"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultSignTx)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientHTTP) Status() (*ctypes.ResultStatus, error) {
-	values, err := argsToURLValues(nil)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := http.PostForm(c.addr+reverseFuncMap["Status"], values)
-	if err != nil {
-		return nil, err
-	}
-	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultStatus)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) BlockchainInfo(minHeight int, maxHeight int) (*ctypes.ResultBlockchainInfo, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["BlockchainInfo"],
-		Params:  []interface{}{minHeight, maxHeight},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultBlockchainInfo)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) BroadcastTx(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["BroadcastTx"],
-		Params:  []interface{}{tx},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultBroadcastTx)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) Call(fromAddress []byte, toAddress []byte, data []byte) (*ctypes.ResultCall, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["Call"],
-		Params:  []interface{}{fromAddress, toAddress, data},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultCall)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) CallCode(fromAddress []byte, code []byte, data []byte) (*ctypes.ResultCall, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["CallCode"],
-		Params:  []interface{}{fromAddress, code, data},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultCall)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["DumpConsensusState"],
-		Params:  []interface{}{},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultDumpConsensusState)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) DumpStorage(address []byte) (*ctypes.ResultDumpStorage, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["DumpStorage"],
-		Params:  []interface{}{address},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultDumpStorage)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) GenPrivAccount() (*ctypes.ResultGenPrivAccount, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["GenPrivAccount"],
-		Params:  []interface{}{},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGenPrivAccount)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) Genesis() (*ctypes.ResultGenesis, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["Genesis"],
-		Params:  []interface{}{},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGenesis)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) GetAccount(address []byte) (*ctypes.ResultGetAccount, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["GetAccount"],
-		Params:  []interface{}{address},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGetAccount)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) GetBlock(height int) (*ctypes.ResultGetBlock, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["GetBlock"],
-		Params:  []interface{}{height},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGetBlock)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) GetName(name string) (*ctypes.ResultGetName, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["GetName"],
-		Params:  []interface{}{name},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGetName)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) GetStorage(address []byte, key []byte) (*ctypes.ResultGetStorage, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["GetStorage"],
-		Params:  []interface{}{address, key},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultGetStorage)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) ListAccounts() (*ctypes.ResultListAccounts, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["ListAccounts"],
-		Params:  []interface{}{},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultListAccounts)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) ListNames() (*ctypes.ResultListNames, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["ListNames"],
-		Params:  []interface{}{},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultListNames)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) ListUnconfirmedTxs() (*ctypes.ResultListUnconfirmedTxs, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["ListUnconfirmedTxs"],
-		Params:  []interface{}{},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultListUnconfirmedTxs)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) ListValidators() (*ctypes.ResultListValidators, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["ListValidators"],
-		Params:  []interface{}{},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultListValidators)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) NetInfo() (*ctypes.ResultNetInfo, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["NetInfo"],
-		Params:  []interface{}{},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultNetInfo)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) SignTx(tx types.Tx, privAccounts []*acm.PrivAccount) (*ctypes.ResultSignTx, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["SignTx"],
-		Params:  []interface{}{tx, privAccounts},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultSignTx)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
-
-func (c *ClientJSON) Status() (*ctypes.ResultStatus, error) {
-	request := rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		Method:  reverseFuncMap["Status"],
-		Params:  []interface{}{},
-		ID:      "",
-	}
-	body, err := c.RequestResponse(request)
-	if err != nil {
-		return nil, err
-	}
-	response, err := unmarshalCheckResponse(body)
-	if err != nil {
-		return nil, err
-	}
-	if response.Result == nil {
-		return nil, nil
-	}
-	result, ok := response.Result.(*ctypes.ResultStatus)
-	if !ok {
-		return nil, fmt.Errorf("response result was wrong type")
-	}
-	return result, nil
-}
diff --git a/rpc/core_client/log.go b/rpc/core_client/log.go
deleted file mode 100644
index 54b638dc..00000000
--- a/rpc/core_client/log.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package core_client
-
-import (
-	"github.com/tendermint/log15"
-)
-
-var log = log15.New("module", "core_client")
diff --git a/rpc/core_client/ws_client.go b/rpc/core_client/ws_client.go
deleted file mode 100644
index fbd3619b..00000000
--- a/rpc/core_client/ws_client.go
+++ /dev/null
@@ -1,119 +0,0 @@
-package core_client
-
-import (
-	"net/http"
-	"strings"
-	"time"
-
-	ctypes "github.com/eris-ltd/eris-db/rpc/core/types"
-	"github.com/gorilla/websocket"
-	. "github.com/tendermint/go-common"
-	"github.com/tendermint/go-rpc/types"
-	"github.com/tendermint/go-wire"
-)
-
-const (
-	wsEventsChannelCapacity  = 10
-	wsResultsChannelCapacity = 10
-	wsWriteTimeoutSeconds    = 10
-)
-
-type WSClient struct {
-	QuitService
-	Address string
-	*websocket.Conn
-	EventsCh  chan ctypes.ResultEvent
-	ResultsCh chan ctypes.Result
-}
-
-// create a new connection
-func NewWSClient(addr string) *WSClient {
-	wsClient := &WSClient{
-		Address:   addr,
-		Conn:      nil,
-		EventsCh:  make(chan ctypes.ResultEvent, wsEventsChannelCapacity),
-		ResultsCh: make(chan ctypes.Result, wsResultsChannelCapacity),
-	}
-	wsClient.QuitService = *NewQuitService(log, "WSClient", wsClient)
-	return wsClient
-}
-
-func (wsc *WSClient) OnStart() error {
-	wsc.QuitService.OnStart()
-	err := wsc.dial()
-	if err != nil {
-		return err
-	}
-	go wsc.receiveEventsRoutine()
-	return nil
-}
-
-func (wsc *WSClient) dial() error {
-	// Dial
-	dialer := websocket.DefaultDialer
-	rHeader := http.Header{}
-	con, _, err := dialer.Dial(wsc.Address, rHeader)
-	if err != nil {
-		return err
-	}
-	// Set the ping/pong handlers
-	con.SetPingHandler(func(m string) error {
-		con.WriteControl(websocket.PongMessage, []byte(m), time.Now().Add(time.Second*wsWriteTimeoutSeconds))
-		return nil
-	})
-	con.SetPongHandler(func(m string) error {
-		return nil
-	})
-	wsc.Conn = con
-	return nil
-}
-
-func (wsc *WSClient) OnStop() {
-	wsc.QuitService.OnStop()
-}
-
-func (wsc *WSClient) receiveEventsRoutine() {
-	for {
-		_, data, err := wsc.ReadMessage()
-		if err != nil {
-			log.Info("WSClient failed to read message", "error", err, "data", string(data))
-			wsc.Stop()
-			break
-		} else {
-			var response ctypes.Response
-			wire.ReadJSON(&response, data, &err)
-			if err != nil {
-				log.Info("WSClient failed to parse message", "error", err)
-				wsc.Stop()
-				break
-			}
-			if strings.HasSuffix(response.ID, "#event") {
-				wsc.EventsCh <- *response.Result.(*ctypes.ResultEvent)
-			} else {
-				wsc.ResultsCh <- response.Result
-			}
-		}
-	}
-}
-
-// subscribe to an event
-func (wsc *WSClient) Subscribe(eventid string) error {
-	err := wsc.WriteJSON(rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		ID:      "",
-		Method:  "subscribe",
-		Params:  []interface{}{eventid},
-	})
-	return err
-}
-
-// unsubscribe from an event
-func (wsc *WSClient) Unsubscribe(eventid string) error {
-	err := wsc.WriteJSON(rpctypes.RPCRequest{
-		JSONRPC: "2.0",
-		ID:      "",
-		Method:  "unsubscribe",
-		Params:  []interface{}{eventid},
-	})
-	return err
-}
diff --git a/state/types/genesis.go b/state/types/genesis.go
index 8886da40..806d701b 100644
--- a/state/types/genesis.go
+++ b/state/types/genesis.go
@@ -3,10 +3,10 @@ package types
 import (
 	"time"
 
+	ptypes "github.com/eris-ltd/eris-db/permission/types"
 	. "github.com/tendermint/go-common"
 	"github.com/tendermint/go-crypto"
 	"github.com/tendermint/go-wire"
-	ptypes "github.com/eris-ltd/eris-db/permission/types"
 )
 
 //------------------------------------------------------------
@@ -30,10 +30,10 @@ type GenesisAccount struct {
 }
 
 type GenesisValidator struct {
-	PubKey   crypto.PubKeyEd25519 `json:"pub_key"`
-	Amount   int64                `json:"amount"`
-	Name     string               `json:"name"`
-	UnbondTo []BasicAccount       `json:"unbond_to"`
+	PubKey   crypto.PubKey  `json:"pub_key"`
+	Amount   int64          `json:"amount"`
+	Name     string         `json:"name"`
+	UnbondTo []BasicAccount `json:"unbond_to"`
 }
 
 type GenesisParams struct {
diff --git a/tmsp/erisdb.go b/tmsp/erisdb.go
index 514f2198..ae31612f 100644
--- a/tmsp/erisdb.go
+++ b/tmsp/erisdb.go
@@ -60,7 +60,6 @@ func (app *ErisDBApp) SetHostAddress(host string) {
 // Broadcast a tx to the tendermint core
 // NOTE: this assumes we know the address of core
 func (app *ErisDBApp) BroadcastTx(tx types.Tx) error {
-	var result ctypes.TMResult
 	buf := new(bytes.Buffer)
 	var n int
 	var err error
@@ -72,6 +71,8 @@ func (app *ErisDBApp) BroadcastTx(tx types.Tx) error {
 	params := map[string]interface{}{
 		"tx": hex.EncodeToString(buf.Bytes()),
 	}
+
+	var result ctypes.TMResult
 	_, err = app.client.Call("broadcast_tx_sync", params, &result)
 	return err
 }
@@ -117,6 +118,7 @@ func (app *ErisDBApp) AppendTx(txBytes []byte) (res tmsp.Result) {
 	if err != nil {
 		return tmsp.NewError(tmsp.CodeType_InternalError, fmt.Sprintf("Internal error: %v", err))
 	}
+	// TODO: need to return receipt so rpc.ResultBroadcastTx.Data (or Log) is the receipt
 	return tmsp.NewResultOK(nil, "Success")
 }
 
@@ -139,6 +141,7 @@ func (app *ErisDBApp) CheckTx(txBytes []byte) (res tmsp.Result) {
 		return tmsp.NewError(tmsp.CodeType_InternalError, fmt.Sprintf("Internal error: %v", err))
 	}
 
+	// TODO: need to return receipt so rpc.ResultBroadcastTx.Data (or Log) is the receipt
 	return tmsp.NewResultOK(nil, "Success")
 }
 
diff --git a/txs/tx.go b/txs/tx.go
index 37805cfc..d84807ed 100644
--- a/txs/tx.go
+++ b/txs/tx.go
@@ -369,6 +369,13 @@ func TxID(chainID string, tx Tx) []byte {
 
 //-----------------------------------------------------------------------------
 
+func EncodeTx(tx Tx) []byte {
+	wrapTx := struct {
+		Tx Tx `json:"unwrap"`
+	}{tx}
+	return wire.JSONBytes(wrapTx)
+}
+
 // panic on err
 func DecodeTx(txBytes []byte) Tx {
 	var n int
-- 
GitLab