PageRenderTime 34ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/geth-docker/src/main/docker/api.go

https://gitlab.com/emerald-platform/emerald
Go | 331 lines | 253 code | 40 blank | 38 comment | 57 complexity | 8a6292ffaf8a73f29e3ce2ef71879db9 MD5 | raw file
  1. package node
  2. import (
  3. "fmt"
  4. "strings"
  5. "time"
  6. "github.com/ethereum/go-ethereum/common/hexutil"
  7. "github.com/ethereum/go-ethereum/crypto"
  8. "github.com/ethereum/go-ethereum/p2p"
  9. "github.com/ethereum/go-ethereum/p2p/discover"
  10. "github.com/ethereum/go-ethereum/rpc"
  11. "github.com/rcrowley/go-metrics"
  12. )
  13. // PrivateAdminAPI is the collection of administrative API methods exposed only
  14. // over a secure RPC channel.
  15. type PrivateAdminAPI struct {
  16. node *Node // Node interfaced by this API
  17. }
  18. // NewPrivateAdminAPI creates a new API definition for the private admin methods
  19. // of the node itself.
  20. func NewPrivateAdminAPI(node *Node) *PrivateAdminAPI {
  21. return &PrivateAdminAPI{node: node}
  22. }
  23. // AddPeer requests connecting to a remote node, and also maintaining the new
  24. // connection at all times, even reconnecting if it is lost.
  25. func (api *PrivateAdminAPI) AddPeer(url string) (bool, error) {
  26. // Make sure the server is running, fail otherwise
  27. server := api.node.Server()
  28. if server == nil {
  29. return false, ErrNodeStopped
  30. }
  31. // Try to add the url as a static peer and return
  32. node, err := discover.ParseNode(url)
  33. if err != nil {
  34. return false, fmt.Errorf("invalid enode: %v", err)
  35. }
  36. server.AddPeer(node)
  37. return true, nil
  38. }
  39. // RemovePeer disconnects from a a remote node if the connection exists
  40. func (api *PrivateAdminAPI) RemovePeer(url string) (bool, error) {
  41. // Make sure the server is running, fail otherwise
  42. server := api.node.Server()
  43. if server == nil {
  44. return false, ErrNodeStopped
  45. }
  46. // Try to remove the url as a static peer and return
  47. node, err := discover.ParseNode(url)
  48. if err != nil {
  49. return false, fmt.Errorf("invalid enode: %v", err)
  50. }
  51. server.RemovePeer(node)
  52. return true, nil
  53. }
  54. // StartRPC starts the HTTP RPC API server.
  55. func (api *PrivateAdminAPI) StartRPC(host *string, port *rpc.HexNumber, cors *string, apis *string) (bool, error) {
  56. api.node.lock.Lock()
  57. defer api.node.lock.Unlock()
  58. if api.node.httpHandler != nil {
  59. return false, fmt.Errorf("HTTP RPC already running on %s", api.node.httpEndpoint)
  60. }
  61. if host == nil {
  62. h := DefaultHTTPHost
  63. if api.node.config.HTTPHost != "" {
  64. h = api.node.config.HTTPHost
  65. }
  66. host = &h
  67. }
  68. if port == nil {
  69. port = rpc.NewHexNumber(api.node.config.HTTPPort)
  70. }
  71. if cors == nil {
  72. cors = &api.node.config.HTTPCors
  73. }
  74. modules := api.node.httpWhitelist
  75. if apis != nil {
  76. modules = nil
  77. for _, m := range strings.Split(*apis, ",") {
  78. modules = append(modules, strings.TrimSpace(m))
  79. }
  80. }
  81. if err := api.node.startHTTP(fmt.Sprintf("%s:%d", *host, port.Int()), api.node.rpcAPIs, modules, *cors); err != nil {
  82. return false, err
  83. }
  84. return true, nil
  85. }
  86. // StopRPC terminates an already running HTTP RPC API endpoint.
  87. func (api *PrivateAdminAPI) StopRPC() (bool, error) {
  88. api.node.lock.Lock()
  89. defer api.node.lock.Unlock()
  90. if api.node.httpHandler == nil {
  91. return false, fmt.Errorf("HTTP RPC not running")
  92. }
  93. api.node.stopHTTP()
  94. return true, nil
  95. }
  96. // StartWS starts the websocket RPC API server.
  97. func (api *PrivateAdminAPI) StartWS(host *string, port *rpc.HexNumber, allowedOrigins *string, apis *string) (bool, error) {
  98. api.node.lock.Lock()
  99. defer api.node.lock.Unlock()
  100. if api.node.wsHandler != nil {
  101. return false, fmt.Errorf("WebSocket RPC already running on %s", api.node.wsEndpoint)
  102. }
  103. if host == nil {
  104. h := DefaultWSHost
  105. if api.node.config.WSHost != "" {
  106. h = api.node.config.WSHost
  107. }
  108. host = &h
  109. }
  110. if port == nil {
  111. port = rpc.NewHexNumber(api.node.config.WSPort)
  112. }
  113. if allowedOrigins == nil {
  114. allowedOrigins = &api.node.config.WSOrigins
  115. }
  116. modules := api.node.config.WSModules
  117. if apis != nil {
  118. modules = nil
  119. for _, m := range strings.Split(*apis, ",") {
  120. modules = append(modules, strings.TrimSpace(m))
  121. }
  122. }
  123. if err := api.node.startWS(fmt.Sprintf("%s:%d", *host, port.Int()), api.node.rpcAPIs, modules, *allowedOrigins); err != nil {
  124. return false, err
  125. }
  126. return true, nil
  127. }
  128. // StopRPC terminates an already running websocket RPC API endpoint.
  129. func (api *PrivateAdminAPI) StopWS() (bool, error) {
  130. api.node.lock.Lock()
  131. defer api.node.lock.Unlock()
  132. if api.node.wsHandler == nil {
  133. return false, fmt.Errorf("WebSocket RPC not running")
  134. }
  135. api.node.stopWS()
  136. return true, nil
  137. }
  138. // PublicAdminAPI is the collection of administrative API methods exposed over
  139. // both secure and unsecure RPC channels.
  140. type PublicAdminAPI struct {
  141. node *Node // Node interfaced by this API
  142. }
  143. // NewPublicAdminAPI creates a new API definition for the public admin methods
  144. // of the node itself.
  145. func NewPublicAdminAPI(node *Node) *PublicAdminAPI {
  146. return &PublicAdminAPI{node: node}
  147. }
  148. // Peers retrieves all the information we know about each individual peer at the
  149. // protocol granularity.
  150. func (api *PublicAdminAPI) Peers() ([]*p2p.PeerInfo, error) {
  151. server := api.node.Server()
  152. if server == nil {
  153. return nil, ErrNodeStopped
  154. }
  155. return server.PeersInfo(), nil
  156. }
  157. // NodeInfo retrieves all the information we know about the host node at the
  158. // protocol granularity.
  159. func (api *PublicAdminAPI) NodeInfo() (*p2p.NodeInfo, error) {
  160. server := api.node.Server()
  161. if server == nil {
  162. return nil, ErrNodeStopped
  163. }
  164. return server.NodeInfo(), nil
  165. }
  166. // Datadir retrieves the current data directory the node is using.
  167. func (api *PublicAdminAPI) Datadir() string {
  168. return api.node.DataDir()
  169. }
  170. // PublicDebugAPI is the collection of debugging related API methods exposed over
  171. // both secure and unsecure RPC channels.
  172. type PublicDebugAPI struct {
  173. node *Node // Node interfaced by this API
  174. }
  175. // NewPublicDebugAPI creates a new API definition for the public debug methods
  176. // of the node itself.
  177. func NewPublicDebugAPI(node *Node) *PublicDebugAPI {
  178. return &PublicDebugAPI{node: node}
  179. }
  180. // Metrics retrieves all the known system metric collected by the node.
  181. func (api *PublicDebugAPI) Metrics(raw bool) (map[string]interface{}, error) {
  182. // Create a rate formatter
  183. units := []string{"", "K", "M", "G", "T", "E", "P"}
  184. round := func(value float64, prec int) string {
  185. unit := 0
  186. for value >= 1000 {
  187. unit, value, prec = unit+1, value/1000, 2
  188. }
  189. return fmt.Sprintf(fmt.Sprintf("%%.%df%s", prec, units[unit]), value)
  190. }
  191. format := func(total float64, rate float64) string {
  192. return fmt.Sprintf("%s (%s/s)", round(total, 0), round(rate, 2))
  193. }
  194. // Iterate over all the metrics, and just dump for now
  195. counters := make(map[string]interface{})
  196. metrics.DefaultRegistry.Each(func(name string, metric interface{}) {
  197. // Create or retrieve the counter hierarchy for this metric
  198. root, parts := counters, strings.Split(name, "/")
  199. for _, part := range parts[:len(parts)-1] {
  200. if _, ok := root[part]; !ok {
  201. root[part] = make(map[string]interface{})
  202. }
  203. root = root[part].(map[string]interface{})
  204. }
  205. name = parts[len(parts)-1]
  206. // Fill the counter with the metric details, formatting if requested
  207. if raw {
  208. switch metric := metric.(type) {
  209. case metrics.Meter:
  210. root[name] = map[string]interface{}{
  211. "AvgRate01Min": metric.Rate1(),
  212. "AvgRate05Min": metric.Rate5(),
  213. "AvgRate15Min": metric.Rate15(),
  214. "MeanRate": metric.RateMean(),
  215. "Overall": float64(metric.Count()),
  216. }
  217. case metrics.Counter:
  218. root[name] = map[string]interface{}{
  219. "Count": float64(metric.Count()),
  220. }
  221. case metrics.Timer:
  222. root[name] = map[string]interface{}{
  223. "AvgRate01Min": metric.Rate1(),
  224. "AvgRate05Min": metric.Rate5(),
  225. "AvgRate15Min": metric.Rate15(),
  226. "MeanRate": metric.RateMean(),
  227. "Overall": float64(metric.Count()),
  228. "Percentiles": map[string]interface{}{
  229. "5": metric.Percentile(0.05),
  230. "20": metric.Percentile(0.2),
  231. "50": metric.Percentile(0.5),
  232. "80": metric.Percentile(0.8),
  233. "95": metric.Percentile(0.95),
  234. },
  235. }
  236. default:
  237. root[name] = "Unknown metric type"
  238. }
  239. } else {
  240. switch metric := metric.(type) {
  241. case metrics.Meter:
  242. root[name] = map[string]interface{}{
  243. "Avg01Min": format(metric.Rate1()*60, metric.Rate1()),
  244. "Avg05Min": format(metric.Rate5()*300, metric.Rate5()),
  245. "Avg15Min": format(metric.Rate15()*900, metric.Rate15()),
  246. "Overall": format(float64(metric.Count()), metric.RateMean()),
  247. }
  248. case metrics.Counter:
  249. root[name] = map[string]interface{}{
  250. "Count": metric.Count(),
  251. }
  252. case metrics.Timer:
  253. root[name] = map[string]interface{}{
  254. "Avg01Min": format(metric.Rate1()*60, metric.Rate1()),
  255. "Avg05Min": format(metric.Rate5()*300, metric.Rate5()),
  256. "Avg15Min": format(metric.Rate15()*900, metric.Rate15()),
  257. "Overall": format(float64(metric.Count()), metric.RateMean()),
  258. "Maximum": time.Duration(metric.Max()).String(),
  259. "Minimum": time.Duration(metric.Min()).String(),
  260. "Percentiles": map[string]interface{}{
  261. "5": time.Duration(metric.Percentile(0.05)).String(),
  262. "20": time.Duration(metric.Percentile(0.2)).String(),
  263. "50": time.Duration(metric.Percentile(0.5)).String(),
  264. "80": time.Duration(metric.Percentile(0.8)).String(),
  265. "95": time.Duration(metric.Percentile(0.95)).String(),
  266. },
  267. }
  268. default:
  269. root[name] = "Unknown metric type"
  270. }
  271. }
  272. })
  273. return counters, nil
  274. }
  275. // PublicWeb3API offers helper utils
  276. type PublicWeb3API struct {
  277. stack *Node
  278. }
  279. // NewPublicWeb3API creates a new Web3Service instance
  280. func NewPublicWeb3API(stack *Node) *PublicWeb3API {
  281. return &PublicWeb3API{stack}
  282. }
  283. // ClientVersion returns the node name
  284. func (s *PublicWeb3API) ClientVersion() string {
  285. return s.stack.Server().Name
  286. }
  287. // Sha3 applies the ethereum sha3 implementation on the input.
  288. // It assumes the input is hex encoded.
  289. func (s *PublicWeb3API) Sha3(input hexutil.Bytes) hexutil.Bytes {
  290. return crypto.Keccak256(input)
  291. }