diff --git a/cmd/geth/js.go b/cmd/geth/js.go index 761943b63..c0c77c02a 100644 --- a/cmd/geth/js.go +++ b/cmd/geth/js.go @@ -41,6 +41,7 @@ import ( "github.com/ethereum/go-ethereum/xeth" "github.com/peterh/liner" "github.com/robertkrimen/otto" + "github.com/ethereum/go-ethereum/rpc/shared" ) type prompter interface { @@ -183,7 +184,9 @@ func newJSRE(ethereum *eth.Ethereum, libPath, corsDomain string, client comms.Et js.wait = js.xeth.UpdateState() js.client = client if clt, ok := js.client.(*comms.InProcClient); ok { - clt.Initialize(js.xeth, ethereum) + if offeredApis, err := api.ParseApiString(shared.AllApis, codec.JSON, js.xeth, ethereum); err == nil { + clt.Initialize(api.Merge(offeredApis...)) + } } // update state in separare forever blocks @@ -311,7 +314,7 @@ func (js *jsre) apiBindings(f xeth.Frontend) error { // load only supported API's in javascript runtime shortcuts := "var eth = web3.eth; " for _, apiName := range apiNames { - if apiName == api.Web3ApiName || apiName == api.EthApiName { + if apiName == shared.Web3ApiName || apiName == shared.EthApiName { continue // manually mapped } diff --git a/cmd/geth/js_test.go b/cmd/geth/js_test.go index fba575030..cfbe26bee 100644 --- a/cmd/geth/js_test.go +++ b/cmd/geth/js_test.go @@ -210,7 +210,7 @@ func TestRPC(t *testing.T) { defer ethereum.Stop() defer os.RemoveAll(tmp) - checkEvalJSON(t, repl, `admin.startRPC("127.0.0.1", 5004)`, `true`) + checkEvalJSON(t, repl, `admin.startRPC("127.0.0.1", 5004, "*", "web3,eth,net")`, `true`) } func TestCheckTestAccountBalance(t *testing.T) { diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index a9d449d1f..15a577a07 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -461,7 +461,7 @@ func StartIPC(eth *eth.Ethereum, ctx *cli.Context) error { return err } - return comms.StartIpc(config, codec, apis...) + return comms.StartIpc(config, codec, api.Merge(apis...)) } func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error { @@ -479,7 +479,7 @@ func StartRPC(eth *eth.Ethereum, ctx *cli.Context) error { return err } - return comms.StartHttp(config, codec, apis...) + return comms.StartHttp(config, codec, api.Merge(apis...)) } func StartPProf(ctx *cli.Context) { diff --git a/rpc/api/admin.go b/rpc/api/admin.go index 368375c93..7e79fd4d0 100644 --- a/rpc/api/admin.go +++ b/rpc/api/admin.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/rlp" "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" ) @@ -32,6 +33,8 @@ var ( "admin_chainSyncStatus": (*adminApi).ChainSyncStatus, "admin_setSolc": (*adminApi).SetSolc, "admin_datadir": (*adminApi).DataDir, + "admin_startRPC": (*adminApi).StartRPC, + "admin_stopRPC": (*adminApi).StopRPC, } ) @@ -42,25 +45,25 @@ type adminhandler func(*adminApi, *shared.Request) (interface{}, error) type adminApi struct { xeth *xeth.XEth ethereum *eth.Ethereum - methods map[string]adminhandler - codec codec.ApiCoder + codec codec.Codec + coder codec.ApiCoder } // create a new admin api instance -func NewAdminApi(xeth *xeth.XEth, ethereum *eth.Ethereum, coder codec.Codec) *adminApi { +func NewAdminApi(xeth *xeth.XEth, ethereum *eth.Ethereum, codec codec.Codec) *adminApi { return &adminApi{ xeth: xeth, ethereum: ethereum, - methods: AdminMapping, - codec: coder.New(nil), + codec: codec, + coder: codec.New(nil), } } // collection with supported methods func (self *adminApi) Methods() []string { - methods := make([]string, len(self.methods)) + methods := make([]string, len(AdminMapping)) i := 0 - for k := range self.methods { + for k := range AdminMapping { methods[i] = k i++ } @@ -69,7 +72,7 @@ func (self *adminApi) Methods() []string { // Execute given request func (self *adminApi) Execute(req *shared.Request) (interface{}, error) { - if callback, ok := self.methods[req.Method]; ok { + if callback, ok := AdminMapping[req.Method]; ok { return callback(self, req) } @@ -77,7 +80,7 @@ func (self *adminApi) Execute(req *shared.Request) (interface{}, error) { } func (self *adminApi) Name() string { - return AdminApiName + return shared.AdminApiName } func (self *adminApi) ApiVersion() string { @@ -86,7 +89,7 @@ func (self *adminApi) ApiVersion() string { func (self *adminApi) AddPeer(req *shared.Request) (interface{}, error) { args := new(AddPeerArgs) - if err := self.codec.Decode(req.Params, &args); err != nil { + if err := self.coder.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } @@ -120,7 +123,7 @@ func hasAllBlocks(chain *core.ChainManager, bs []*types.Block) bool { func (self *adminApi) ImportChain(req *shared.Request) (interface{}, error) { args := new(ImportExportChainArgs) - if err := self.codec.Decode(req.Params, &args); err != nil { + if err := self.coder.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } @@ -163,7 +166,7 @@ func (self *adminApi) ImportChain(req *shared.Request) (interface{}, error) { func (self *adminApi) ExportChain(req *shared.Request) (interface{}, error) { args := new(ImportExportChainArgs) - if err := self.codec.Decode(req.Params, &args); err != nil { + if err := self.coder.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } @@ -181,7 +184,7 @@ func (self *adminApi) ExportChain(req *shared.Request) (interface{}, error) { func (self *adminApi) Verbosity(req *shared.Request) (interface{}, error) { args := new(VerbosityArgs) - if err := self.codec.Decode(req.Params, &args); err != nil { + if err := self.coder.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } @@ -202,7 +205,7 @@ func (self *adminApi) ChainSyncStatus(req *shared.Request) (interface{}, error) func (self *adminApi) SetSolc(req *shared.Request) (interface{}, error) { args := new(SetSolcArgs) - if err := self.codec.Decode(req.Params, &args); err != nil { + if err := self.coder.Decode(req.Params, &args); err != nil { return nil, shared.NewDecodeParamError(err.Error()) } @@ -212,3 +215,32 @@ func (self *adminApi) SetSolc(req *shared.Request) (interface{}, error) { } return solc.Info(), nil } + +func (self *adminApi) StartRPC(req *shared.Request) (interface{}, error) { + var err error + args := new(StartRPCArgs) + if err := self.coder.Decode(req.Params, &args); err != nil { + return nil, shared.NewDecodeParamError(err.Error()) + } + + cfg := comms.HttpConfig{ + ListenAddress: args.ListenAddress, + ListenPort: args.ListenPort, + CorsDomain: args.CorsDomain, + } + + if apis, err := ParseApiString(args.Apis, self.codec, self.xeth, self.ethereum); err == nil { + err = comms.StartHttp(cfg, self.codec, Merge(apis...)) + } + + if err == nil { + return true, nil + } + + return false, err +} + +func (self *adminApi) StopRPC(req *shared.Request) (interface{}, error) { + comms.StopHttp() + return true, nil +} diff --git a/rpc/api/admin_args.go b/rpc/api/admin_args.go index 56bb57e20..5437971ca 100644 --- a/rpc/api/admin_args.go +++ b/rpc/api/admin_args.go @@ -95,3 +95,55 @@ func (args *SetSolcArgs) UnmarshalJSON(b []byte) (err error) { return shared.NewInvalidTypeError("path", "not a string") } + +type StartRPCArgs struct { + ListenAddress string + ListenPort uint + CorsDomain string + Apis string +} + +func (args *StartRPCArgs) UnmarshalJSON(b []byte) (err error) { + var obj []interface{} + if err := json.Unmarshal(b, &obj); err != nil { + return shared.NewDecodeParamError(err.Error()) + } + + args.ListenAddress = "127.0.0.1" + args.ListenPort = 8545 + args.Apis = "net,eth,web3" + + if len(obj) >= 1 { + if addr, ok := obj[0].(string); ok { + args.ListenAddress = addr + } else { + return shared.NewInvalidTypeError("listenAddress", "not a string") + } + } + + if len(obj) >= 2 { + if port, ok := obj[1].(float64); ok && port >= 0 && port <= 64*1024 { + args.ListenPort = uint(port) + } else { + return shared.NewInvalidTypeError("listenPort", "not a valid port number") + } + } + + if len(obj) >= 3 { + if corsDomain, ok := obj[2].(string); ok { + args.CorsDomain = corsDomain + } else { + return shared.NewInvalidTypeError("corsDomain", "not a string") + } + } + + if len(obj) >= 4 { + if apis, ok := obj[3].(string); ok { + args.Apis = apis + } else { + return shared.NewInvalidTypeError("apis", "not a string") + } + } + + return nil +} diff --git a/rpc/api/admin_js.go b/rpc/api/admin_js.go index c3e713c67..97642ade7 100644 --- a/rpc/api/admin_js.go +++ b/rpc/api/admin_js.go @@ -39,6 +39,20 @@ web3._extend({ params: 1, inputFormatter: [web3._extend.utils.formatInputString], outputFormatter: web3._extend.formatters.formatOutputString + }), + new web3._extend.Method({ + name: 'startRPC', + call: 'admin_startRPC', + params: 4, + inputFormatter: [web3._extend.utils.formatInputString,web3._extend.utils.formatInputInteger,web3._extend.utils.formatInputString,web3._extend.utils.formatInputString], + outputFormatter: web3._extend.formatters.formatOutputBool + }), + new web3._extend.Method({ + name: 'stopRPC', + call: 'admin_stopRPC', + params: 0, + inputFormatter: [], + outputFormatter: web3._extend.formatters.formatOutputBool }) ], properties: diff --git a/rpc/api/api.go b/rpc/api/api.go index 10b448594..ca1ccb9a5 100644 --- a/rpc/api/api.go +++ b/rpc/api/api.go @@ -1,51 +1,10 @@ package api import ( - "strings" - "github.com/ethereum/go-ethereum/rpc/shared" ) -const ( - AdminApiName = "admin" - EthApiName = "eth" - DbApiName = "db" - DebugApiName = "debug" - MergedApiName = "merged" - MinerApiName = "miner" - NetApiName = "net" - ShhApiName = "shh" - TxPoolApiName = "txpool" - PersonalApiName = "personal" - Web3ApiName = "web3" - - JsonRpcVersion = "2.0" -) - -var ( - // All API's - AllApis = strings.Join([]string{ - AdminApiName, DbApiName, EthApiName, DebugApiName, MinerApiName, NetApiName, - ShhApiName, TxPoolApiName, PersonalApiName, Web3ApiName, - }, ",") -) - -// Ethereum RPC API interface -type EthereumApi interface { - // API identifier - Name() string - - // API version - ApiVersion() string - - // Execute the given request and returns the response or an error - Execute(*shared.Request) (interface{}, error) - - // List of supported RCP methods this API provides - Methods() []string -} - // Merge multiple API's to a single API instance -func Merge(apis ...EthereumApi) EthereumApi { +func Merge(apis ...shared.EthereumApi) shared.EthereumApi { return newMergedApi(apis...) } diff --git a/rpc/api/args.go b/rpc/api/args.go index 4ef1b26e7..fc85448e6 100644 --- a/rpc/api/args.go +++ b/rpc/api/args.go @@ -2,6 +2,7 @@ package api import ( "encoding/json" + "github.com/ethereum/go-ethereum/rpc/shared" ) @@ -54,4 +55,4 @@ func (args *FilterStringArgs) UnmarshalJSON(b []byte) (err error) { } args.Word = argstr return nil -} \ No newline at end of file +} diff --git a/rpc/api/args_test.go b/rpc/api/args_test.go index 4153d5432..a30f247bc 100644 --- a/rpc/api/args_test.go +++ b/rpc/api/args_test.go @@ -6,6 +6,7 @@ import ( "fmt" "math/big" "testing" + "github.com/ethereum/go-ethereum/rpc/shared" ) diff --git a/rpc/api/db.go b/rpc/api/db.go index 745269168..6f10d6447 100644 --- a/rpc/api/db.go +++ b/rpc/api/db.go @@ -63,7 +63,7 @@ func (self *dbApi) Execute(req *shared.Request) (interface{}, error) { } func (self *dbApi) Name() string { - return DbApiName + return shared.DbApiName } func (self *dbApi) ApiVersion() string { diff --git a/rpc/api/debug.go b/rpc/api/debug.go index 5b6a449dc..b451d8662 100644 --- a/rpc/api/debug.go +++ b/rpc/api/debug.go @@ -71,7 +71,7 @@ func (self *debugApi) Execute(req *shared.Request) (interface{}, error) { } func (self *debugApi) Name() string { - return DebugApiName + return shared.DebugApiName } func (self *debugApi) ApiVersion() string { diff --git a/rpc/api/eth.go b/rpc/api/eth.go index cafa05e34..0bb8d449b 100644 --- a/rpc/api/eth.go +++ b/rpc/api/eth.go @@ -100,7 +100,7 @@ func (self *ethApi) Execute(req *shared.Request) (interface{}, error) { } func (self *ethApi) Name() string { - return EthApiName + return shared.EthApiName } func (self *ethApi) ApiVersion() string { diff --git a/rpc/api/mergedapi.go b/rpc/api/mergedapi.go index 8cf4ae96e..bc4fa32e8 100644 --- a/rpc/api/mergedapi.go +++ b/rpc/api/mergedapi.go @@ -13,14 +13,14 @@ const ( // combines multiple API's type MergedApi struct { apis map[string]string - methods map[string]EthereumApi + methods map[string]shared.EthereumApi } // create new merged api instance -func newMergedApi(apis ...EthereumApi) *MergedApi { +func newMergedApi(apis ...shared.EthereumApi) *MergedApi { mergedApi := new(MergedApi) mergedApi.apis = make(map[string]string, len(apis)) - mergedApi.methods = make(map[string]EthereumApi) + mergedApi.methods = make(map[string]shared.EthereumApi) for _, api := range apis { mergedApi.apis[api.Name()] = api.ApiVersion() @@ -54,7 +54,7 @@ func (self *MergedApi) Execute(req *shared.Request) (interface{}, error) { } func (self *MergedApi) Name() string { - return MergedApiName + return shared.MergedApiName } func (self *MergedApi) ApiVersion() string { diff --git a/rpc/api/mergedapi_js.go b/rpc/api/mergedapi_js.go deleted file mode 100644 index 778f64ec1..000000000 --- a/rpc/api/mergedapi_js.go +++ /dev/null @@ -1 +0,0 @@ -package api diff --git a/rpc/api/miner.go b/rpc/api/miner.go index 0b5e74f52..7a84cb9ae 100644 --- a/rpc/api/miner.go +++ b/rpc/api/miner.go @@ -66,7 +66,7 @@ func (self *minerApi) Methods() []string { } func (self *minerApi) Name() string { - return MinerApiName + return shared.MinerApiName } func (self *minerApi) ApiVersion() string { diff --git a/rpc/api/net.go b/rpc/api/net.go index 247c23827..761654661 100644 --- a/rpc/api/net.go +++ b/rpc/api/net.go @@ -63,7 +63,7 @@ func (self *netApi) Execute(req *shared.Request) (interface{}, error) { } func (self *netApi) Name() string { - return NetApiName + return shared.NetApiName } func (self *netApi) ApiVersion() string { diff --git a/rpc/api/personal.go b/rpc/api/personal.go index 7a6c91c82..b4a63ea7a 100644 --- a/rpc/api/personal.go +++ b/rpc/api/personal.go @@ -66,7 +66,7 @@ func (self *personalApi) Execute(req *shared.Request) (interface{}, error) { } func (self *personalApi) Name() string { - return PersonalApiName + return shared.PersonalApiName } func (self *personalApi) ApiVersion() string { diff --git a/rpc/api/shh.go b/rpc/api/shh.go index e83a7b22e..18a8fd15d 100644 --- a/rpc/api/shh.go +++ b/rpc/api/shh.go @@ -72,7 +72,7 @@ func (self *shhApi) Execute(req *shared.Request) (interface{}, error) { } func (self *shhApi) Name() string { - return ShhApiName + return shared.ShhApiName } func (self *shhApi) ApiVersion() string { diff --git a/rpc/api/txpool.go b/rpc/api/txpool.go index 64550bdaf..25ad6e9b2 100644 --- a/rpc/api/txpool.go +++ b/rpc/api/txpool.go @@ -60,7 +60,7 @@ func (self *txPoolApi) Execute(req *shared.Request) (interface{}, error) { } func (self *txPoolApi) Name() string { - return TxPoolApiName + return shared.TxPoolApiName } func (self *txPoolApi) ApiVersion() string { diff --git a/rpc/api/utils.go b/rpc/api/utils.go index a4ce6409a..9995e1f7c 100644 --- a/rpc/api/utils.go +++ b/rpc/api/utils.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/rpc/codec" + "github.com/ethereum/go-ethereum/rpc/shared" "github.com/ethereum/go-ethereum/xeth" ) @@ -23,6 +24,8 @@ var ( "chainSyncStatus", "setSolc", "datadir", + "startRPC", + "stopRPC", }, "db": []string{ "getString", @@ -129,35 +132,35 @@ var ( ) // Parse a comma separated API string to individual api's -func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.Ethereum) ([]EthereumApi, error) { +func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.Ethereum) ([]shared.EthereumApi, error) { if len(strings.TrimSpace(apistr)) == 0 { return nil, fmt.Errorf("Empty apistr provided") } names := strings.Split(apistr, ",") - apis := make([]EthereumApi, len(names)) + apis := make([]shared.EthereumApi, len(names)) for i, name := range names { switch strings.ToLower(strings.TrimSpace(name)) { - case AdminApiName: + case shared.AdminApiName: apis[i] = NewAdminApi(xeth, eth, codec) - case DebugApiName: + case shared.DebugApiName: apis[i] = NewDebugApi(xeth, eth, codec) - case DbApiName: + case shared.DbApiName: apis[i] = NewDbApi(xeth, eth, codec) - case EthApiName: + case shared.EthApiName: apis[i] = NewEthApi(xeth, codec) - case MinerApiName: + case shared.MinerApiName: apis[i] = NewMinerApi(eth, codec) - case NetApiName: + case shared.NetApiName: apis[i] = NewNetApi(xeth, eth, codec) - case ShhApiName: + case shared.ShhApiName: apis[i] = NewShhApi(xeth, eth, codec) - case TxPoolApiName: + case shared.TxPoolApiName: apis[i] = NewTxPoolApi(xeth, eth, codec) - case PersonalApiName: + case shared.PersonalApiName: apis[i] = NewPersonalApi(xeth, eth, codec) - case Web3ApiName: + case shared.Web3ApiName: apis[i] = NewWeb3Api(xeth, codec) default: return nil, fmt.Errorf("Unknown API '%s'", name) @@ -169,21 +172,21 @@ func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth. func Javascript(name string) string { switch strings.ToLower(strings.TrimSpace(name)) { - case AdminApiName: + case shared.AdminApiName: return Admin_JS - case DebugApiName: + case shared.DebugApiName: return Debug_JS - case DbApiName: + case shared.DbApiName: return Db_JS - case MinerApiName: + case shared.MinerApiName: return Miner_JS - case NetApiName: + case shared.NetApiName: return Net_JS - case ShhApiName: + case shared.ShhApiName: return Shh_JS - case TxPoolApiName: + case shared.TxPoolApiName: return TxPool_JS - case PersonalApiName: + case shared.PersonalApiName: return Personal_JS } diff --git a/rpc/api/web3.go b/rpc/api/web3.go index ed5008446..4c20baa25 100644 --- a/rpc/api/web3.go +++ b/rpc/api/web3.go @@ -60,7 +60,7 @@ func (self *web3Api) Execute(req *shared.Request) (interface{}, error) { } func (self *web3Api) Name() string { - return Web3ApiName + return shared.Web3ApiName } func (self *web3Api) ApiVersion() string { diff --git a/rpc/comms/comms.go b/rpc/comms/comms.go index 29ad11b3c..bfe625758 100644 --- a/rpc/comms/comms.go +++ b/rpc/comms/comms.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" - "github.com/ethereum/go-ethereum/rpc/api" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/shared" ) @@ -22,14 +21,14 @@ const ( var ( // List with all API's which are offered over the in proc interface by default - DefaultInProcApis = api.AllApis + DefaultInProcApis = shared.AllApis // List with all API's which are offered over the IPC interface by default - DefaultIpcApis = api.AllApis + DefaultIpcApis = shared.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, + shared.DbApiName, shared.EthApiName, shared.NetApiName, shared.Web3ApiName, }, ",") ) @@ -44,7 +43,7 @@ type EthereumClient interface { SupportedModules() (map[string]string, error) } -func handle(conn net.Conn, api api.EthereumApi, c codec.Codec) { +func handle(conn net.Conn, api shared.EthereumApi, c codec.Codec) { codec := c.New(conn) for { diff --git a/rpc/comms/http.go b/rpc/comms/http.go index 6a543c0ed..ebee791bd 100644 --- a/rpc/comms/http.go +++ b/rpc/comms/http.go @@ -10,7 +10,6 @@ import ( "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" - "github.com/ethereum/go-ethereum/rpc/api" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/shared" "github.com/rs/cors" @@ -28,7 +27,7 @@ type HttpConfig struct { CorsDomain string } -func StartHttp(cfg HttpConfig, codec codec.Codec, apis ...api.EthereumApi) error { +func StartHttp(cfg HttpConfig, codec codec.Codec, api shared.EthereumApi) error { if httpListener != nil { if fmt.Sprintf("%s:%d", cfg.ListenAddress, cfg.ListenPort) != httpListener.Addr().String() { return fmt.Errorf("RPC service already running on %s ", httpListener.Addr().String()) @@ -43,7 +42,6 @@ func StartHttp(cfg HttpConfig, codec codec.Codec, apis ...api.EthereumApi) error } httpListener = l - api := api.Merge(apis...) var handler http.Handler if len(cfg.CorsDomain) > 0 { var opts cors.Options diff --git a/rpc/comms/http_net.go b/rpc/comms/http_net.go index f326f1a7e..acc5f99a9 100644 --- a/rpc/comms/http_net.go +++ b/rpc/comms/http_net.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" - "github.com/ethereum/go-ethereum/rpc/api" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/shared" ) @@ -90,7 +89,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, api.JsonRpcVersion, nil, err) + response := shared.NewRpcResponse(-1, shared.JsonRpcVersion, nil, err) httpSend(w, response) default: h.ServeHTTP(w, r) @@ -110,14 +109,14 @@ func httpSend(writer io.Writer, v interface{}) (n int, err error) { return writer.Write(payload) } -func gethHttpHandler(codec codec.Codec, a api.EthereumApi) http.Handler { +func gethHttpHandler(codec codec.Codec, a shared.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, api.JsonRpcVersion, -32700, err) + response := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32700, err) httpSend(w, &response) return } @@ -126,7 +125,7 @@ func gethHttpHandler(codec codec.Codec, a 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, api.JsonRpcVersion, -32700, err) + response := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32700, err) httpSend(w, &response) return } @@ -161,7 +160,7 @@ func gethHttpHandler(codec codec.Codec, a api.EthereumApi) http.Handler { // invalid request err = fmt.Errorf("Could not decode request") - res := shared.NewRpcErrorResponse(-1, api.JsonRpcVersion, -32600, err) + res := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32600, err) httpSend(w, res) }) } diff --git a/rpc/comms/inproc.go b/rpc/comms/inproc.go index b9c4e93d9..5c84b8fd8 100644 --- a/rpc/comms/inproc.go +++ b/rpc/comms/inproc.go @@ -3,15 +3,12 @@ package comms import ( "fmt" - "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/rpc/api" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/shared" - "github.com/ethereum/go-ethereum/xeth" ) type InProcClient struct { - api api.EthereumApi + api shared.EthereumApi codec codec.Codec lastId interface{} lastJsonrpc string @@ -31,10 +28,8 @@ func (self *InProcClient) Close() { } // 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) Initialize(offeredApi shared.EthereumApi) { + self.api = offeredApi } func (self *InProcClient) Send(req interface{}) error { diff --git a/rpc/comms/ipc.go b/rpc/comms/ipc.go index 7f5219300..068a1288f 100644 --- a/rpc/comms/ipc.go +++ b/rpc/comms/ipc.go @@ -6,7 +6,6 @@ import ( "encoding/json" - "github.com/ethereum/go-ethereum/rpc/api" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/shared" ) @@ -92,7 +91,6 @@ func NewIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) { } // Start IPC server -func StartIpc(cfg IpcConfig, codec codec.Codec, apis ...api.EthereumApi) error { - offeredApi := api.Merge(apis...) +func StartIpc(cfg IpcConfig, codec codec.Codec, offeredApi shared.EthereumApi) error { return startIpc(cfg, codec, offeredApi) } diff --git a/rpc/comms/ipc_unix.go b/rpc/comms/ipc_unix.go index b5eec92db..295eb916b 100644 --- a/rpc/comms/ipc_unix.go +++ b/rpc/comms/ipc_unix.go @@ -8,8 +8,8 @@ import ( "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" - "github.com/ethereum/go-ethereum/rpc/api" "github.com/ethereum/go-ethereum/rpc/codec" + "github.com/ethereum/go-ethereum/rpc/shared" ) func newIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) { @@ -31,7 +31,7 @@ func (self *ipcClient) reconnect() error { return err } -func startIpc(cfg IpcConfig, codec codec.Codec, api api.EthereumApi) error { +func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error { os.Remove(cfg.Endpoint) // in case it still exists from a previous run l, err := net.ListenUnix("unix", &net.UnixAddr{Name: cfg.Endpoint, Net: "unix"}) diff --git a/rpc/comms/ipc_windows.go b/rpc/comms/ipc_windows.go index 08f79274a..44c82ef8a 100644 --- a/rpc/comms/ipc_windows.go +++ b/rpc/comms/ipc_windows.go @@ -14,7 +14,6 @@ import ( "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger/glog" - "github.com/ethereum/go-ethereum/rpc/api" "github.com/ethereum/go-ethereum/rpc/codec" "github.com/ethereum/go-ethereum/rpc/shared" ) @@ -652,7 +651,7 @@ func (self *ipcClient) reconnect() error { return err } -func startIpc(cfg IpcConfig, codec codec.Codec, api api.EthereumApi) error { +func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error { os.Remove(cfg.Endpoint) // in case it still exists from a previous run l, err := Listen(cfg.Endpoint) diff --git a/rpc/jeth.go b/rpc/jeth.go index e656e8fa9..33fcd6efd 100644 --- a/rpc/jeth.go +++ b/rpc/jeth.go @@ -4,25 +4,24 @@ import ( "encoding/json" "github.com/ethereum/go-ethereum/jsre" - "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" ) type Jeth struct { - ethApi api.EthereumApi + ethApi shared.EthereumApi re *jsre.JSRE client comms.EthereumClient } -func NewJeth(ethApi api.EthereumApi, re *jsre.JSRE, client comms.EthereumClient) *Jeth { +func NewJeth(ethApi shared.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 := &shared.ErrorObject{code, msg} - call.Otto.Set("ret_jsonrpc", api.JsonRpcVersion) + call.Otto.Set("ret_jsonrpc", shared.JsonRpcVersion) call.Otto.Set("ret_id", id) call.Otto.Set("ret_error", rpcerr) response, _ = call.Otto.Run(` @@ -61,7 +60,7 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) { return self.err(call, -32603, err.Error(), req.Id) } - call.Otto.Set("ret_jsonrpc", api.JsonRpcVersion) + call.Otto.Set("ret_jsonrpc", shared.JsonRpcVersion) call.Otto.Set("ret_id", req.Id) res, _ := json.Marshal(respif) diff --git a/rpc/shared/types.go b/rpc/shared/types.go index dd38a4559..7c4b04e83 100644 --- a/rpc/shared/types.go +++ b/rpc/shared/types.go @@ -7,6 +7,21 @@ import ( "github.com/ethereum/go-ethereum/logger/glog" ) +// Ethereum RPC API interface +type EthereumApi interface { + // API identifier + Name() string + + // API version + ApiVersion() string + + // Execute the given request and returns the response or an error + Execute(*Request) (interface{}, error) + + // List of supported RCP methods this API provides + Methods() []string +} + // RPC request type Request struct { Id interface{} `json:"id"` diff --git a/rpc/shared/utils.go b/rpc/shared/utils.go new file mode 100644 index 000000000..7953d6c22 --- /dev/null +++ b/rpc/shared/utils.go @@ -0,0 +1,28 @@ +package shared + +import "strings" + +const ( + AdminApiName = "admin" + EthApiName = "eth" + DbApiName = "db" + DebugApiName = "debug" + MergedApiName = "merged" + MinerApiName = "miner" + NetApiName = "net" + ShhApiName = "shh" + TxPoolApiName = "txpool" + PersonalApiName = "personal" + Web3ApiName = "web3" + + JsonRpcVersion = "2.0" +) + +var ( + // All API's + AllApis = strings.Join([]string{ + AdminApiName, DbApiName, EthApiName, DebugApiName, MinerApiName, NetApiName, + ShhApiName, TxPoolApiName, PersonalApiName, Web3ApiName, + }, ",") +) +