aboutsummaryrefslogtreecommitdiffstats
path: root/rpc/api/admin.go
diff options
context:
space:
mode:
Diffstat (limited to 'rpc/api/admin.go')
-rw-r--r--rpc/api/admin.go228
1 files changed, 228 insertions, 0 deletions
diff --git a/rpc/api/admin.go b/rpc/api/admin.go
new file mode 100644
index 000000000..c37463604
--- /dev/null
+++ b/rpc/api/admin.go
@@ -0,0 +1,228 @@
+package api
+
+import (
+ "fmt"
+ "io"
+ "os"
+
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth"
+ "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/shared"
+ "github.com/ethereum/go-ethereum/xeth"
+)
+
+const (
+ AdminVersion = "1.0.0"
+ importBatchSize = 2500
+)
+
+var (
+ // mapping between methods and handlers
+ AdminMapping = map[string]adminhandler{
+ // "admin_startRPC": (*adminApi).StartRPC,
+ // "admin_stopRPC": (*adminApi).StopRPC,
+ "admin_addPeer": (*adminApi).AddPeer,
+ "admin_peers": (*adminApi).Peers,
+ "admin_nodeInfo": (*adminApi).NodeInfo,
+ "admin_exportChain": (*adminApi).ExportChain,
+ "admin_importChain": (*adminApi).ImportChain,
+ "admin_verbosity": (*adminApi).Verbosity,
+ "admin_syncStatus": (*adminApi).SyncStatus,
+ "admin_setSolc": (*adminApi).SetSolc,
+ }
+)
+
+// admin callback handler
+type adminhandler func(*adminApi, *shared.Request) (interface{}, error)
+
+// admin api provider
+type adminApi struct {
+ xeth *xeth.XEth
+ ethereum *eth.Ethereum
+ methods map[string]adminhandler
+ codec codec.ApiCoder
+}
+
+// create a new admin api instance
+func NewAdminApi(xeth *xeth.XEth, ethereum *eth.Ethereum, coder codec.Codec) *adminApi {
+ return &adminApi{
+ xeth: xeth,
+ ethereum: ethereum,
+ methods: AdminMapping,
+ codec: coder.New(nil),
+ }
+}
+
+// collection with supported methods
+func (self *adminApi) Methods() []string {
+ methods := make([]string, len(self.methods))
+ i := 0
+ for k := range self.methods {
+ methods[i] = k
+ i++
+ }
+ return methods
+}
+
+// Execute given request
+func (self *adminApi) Execute(req *shared.Request) (interface{}, error) {
+ if callback, ok := self.methods[req.Method]; ok {
+ return callback(self, req)
+ }
+
+ return nil, &shared.NotImplementedError{req.Method}
+}
+
+func (self *adminApi) Name() string {
+ return AdminApiName
+}
+
+func (self *adminApi) AddPeer(req *shared.Request) (interface{}, error) {
+ args := new(AddPeerArgs)
+ if err := self.codec.Decode(req.Params, &args); err != nil {
+ return nil, shared.NewDecodeParamError(err.Error())
+ }
+
+ err := self.ethereum.AddPeer(args.Url)
+ if err == nil {
+ return true, nil
+ }
+ return false, err
+}
+
+func (self *adminApi) Peers(req *shared.Request) (interface{}, error) {
+ return self.ethereum.PeersInfo(), nil
+}
+
+func (self *adminApi) StartRPC(req *shared.Request) (interface{}, error) {
+ return false, nil
+ // Enable when http rpc interface is refactored to prevent import cycles
+ // args := new(StartRpcArgs)
+ // if err := self.codec.Decode(req.Params, &args); err != nil {
+ // return nil, shared.NewDecodeParamError(err.Error())
+ // }
+ //
+ // cfg := rpc.RpcConfig{
+ // ListenAddress: args.Address,
+ // ListenPort: args.Port,
+ // }
+ //
+ // err := rpc.Start(self.xeth, cfg)
+ // if err == nil {
+ // return true, nil
+ // }
+ // return false, err
+}
+
+func (self *adminApi) StopRPC(req *shared.Request) (interface{}, error) {
+ return false, nil
+ // Enable when http rpc interface is refactored to prevent import cycles
+ // rpc.Stop()
+ // return true, nil
+}
+
+func (self *adminApi) NodeInfo(req *shared.Request) (interface{}, error) {
+ return self.ethereum.NodeInfo(), nil
+}
+
+func hasAllBlocks(chain *core.ChainManager, bs []*types.Block) bool {
+ for _, b := range bs {
+ if !chain.HasBlock(b.Hash()) {
+ return false
+ }
+ }
+ return true
+}
+
+func (self *adminApi) ImportChain(req *shared.Request) (interface{}, error) {
+ args := new(ImportExportChainArgs)
+ if err := self.codec.Decode(req.Params, &args); err != nil {
+ return nil, shared.NewDecodeParamError(err.Error())
+ }
+
+ fh, err := os.Open(args.Filename)
+ if err != nil {
+ return false, err
+ }
+ defer fh.Close()
+ stream := rlp.NewStream(fh, 0)
+
+ // Run actual the import.
+ blocks := make(types.Blocks, importBatchSize)
+ n := 0
+ for batch := 0; ; batch++ {
+
+ i := 0
+ for ; i < importBatchSize; i++ {
+ var b types.Block
+ if err := stream.Decode(&b); err == io.EOF {
+ break
+ } else if err != nil {
+ return false, fmt.Errorf("at block %d: %v", n, err)
+ }
+ blocks[i] = &b
+ n++
+ }
+ if i == 0 {
+ break
+ }
+ // Import the batch.
+ if hasAllBlocks(self.ethereum.ChainManager(), blocks[:i]) {
+ continue
+ }
+ if _, err := self.ethereum.ChainManager().InsertChain(blocks[:i]); err != nil {
+ return false, fmt.Errorf("invalid block %d: %v", n, err)
+ }
+ }
+ return true, nil
+}
+
+func (self *adminApi) ExportChain(req *shared.Request) (interface{}, error) {
+ args := new(ImportExportChainArgs)
+ if err := self.codec.Decode(req.Params, &args); err != nil {
+ return nil, shared.NewDecodeParamError(err.Error())
+ }
+
+ fh, err := os.OpenFile(args.Filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
+ if err != nil {
+ return false, err
+ }
+ defer fh.Close()
+ if err := self.ethereum.ChainManager().Export(fh); err != nil {
+ return false, err
+ }
+
+ return true, nil
+}
+
+func (self *adminApi) Verbosity(req *shared.Request) (interface{}, error) {
+ args := new(VerbosityArgs)
+ if err := self.codec.Decode(req.Params, &args); err != nil {
+ return nil, shared.NewDecodeParamError(err.Error())
+ }
+
+ glog.SetV(args.Level)
+ return true, nil
+}
+
+func (self *adminApi) SyncStatus(req *shared.Request) (interface{}, error) {
+ pending, cached := self.ethereum.Downloader().Stats()
+ return map[string]interface{}{"available": pending, "waitingForImport": cached}, nil
+}
+
+func (self *adminApi) SetSolc(req *shared.Request) (interface{}, error) {
+ args := new(SetSolcArgs)
+ if err := self.codec.Decode(req.Params, &args); err != nil {
+ return nil, shared.NewDecodeParamError(err.Error())
+ }
+
+ solc, err := self.xeth.SetSolc(args.Path)
+ if err != nil {
+ return nil, err
+ }
+ return solc.Info(), nil
+}