admin.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. package api
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "github.com/ethereum/go-ethereum/core"
  7. "github.com/ethereum/go-ethereum/core/types"
  8. "github.com/ethereum/go-ethereum/eth"
  9. "github.com/ethereum/go-ethereum/logger/glog"
  10. "github.com/ethereum/go-ethereum/rlp"
  11. "github.com/ethereum/go-ethereum/rpc/codec"
  12. "github.com/ethereum/go-ethereum/rpc/shared"
  13. "github.com/ethereum/go-ethereum/xeth"
  14. )
  15. const (
  16. AdminApiversion = "1.0"
  17. importBatchSize = 2500
  18. )
  19. var (
  20. // mapping between methods and handlers
  21. AdminMapping = map[string]adminhandler{
  22. "admin_addPeer": (*adminApi).AddPeer,
  23. "admin_peers": (*adminApi).Peers,
  24. "admin_nodeInfo": (*adminApi).NodeInfo,
  25. "admin_exportChain": (*adminApi).ExportChain,
  26. "admin_importChain": (*adminApi).ImportChain,
  27. "admin_verbosity": (*adminApi).Verbosity,
  28. "admin_chainSyncStatus": (*adminApi).ChainSyncStatus,
  29. "admin_setSolc": (*adminApi).SetSolc,
  30. "admin_datadir": (*adminApi).DataDir,
  31. }
  32. )
  33. // admin callback handler
  34. type adminhandler func(*adminApi, *shared.Request) (interface{}, error)
  35. // admin api provider
  36. type adminApi struct {
  37. xeth *xeth.XEth
  38. ethereum *eth.Ethereum
  39. methods map[string]adminhandler
  40. codec codec.ApiCoder
  41. }
  42. // create a new admin api instance
  43. func NewAdminApi(xeth *xeth.XEth, ethereum *eth.Ethereum, coder codec.Codec) *adminApi {
  44. return &adminApi{
  45. xeth: xeth,
  46. ethereum: ethereum,
  47. methods: AdminMapping,
  48. codec: coder.New(nil),
  49. }
  50. }
  51. // collection with supported methods
  52. func (self *adminApi) Methods() []string {
  53. methods := make([]string, len(self.methods))
  54. i := 0
  55. for k := range self.methods {
  56. methods[i] = k
  57. i++
  58. }
  59. return methods
  60. }
  61. // Execute given request
  62. func (self *adminApi) Execute(req *shared.Request) (interface{}, error) {
  63. if callback, ok := self.methods[req.Method]; ok {
  64. return callback(self, req)
  65. }
  66. return nil, &shared.NotImplementedError{req.Method}
  67. }
  68. func (self *adminApi) Name() string {
  69. return AdminApiName
  70. }
  71. func (self *adminApi) ApiVersion() string {
  72. return AdminApiversion
  73. }
  74. func (self *adminApi) AddPeer(req *shared.Request) (interface{}, error) {
  75. args := new(AddPeerArgs)
  76. if err := self.codec.Decode(req.Params, &args); err != nil {
  77. return nil, shared.NewDecodeParamError(err.Error())
  78. }
  79. err := self.ethereum.AddPeer(args.Url)
  80. if err == nil {
  81. return true, nil
  82. }
  83. return false, err
  84. }
  85. func (self *adminApi) Peers(req *shared.Request) (interface{}, error) {
  86. return self.ethereum.PeersInfo(), nil
  87. }
  88. func (self *adminApi) NodeInfo(req *shared.Request) (interface{}, error) {
  89. return self.ethereum.NodeInfo(), nil
  90. }
  91. func (self *adminApi) DataDir(req *shared.Request) (interface{}, error) {
  92. return self.ethereum.DataDir, nil
  93. }
  94. func hasAllBlocks(chain *core.ChainManager, bs []*types.Block) bool {
  95. for _, b := range bs {
  96. if !chain.HasBlock(b.Hash()) {
  97. return false
  98. }
  99. }
  100. return true
  101. }
  102. func (self *adminApi) ImportChain(req *shared.Request) (interface{}, error) {
  103. args := new(ImportExportChainArgs)
  104. if err := self.codec.Decode(req.Params, &args); err != nil {
  105. return nil, shared.NewDecodeParamError(err.Error())
  106. }
  107. fh, err := os.Open(args.Filename)
  108. if err != nil {
  109. return false, err
  110. }
  111. defer fh.Close()
  112. stream := rlp.NewStream(fh, 0)
  113. // Run actual the import.
  114. blocks := make(types.Blocks, importBatchSize)
  115. n := 0
  116. for batch := 0; ; batch++ {
  117. i := 0
  118. for ; i < importBatchSize; i++ {
  119. var b types.Block
  120. if err := stream.Decode(&b); err == io.EOF {
  121. break
  122. } else if err != nil {
  123. return false, fmt.Errorf("at block %d: %v", n, err)
  124. }
  125. blocks[i] = &b
  126. n++
  127. }
  128. if i == 0 {
  129. break
  130. }
  131. // Import the batch.
  132. if hasAllBlocks(self.ethereum.ChainManager(), blocks[:i]) {
  133. continue
  134. }
  135. if _, err := self.ethereum.ChainManager().InsertChain(blocks[:i]); err != nil {
  136. return false, fmt.Errorf("invalid block %d: %v", n, err)
  137. }
  138. }
  139. return true, nil
  140. }
  141. func (self *adminApi) ExportChain(req *shared.Request) (interface{}, error) {
  142. args := new(ImportExportChainArgs)
  143. if err := self.codec.Decode(req.Params, &args); err != nil {
  144. return nil, shared.NewDecodeParamError(err.Error())
  145. }
  146. fh, err := os.OpenFile(args.Filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
  147. if err != nil {
  148. return false, err
  149. }
  150. defer fh.Close()
  151. if err := self.ethereum.ChainManager().Export(fh); err != nil {
  152. return false, err
  153. }
  154. return true, nil
  155. }
  156. func (self *adminApi) Verbosity(req *shared.Request) (interface{}, error) {
  157. args := new(VerbosityArgs)
  158. if err := self.codec.Decode(req.Params, &args); err != nil {
  159. return nil, shared.NewDecodeParamError(err.Error())
  160. }
  161. glog.SetV(args.Level)
  162. return true, nil
  163. }
  164. func (self *adminApi) ChainSyncStatus(req *shared.Request) (interface{}, error) {
  165. pending, cached, importing, estimate := self.ethereum.Downloader().Stats()
  166. return map[string]interface{}{
  167. "blocksAvailable": pending,
  168. "blocksWaitingForImport": cached,
  169. "importing": importing,
  170. "estimate": estimate.String(),
  171. }, nil
  172. }
  173. func (self *adminApi) SetSolc(req *shared.Request) (interface{}, error) {
  174. args := new(SetSolcArgs)
  175. if err := self.codec.Decode(req.Params, &args); err != nil {
  176. return nil, shared.NewDecodeParamError(err.Error())
  177. }
  178. solc, err := self.xeth.SetSolc(args.Path)
  179. if err != nil {
  180. return nil, err
  181. }
  182. return solc.Info(), nil
  183. }