added admin API
This commit is contained in:
		
				
					committed by
					
						
						Bas van Kervel
					
				
			
			
				
	
			
			
			
						parent
						
							08d72a9245
						
					
				
				
					commit
					cc9ae39933
				
			
							
								
								
									
										228
									
								
								rpc/api/admin.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								rpc/api/admin.go
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user