| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package node | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2017-09-25 09:08:07 +01:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-28 17:14:55 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common/hexutil" | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/p2p" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/p2p/discover" | 
					
						
							| 
									
										
										
										
											2017-09-25 09:08:07 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/rpc" | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	"github.com/rcrowley/go-metrics" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // PrivateAdminAPI is the collection of administrative API methods exposed only | 
					
						
							|  |  |  | // over a secure RPC channel. | 
					
						
							|  |  |  | type PrivateAdminAPI struct { | 
					
						
							|  |  |  | 	node *Node // Node interfaced by this API | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewPrivateAdminAPI creates a new API definition for the private admin methods | 
					
						
							|  |  |  | // of the node itself. | 
					
						
							|  |  |  | func NewPrivateAdminAPI(node *Node) *PrivateAdminAPI { | 
					
						
							|  |  |  | 	return &PrivateAdminAPI{node: node} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // AddPeer requests connecting to a remote node, and also maintaining the new | 
					
						
							|  |  |  | // connection at all times, even reconnecting if it is lost. | 
					
						
							|  |  |  | func (api *PrivateAdminAPI) AddPeer(url string) (bool, error) { | 
					
						
							|  |  |  | 	// Make sure the server is running, fail otherwise | 
					
						
							|  |  |  | 	server := api.node.Server() | 
					
						
							|  |  |  | 	if server == nil { | 
					
						
							|  |  |  | 		return false, ErrNodeStopped | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Try to add the url as a static peer and return | 
					
						
							|  |  |  | 	node, err := discover.ParseNode(url) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false, fmt.Errorf("invalid enode: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	server.AddPeer(node) | 
					
						
							|  |  |  | 	return true, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 16:27:55 -04:00
										 |  |  | // RemovePeer disconnects from a a remote node if the connection exists | 
					
						
							|  |  |  | func (api *PrivateAdminAPI) RemovePeer(url string) (bool, error) { | 
					
						
							|  |  |  | 	// Make sure the server is running, fail otherwise | 
					
						
							|  |  |  | 	server := api.node.Server() | 
					
						
							|  |  |  | 	if server == nil { | 
					
						
							|  |  |  | 		return false, ErrNodeStopped | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Try to remove the url as a static peer and return | 
					
						
							|  |  |  | 	node, err := discover.ParseNode(url) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false, fmt.Errorf("invalid enode: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	server.RemovePeer(node) | 
					
						
							|  |  |  | 	return true, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-25 09:08:07 +01:00
										 |  |  | // PeerEvents creates an RPC subscription which receives peer events from the | 
					
						
							|  |  |  | // node's p2p.Server | 
					
						
							|  |  |  | func (api *PrivateAdminAPI) PeerEvents(ctx context.Context) (*rpc.Subscription, error) { | 
					
						
							|  |  |  | 	// Make sure the server is running, fail otherwise | 
					
						
							|  |  |  | 	server := api.node.Server() | 
					
						
							|  |  |  | 	if server == nil { | 
					
						
							|  |  |  | 		return nil, ErrNodeStopped | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Create the subscription | 
					
						
							|  |  |  | 	notifier, supported := rpc.NotifierFromContext(ctx) | 
					
						
							|  |  |  | 	if !supported { | 
					
						
							|  |  |  | 		return nil, rpc.ErrNotificationsUnsupported | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	rpcSub := notifier.CreateSubscription() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	go func() { | 
					
						
							|  |  |  | 		events := make(chan *p2p.PeerEvent) | 
					
						
							|  |  |  | 		sub := server.SubscribeEvents(events) | 
					
						
							|  |  |  | 		defer sub.Unsubscribe() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for { | 
					
						
							|  |  |  | 			select { | 
					
						
							|  |  |  | 			case event := <-events: | 
					
						
							|  |  |  | 				notifier.Notify(rpcSub.ID, event) | 
					
						
							|  |  |  | 			case <-sub.Err(): | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			case <-rpcSub.Err(): | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			case <-notifier.Closed(): | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return rpcSub, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | // StartRPC starts the HTTP RPC API server. | 
					
						
							| 
									
										
										
										
											2018-02-12 13:52:07 +01:00
										 |  |  | func (api *PrivateAdminAPI) StartRPC(host *string, port *int, cors *string, apis *string, vhosts *string) (bool, error) { | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	api.node.lock.Lock() | 
					
						
							|  |  |  | 	defer api.node.lock.Unlock() | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	if api.node.httpHandler != nil { | 
					
						
							|  |  |  | 		return false, fmt.Errorf("HTTP RPC already running on %s", api.node.httpEndpoint) | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if host == nil { | 
					
						
							| 
									
										
										
										
											2016-09-16 11:53:50 +02:00
										 |  |  | 		h := DefaultHTTPHost | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 		if api.node.config.HTTPHost != "" { | 
					
						
							|  |  |  | 			h = api.node.config.HTTPHost | 
					
						
							| 
									
										
										
										
											2016-05-04 13:40:07 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		host = &h | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if port == nil { | 
					
						
							| 
									
										
										
										
											2016-12-17 15:39:55 +01:00
										 |  |  | 		port = &api.node.config.HTTPPort | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-12 23:04:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	allowedOrigins := api.node.config.HTTPCors | 
					
						
							|  |  |  | 	if cors != nil { | 
					
						
							|  |  |  | 		allowedOrigins = nil | 
					
						
							|  |  |  | 		for _, origin := range strings.Split(*cors, ",") { | 
					
						
							|  |  |  | 			allowedOrigins = append(allowedOrigins, strings.TrimSpace(origin)) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-12 13:52:07 +01:00
										 |  |  | 	allowedVHosts := api.node.config.HTTPVirtualHosts | 
					
						
							|  |  |  | 	if vhosts != nil { | 
					
						
							|  |  |  | 		allowedVHosts = nil | 
					
						
							|  |  |  | 		for _, vhost := range strings.Split(*host, ",") { | 
					
						
							|  |  |  | 			allowedVHosts = append(allowedVHosts, strings.TrimSpace(vhost)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	modules := api.node.httpWhitelist | 
					
						
							|  |  |  | 	if apis != nil { | 
					
						
							|  |  |  | 		modules = nil | 
					
						
							|  |  |  | 		for _, m := range strings.Split(*apis, ",") { | 
					
						
							|  |  |  | 			modules = append(modules, strings.TrimSpace(m)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-12 13:52:07 +01:00
										 |  |  | 	if err := api.node.startHTTP(fmt.Sprintf("%s:%d", *host, *port), api.node.rpcAPIs, modules, allowedOrigins, allowedVHosts); err != nil { | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 		return false, err | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	return true, nil | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // StopRPC terminates an already running HTTP RPC API endpoint. | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | func (api *PrivateAdminAPI) StopRPC() (bool, error) { | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	api.node.lock.Lock() | 
					
						
							|  |  |  | 	defer api.node.lock.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if api.node.httpHandler == nil { | 
					
						
							|  |  |  | 		return false, fmt.Errorf("HTTP RPC not running") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	api.node.stopHTTP() | 
					
						
							|  |  |  | 	return true, nil | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // StartWS starts the websocket RPC API server. | 
					
						
							| 
									
										
										
										
											2016-12-17 15:39:55 +01:00
										 |  |  | func (api *PrivateAdminAPI) StartWS(host *string, port *int, allowedOrigins *string, apis *string) (bool, error) { | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 	api.node.lock.Lock() | 
					
						
							|  |  |  | 	defer api.node.lock.Unlock() | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 	if api.node.wsHandler != nil { | 
					
						
							| 
									
										
										
										
											2016-02-09 14:10:40 +02:00
										 |  |  | 		return false, fmt.Errorf("WebSocket RPC already running on %s", api.node.wsEndpoint) | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if host == nil { | 
					
						
							| 
									
										
										
										
											2016-09-16 11:53:50 +02:00
										 |  |  | 		h := DefaultWSHost | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 		if api.node.config.WSHost != "" { | 
					
						
							|  |  |  | 			h = api.node.config.WSHost | 
					
						
							| 
									
										
										
										
											2016-05-04 13:40:07 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		host = &h | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if port == nil { | 
					
						
							| 
									
										
										
										
											2016-12-17 15:39:55 +01:00
										 |  |  | 		port = &api.node.config.WSPort | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-04-12 23:04:14 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	origins := api.node.config.WSOrigins | 
					
						
							|  |  |  | 	if allowedOrigins != nil { | 
					
						
							|  |  |  | 		origins = nil | 
					
						
							|  |  |  | 		for _, origin := range strings.Split(*allowedOrigins, ",") { | 
					
						
							|  |  |  | 			origins = append(origins, strings.TrimSpace(origin)) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 	modules := api.node.config.WSModules | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	if apis != nil { | 
					
						
							|  |  |  | 		modules = nil | 
					
						
							|  |  |  | 		for _, m := range strings.Split(*apis, ",") { | 
					
						
							|  |  |  | 			modules = append(modules, strings.TrimSpace(m)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-25 09:08:07 +01:00
										 |  |  | 	if err := api.node.startWS(fmt.Sprintf("%s:%d", *host, *port), api.node.rpcAPIs, modules, origins, api.node.config.WSExposeAll); err != nil { | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 		return false, err | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 	return true, nil | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // StopRPC terminates an already running websocket RPC API endpoint. | 
					
						
							|  |  |  | func (api *PrivateAdminAPI) StopWS() (bool, error) { | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 	api.node.lock.Lock() | 
					
						
							|  |  |  | 	defer api.node.lock.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if api.node.wsHandler == nil { | 
					
						
							|  |  |  | 		return false, fmt.Errorf("WebSocket RPC not running") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	api.node.stopWS() | 
					
						
							|  |  |  | 	return true, nil | 
					
						
							| 
									
										
										
										
											2015-12-04 20:56:11 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // PublicAdminAPI is the collection of administrative API methods exposed over | 
					
						
							|  |  |  | // both secure and unsecure RPC channels. | 
					
						
							|  |  |  | type PublicAdminAPI struct { | 
					
						
							|  |  |  | 	node *Node // Node interfaced by this API | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewPublicAdminAPI creates a new API definition for the public admin methods | 
					
						
							|  |  |  | // of the node itself. | 
					
						
							|  |  |  | func NewPublicAdminAPI(node *Node) *PublicAdminAPI { | 
					
						
							|  |  |  | 	return &PublicAdminAPI{node: node} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Peers retrieves all the information we know about each individual peer at the | 
					
						
							|  |  |  | // protocol granularity. | 
					
						
							|  |  |  | func (api *PublicAdminAPI) Peers() ([]*p2p.PeerInfo, error) { | 
					
						
							|  |  |  | 	server := api.node.Server() | 
					
						
							|  |  |  | 	if server == nil { | 
					
						
							|  |  |  | 		return nil, ErrNodeStopped | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return server.PeersInfo(), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NodeInfo retrieves all the information we know about the host node at the | 
					
						
							|  |  |  | // protocol granularity. | 
					
						
							|  |  |  | func (api *PublicAdminAPI) NodeInfo() (*p2p.NodeInfo, error) { | 
					
						
							|  |  |  | 	server := api.node.Server() | 
					
						
							|  |  |  | 	if server == nil { | 
					
						
							|  |  |  | 		return nil, ErrNodeStopped | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return server.NodeInfo(), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Datadir retrieves the current data directory the node is using. | 
					
						
							|  |  |  | func (api *PublicAdminAPI) Datadir() string { | 
					
						
							|  |  |  | 	return api.node.DataDir() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // PublicDebugAPI is the collection of debugging related API methods exposed over | 
					
						
							|  |  |  | // both secure and unsecure RPC channels. | 
					
						
							|  |  |  | type PublicDebugAPI struct { | 
					
						
							|  |  |  | 	node *Node // Node interfaced by this API | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewPublicDebugAPI creates a new API definition for the public debug methods | 
					
						
							|  |  |  | // of the node itself. | 
					
						
							|  |  |  | func NewPublicDebugAPI(node *Node) *PublicDebugAPI { | 
					
						
							|  |  |  | 	return &PublicDebugAPI{node: node} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Metrics retrieves all the known system metric collected by the node. | 
					
						
							|  |  |  | func (api *PublicDebugAPI) Metrics(raw bool) (map[string]interface{}, error) { | 
					
						
							|  |  |  | 	// Create a rate formatter | 
					
						
							|  |  |  | 	units := []string{"", "K", "M", "G", "T", "E", "P"} | 
					
						
							|  |  |  | 	round := func(value float64, prec int) string { | 
					
						
							|  |  |  | 		unit := 0 | 
					
						
							|  |  |  | 		for value >= 1000 { | 
					
						
							|  |  |  | 			unit, value, prec = unit+1, value/1000, 2 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return fmt.Sprintf(fmt.Sprintf("%%.%df%s", prec, units[unit]), value) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	format := func(total float64, rate float64) string { | 
					
						
							|  |  |  | 		return fmt.Sprintf("%s (%s/s)", round(total, 0), round(rate, 2)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Iterate over all the metrics, and just dump for now | 
					
						
							|  |  |  | 	counters := make(map[string]interface{}) | 
					
						
							|  |  |  | 	metrics.DefaultRegistry.Each(func(name string, metric interface{}) { | 
					
						
							|  |  |  | 		// Create or retrieve the counter hierarchy for this metric | 
					
						
							|  |  |  | 		root, parts := counters, strings.Split(name, "/") | 
					
						
							|  |  |  | 		for _, part := range parts[:len(parts)-1] { | 
					
						
							|  |  |  | 			if _, ok := root[part]; !ok { | 
					
						
							|  |  |  | 				root[part] = make(map[string]interface{}) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			root = root[part].(map[string]interface{}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		name = parts[len(parts)-1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Fill the counter with the metric details, formatting if requested | 
					
						
							|  |  |  | 		if raw { | 
					
						
							|  |  |  | 			switch metric := metric.(type) { | 
					
						
							|  |  |  | 			case metrics.Meter: | 
					
						
							|  |  |  | 				root[name] = map[string]interface{}{ | 
					
						
							|  |  |  | 					"AvgRate01Min": metric.Rate1(), | 
					
						
							|  |  |  | 					"AvgRate05Min": metric.Rate5(), | 
					
						
							|  |  |  | 					"AvgRate15Min": metric.Rate15(), | 
					
						
							|  |  |  | 					"MeanRate":     metric.RateMean(), | 
					
						
							|  |  |  | 					"Overall":      float64(metric.Count()), | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case metrics.Timer: | 
					
						
							|  |  |  | 				root[name] = map[string]interface{}{ | 
					
						
							|  |  |  | 					"AvgRate01Min": metric.Rate1(), | 
					
						
							|  |  |  | 					"AvgRate05Min": metric.Rate5(), | 
					
						
							|  |  |  | 					"AvgRate15Min": metric.Rate15(), | 
					
						
							|  |  |  | 					"MeanRate":     metric.RateMean(), | 
					
						
							|  |  |  | 					"Overall":      float64(metric.Count()), | 
					
						
							|  |  |  | 					"Percentiles": map[string]interface{}{ | 
					
						
							|  |  |  | 						"5":  metric.Percentile(0.05), | 
					
						
							|  |  |  | 						"20": metric.Percentile(0.2), | 
					
						
							|  |  |  | 						"50": metric.Percentile(0.5), | 
					
						
							|  |  |  | 						"80": metric.Percentile(0.8), | 
					
						
							|  |  |  | 						"95": metric.Percentile(0.95), | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				root[name] = "Unknown metric type" | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			switch metric := metric.(type) { | 
					
						
							|  |  |  | 			case metrics.Meter: | 
					
						
							|  |  |  | 				root[name] = map[string]interface{}{ | 
					
						
							|  |  |  | 					"Avg01Min": format(metric.Rate1()*60, metric.Rate1()), | 
					
						
							|  |  |  | 					"Avg05Min": format(metric.Rate5()*300, metric.Rate5()), | 
					
						
							|  |  |  | 					"Avg15Min": format(metric.Rate15()*900, metric.Rate15()), | 
					
						
							|  |  |  | 					"Overall":  format(float64(metric.Count()), metric.RateMean()), | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case metrics.Timer: | 
					
						
							|  |  |  | 				root[name] = map[string]interface{}{ | 
					
						
							|  |  |  | 					"Avg01Min": format(metric.Rate1()*60, metric.Rate1()), | 
					
						
							|  |  |  | 					"Avg05Min": format(metric.Rate5()*300, metric.Rate5()), | 
					
						
							|  |  |  | 					"Avg15Min": format(metric.Rate15()*900, metric.Rate15()), | 
					
						
							|  |  |  | 					"Overall":  format(float64(metric.Count()), metric.RateMean()), | 
					
						
							|  |  |  | 					"Maximum":  time.Duration(metric.Max()).String(), | 
					
						
							|  |  |  | 					"Minimum":  time.Duration(metric.Min()).String(), | 
					
						
							|  |  |  | 					"Percentiles": map[string]interface{}{ | 
					
						
							|  |  |  | 						"5":  time.Duration(metric.Percentile(0.05)).String(), | 
					
						
							|  |  |  | 						"20": time.Duration(metric.Percentile(0.2)).String(), | 
					
						
							|  |  |  | 						"50": time.Duration(metric.Percentile(0.5)).String(), | 
					
						
							|  |  |  | 						"80": time.Duration(metric.Percentile(0.8)).String(), | 
					
						
							|  |  |  | 						"95": time.Duration(metric.Percentile(0.95)).String(), | 
					
						
							|  |  |  | 					}, | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				root[name] = "Unknown metric type" | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	return counters, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | // PublicWeb3API offers helper utils | 
					
						
							|  |  |  | type PublicWeb3API struct { | 
					
						
							|  |  |  | 	stack *Node | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewPublicWeb3API creates a new Web3Service instance | 
					
						
							|  |  |  | func NewPublicWeb3API(stack *Node) *PublicWeb3API { | 
					
						
							|  |  |  | 	return &PublicWeb3API{stack} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ClientVersion returns the node name | 
					
						
							|  |  |  | func (s *PublicWeb3API) ClientVersion() string { | 
					
						
							|  |  |  | 	return s.stack.Server().Name | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Sha3 applies the ethereum sha3 implementation on the input. | 
					
						
							|  |  |  | // It assumes the input is hex encoded. | 
					
						
							| 
									
										
										
										
											2016-11-28 17:14:55 +01:00
										 |  |  | func (s *PublicWeb3API) Sha3(input hexutil.Bytes) hexutil.Bytes { | 
					
						
							|  |  |  | 	return crypto.Keccak256(input) | 
					
						
							| 
									
										
										
										
											2015-12-16 10:58:01 +01:00
										 |  |  | } |