added RPC start/stop support
This commit is contained in:
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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...)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/rpc/shared"
|
||||
)
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -1 +0,0 @@
|
||||
package api
|
@ -66,7 +66,7 @@ func (self *minerApi) Methods() []string {
|
||||
}
|
||||
|
||||
func (self *minerApi) Name() string {
|
||||
return MinerApiName
|
||||
return shared.MinerApiName
|
||||
}
|
||||
|
||||
func (self *minerApi) ApiVersion() string {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
Reference in New Issue
Block a user