| 
									
										
										
										
											2016-04-14 18:18:24 +02:00
										 |  |  | // Copyright 2014 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | // 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 ( | 
					
						
							|  |  |  | 	"crypto/ecdsa" | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"net" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 	"runtime" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/accounts" | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/p2p/discover" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/p2p/nat" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 	datadirPrivateKey      = "nodekey"            // Path within the datadir to the node's private key | 
					
						
							|  |  |  | 	datadirDefaultKeyStore = "keystore"           // Path within the datadir to the keystore | 
					
						
							|  |  |  | 	datadirStaticNodes     = "static-nodes.json"  // Path within the datadir to the static node list | 
					
						
							|  |  |  | 	datadirTrustedNodes    = "trusted-nodes.json" // Path within the datadir to the trusted node list | 
					
						
							|  |  |  | 	datadirNodeDatabase    = "nodes"              // Path within the datadir to store the node infos | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Config represents a small collection of configuration values to fine tune the | 
					
						
							|  |  |  | // P2P network layer of a protocol stack. These values can be further extended by | 
					
						
							|  |  |  | // all registered services. | 
					
						
							|  |  |  | type Config struct { | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 	// Name sets the instance name of the node. It must not contain the / character and is | 
					
						
							|  |  |  | 	// used in the devp2p node identifier. The instance name of geth is "geth". If no | 
					
						
							|  |  |  | 	// value is specified, the basename of the current executable is used. | 
					
						
							|  |  |  | 	Name string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// UserIdent, if set, is used as an additional component in the devp2p node identifier. | 
					
						
							|  |  |  | 	UserIdent string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Version should be set to the version number of the program. It is used | 
					
						
							|  |  |  | 	// in the devp2p node identifier. | 
					
						
							|  |  |  | 	Version string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	// DataDir is the file system folder the node should use for any data storage | 
					
						
							|  |  |  | 	// requirements. The configured data directory will not be directly shared with | 
					
						
							|  |  |  | 	// registered services, instead those can use utility methods to create/access | 
					
						
							|  |  |  | 	// databases or flat files. This enables ephemeral nodes which can fully reside | 
					
						
							|  |  |  | 	// in memory. | 
					
						
							|  |  |  | 	DataDir string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 	// KeyStoreDir is the file system folder that contains private keys. The directory can | 
					
						
							|  |  |  | 	// be specified as a relative path, in which case it is resolved relative to the | 
					
						
							|  |  |  | 	// current directory. | 
					
						
							|  |  |  | 	// | 
					
						
							|  |  |  | 	// If KeyStoreDir is empty, the default location is the "keystore" subdirectory of | 
					
						
							|  |  |  | 	// DataDir. If DataDir is unspecified and KeyStoreDir is empty, an ephemeral directory | 
					
						
							|  |  |  | 	// is created by New and destroyed when the node is stopped. | 
					
						
							|  |  |  | 	KeyStoreDir string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// UseLightweightKDF lowers the memory and CPU requirements of the key store | 
					
						
							|  |  |  | 	// scrypt KDF at the expense of security. | 
					
						
							|  |  |  | 	UseLightweightKDF bool | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	// IPCPath is the requested location to place the IPC endpoint. If the path is | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 	// a simple file name, it is placed inside the data directory (or on the root | 
					
						
							|  |  |  | 	// pipe path on Windows), whereas if it's a resolvable path name (absolute or | 
					
						
							|  |  |  | 	// relative), then that specific path is enforced. An empty path disables IPC. | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	IPCPath string | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	// This field should be a valid secp256k1 private key that will be used for both | 
					
						
							|  |  |  | 	// remote peer identification as well as network traffic encryption. If no key | 
					
						
							|  |  |  | 	// is configured, the preset one is loaded from the data dir, generating it if | 
					
						
							|  |  |  | 	// needed. | 
					
						
							|  |  |  | 	PrivateKey *ecdsa.PrivateKey | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// NoDiscovery specifies whether the peer discovery mechanism should be started | 
					
						
							|  |  |  | 	// or not. Disabling is usually useful for protocol debugging (manual topology). | 
					
						
							|  |  |  | 	NoDiscovery bool | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-19 13:04:55 +02:00
										 |  |  | 	DiscoveryV5 bool | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	// Bootstrap nodes used to establish connectivity with the rest of the network. | 
					
						
							|  |  |  | 	BootstrapNodes []*discover.Node | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Network interface address on which the node should listen for inbound peers. | 
					
						
							|  |  |  | 	ListenAddr string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-19 13:04:55 +02:00
										 |  |  | 	ListenAddrV5 string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	// If set to a non-nil value, the given NAT port mapper is used to make the | 
					
						
							|  |  |  | 	// listening port available to the Internet. | 
					
						
							|  |  |  | 	NAT nat.Interface | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If Dialer is set to a non-nil value, the given Dialer is used to dial outbound | 
					
						
							|  |  |  | 	// peer connections. | 
					
						
							|  |  |  | 	Dialer *net.Dialer | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If NoDial is true, the node will not dial any peers. | 
					
						
							|  |  |  | 	NoDial bool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// MaxPeers is the maximum number of peers that can be connected. If this is | 
					
						
							|  |  |  | 	// set to zero, then only the configured static and trusted peers can connect. | 
					
						
							|  |  |  | 	MaxPeers int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// MaxPendingPeers is the maximum number of peers that can be pending in the | 
					
						
							|  |  |  | 	// handshake phase, counted separately for inbound and outbound connections. | 
					
						
							|  |  |  | 	// Zero defaults to preset values. | 
					
						
							|  |  |  | 	MaxPendingPeers int | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	// HTTPHost is the host interface on which to start the HTTP RPC server. If this | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	// field is empty, no HTTP API endpoint will be started. | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	HTTPHost string | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	// HTTPPort is the TCP port number on which to start the HTTP RPC server. The | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	// default zero value is/ valid and will pick a port number randomly (useful | 
					
						
							|  |  |  | 	// for ephemeral nodes). | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	HTTPPort int | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	// HTTPCors is the Cross-Origin Resource Sharing header to send to requesting | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	// clients. Please be aware that CORS is a browser enforced security, it's fully | 
					
						
							|  |  |  | 	// useless for custom HTTP clients. | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	HTTPCors string | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	// HTTPModules is a list of API modules to expose via the HTTP RPC interface. | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 	// If the module list is empty, all RPC API endpoints designated public will be | 
					
						
							|  |  |  | 	// exposed. | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	HTTPModules []string | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	// WSHost is the host interface on which to start the websocket RPC server. If | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 	// this field is empty, no websocket API endpoint will be started. | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	WSHost string | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	// WSPort is the TCP port number on which to start the websocket RPC server. The | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 	// default zero value is/ valid and will pick a port number randomly (useful for | 
					
						
							|  |  |  | 	// ephemeral nodes). | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	WSPort int | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	// WSOrigins is the list of domain to accept websocket requests from. Please be | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	// aware that the server can only act upon the HTTP request the client sends and | 
					
						
							|  |  |  | 	// cannot verify the validity of the request header. | 
					
						
							| 
									
										
										
										
											2016-03-14 09:38:54 +01:00
										 |  |  | 	WSOrigins string | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	// WSModules is a list of API modules to expose via the websocket RPC interface. | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 	// If the module list is empty, all RPC API endpoints designated public will be | 
					
						
							|  |  |  | 	// exposed. | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	WSModules []string | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | // IPCEndpoint resolves an IPC endpoint based on a configured value, taking into | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | // account the set data folders as well as the designated platform we're currently | 
					
						
							|  |  |  | // running on. | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | func (c *Config) IPCEndpoint() string { | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 	// Short circuit if IPC has not been enabled | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	if c.IPCPath == "" { | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 		return "" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// On windows we can only use plain top-level pipes | 
					
						
							|  |  |  | 	if runtime.GOOS == "windows" { | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 		if strings.HasPrefix(c.IPCPath, `\\.\pipe\`) { | 
					
						
							|  |  |  | 			return c.IPCPath | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 		return `\\.\pipe\` + c.IPCPath | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Resolve names into the data directory full paths otherwise | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	if filepath.Base(c.IPCPath) == c.IPCPath { | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 		if c.DataDir == "" { | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 			return filepath.Join(os.TempDir(), c.IPCPath) | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 		return filepath.Join(c.DataDir, c.IPCPath) | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	return c.IPCPath | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | // NodeDB returns the path to the discovery node database. | 
					
						
							|  |  |  | func (c *Config) NodeDB() string { | 
					
						
							|  |  |  | 	if c.DataDir == "" { | 
					
						
							|  |  |  | 		return "" // ephemeral | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return c.resolvePath("nodes") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | // DefaultIPCEndpoint returns the IPC path used by default. | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | func DefaultIPCEndpoint(clientIdentifier string) string { | 
					
						
							|  |  |  | 	if clientIdentifier == "" { | 
					
						
							|  |  |  | 		clientIdentifier = strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") | 
					
						
							|  |  |  | 		if clientIdentifier == "" { | 
					
						
							|  |  |  | 			panic("empty executable name") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-09-16 11:53:50 +02:00
										 |  |  | 	config := &Config{DataDir: DefaultDataDir(), IPCPath: clientIdentifier + ".ipc"} | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	return config.IPCEndpoint() | 
					
						
							| 
									
										
										
										
											2016-02-02 19:06:43 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | // HTTPEndpoint resolves an HTTP endpoint based on the configured host interface | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | // and port parameters. | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | func (c *Config) HTTPEndpoint() string { | 
					
						
							|  |  |  | 	if c.HTTPHost == "" { | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | 		return "" | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	return fmt.Sprintf("%s:%d", c.HTTPHost, c.HTTPPort) | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | // DefaultHTTPEndpoint returns the HTTP endpoint used by default. | 
					
						
							|  |  |  | func DefaultHTTPEndpoint() string { | 
					
						
							| 
									
										
										
										
											2016-09-16 11:53:50 +02:00
										 |  |  | 	config := &Config{HTTPHost: DefaultHTTPHost, HTTPPort: DefaultHTTPPort} | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	return config.HTTPEndpoint() | 
					
						
							| 
									
										
										
										
											2016-02-05 13:45:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | // WSEndpoint resolves an websocket endpoint based on the configured host interface | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | // and port parameters. | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | func (c *Config) WSEndpoint() string { | 
					
						
							|  |  |  | 	if c.WSHost == "" { | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | 		return "" | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	return fmt.Sprintf("%s:%d", c.WSHost, c.WSPort) | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | // DefaultWSEndpoint returns the websocket endpoint used by default. | 
					
						
							|  |  |  | func DefaultWSEndpoint() string { | 
					
						
							| 
									
										
										
										
											2016-09-16 11:53:50 +02:00
										 |  |  | 	config := &Config{WSHost: DefaultWSHost, WSPort: DefaultWSPort} | 
					
						
							| 
									
										
										
										
											2016-02-09 13:24:42 +02:00
										 |  |  | 	return config.WSEndpoint() | 
					
						
							| 
									
										
										
										
											2016-02-05 15:08:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | // NodeName returns the devp2p node identifier. | 
					
						
							|  |  |  | func (c *Config) NodeName() string { | 
					
						
							|  |  |  | 	name := c.name() | 
					
						
							|  |  |  | 	// Backwards compatibility: previous versions used title-cased "Geth", keep that. | 
					
						
							|  |  |  | 	if name == "geth" || name == "geth-testnet" { | 
					
						
							|  |  |  | 		name = "Geth" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if c.UserIdent != "" { | 
					
						
							|  |  |  | 		name += "/" + c.UserIdent | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if c.Version != "" { | 
					
						
							|  |  |  | 		name += "/v" + c.Version | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	name += "/" + runtime.GOOS | 
					
						
							|  |  |  | 	name += "/" + runtime.Version() | 
					
						
							|  |  |  | 	return name | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Config) name() string { | 
					
						
							|  |  |  | 	if c.Name == "" { | 
					
						
							|  |  |  | 		progname := strings.TrimSuffix(filepath.Base(os.Args[0]), ".exe") | 
					
						
							|  |  |  | 		if progname == "" { | 
					
						
							|  |  |  | 			panic("empty executable name, set Config.Name") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return progname | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return c.Name | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // These resources are resolved differently for the "geth" and "geth-testnet" instances. | 
					
						
							|  |  |  | var isOldGethResource = map[string]bool{ | 
					
						
							|  |  |  | 	"chaindata":          true, | 
					
						
							|  |  |  | 	"nodes":              true, | 
					
						
							|  |  |  | 	"nodekey":            true, | 
					
						
							|  |  |  | 	"static-nodes.json":  true, | 
					
						
							|  |  |  | 	"trusted-nodes.json": true, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // resolvePath resolves path in the instance directory. | 
					
						
							|  |  |  | func (c *Config) resolvePath(path string) string { | 
					
						
							|  |  |  | 	if filepath.IsAbs(path) { | 
					
						
							|  |  |  | 		return path | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if c.DataDir == "" { | 
					
						
							|  |  |  | 		return "" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Backwards-compatibility: ensure that data directory files created | 
					
						
							|  |  |  | 	// by geth 1.4 are used if they exist. | 
					
						
							|  |  |  | 	if c.name() == "geth" && isOldGethResource[path] { | 
					
						
							|  |  |  | 		oldpath := "" | 
					
						
							|  |  |  | 		if c.Name == "geth" { | 
					
						
							|  |  |  | 			oldpath = filepath.Join(c.DataDir, path) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if oldpath != "" && common.FileExist(oldpath) { | 
					
						
							|  |  |  | 			// TODO: print warning | 
					
						
							|  |  |  | 			return oldpath | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return filepath.Join(c.DataDir, c.name(), path) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | // NodeKey retrieves the currently configured private key of the node, checking | 
					
						
							|  |  |  | // first any manually set key, falling back to the one found in the configured | 
					
						
							|  |  |  | // data folder. If no key can be found, a new one is generated. | 
					
						
							|  |  |  | func (c *Config) NodeKey() *ecdsa.PrivateKey { | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 	// Use any specifically configured key. | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	if c.PrivateKey != nil { | 
					
						
							|  |  |  | 		return c.PrivateKey | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 	// Generate ephemeral key if no datadir is being used. | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	if c.DataDir == "" { | 
					
						
							|  |  |  | 		key, err := crypto.GenerateKey() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			glog.Fatalf("Failed to generate ephemeral node key: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return key | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	keyfile := c.resolvePath(datadirPrivateKey) | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	if key, err := crypto.LoadECDSA(keyfile); err == nil { | 
					
						
							|  |  |  | 		return key | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 	// No persistent key found, generate and store a new one. | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	key, err := crypto.GenerateKey() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		glog.Fatalf("Failed to generate node key: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 	instanceDir := filepath.Join(c.DataDir, c.name()) | 
					
						
							|  |  |  | 	if err := os.MkdirAll(instanceDir, 0700); err != nil { | 
					
						
							|  |  |  | 		glog.V(logger.Error).Infof("Failed to persist node key: %v", err) | 
					
						
							|  |  |  | 		return key | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	keyfile = filepath.Join(instanceDir, datadirPrivateKey) | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 	if err := crypto.SaveECDSA(keyfile, key); err != nil { | 
					
						
							|  |  |  | 		glog.V(logger.Error).Infof("Failed to persist node key: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return key | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // StaticNodes returns a list of node enode URLs configured as static nodes. | 
					
						
							|  |  |  | func (c *Config) StaticNodes() []*discover.Node { | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 	return c.parsePersistentNodes(c.resolvePath(datadirStaticNodes)) | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TrusterNodes returns a list of node enode URLs configured as trusted nodes. | 
					
						
							|  |  |  | func (c *Config) TrusterNodes() []*discover.Node { | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 	return c.parsePersistentNodes(c.resolvePath(datadirTrustedNodes)) | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // parsePersistentNodes parses a list of discovery node URLs loaded from a .json | 
					
						
							|  |  |  | // file from within the data directory. | 
					
						
							|  |  |  | func (c *Config) parsePersistentNodes(file string) []*discover.Node { | 
					
						
							|  |  |  | 	// Short circuit if no node config is present | 
					
						
							|  |  |  | 	if c.DataDir == "" { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	path := filepath.Join(c.DataDir, file) | 
					
						
							|  |  |  | 	if _, err := os.Stat(path); err != nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-18 13:28:17 +02:00
										 |  |  | 	// Load the nodes from the config file. | 
					
						
							|  |  |  | 	var nodelist []string | 
					
						
							|  |  |  | 	if err := common.LoadJSON(path, &nodelist); err != nil { | 
					
						
							|  |  |  | 		glog.V(logger.Error).Infof("Can't load node file %s: %v", path, err) | 
					
						
							| 
									
										
										
										
											2015-11-05 23:57:57 +02:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Interpret the list as a discovery node array | 
					
						
							|  |  |  | 	var nodes []*discover.Node | 
					
						
							|  |  |  | 	for _, url := range nodelist { | 
					
						
							|  |  |  | 		if url == "" { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		node, err := discover.ParseNode(url) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			glog.V(logger.Error).Infof("Node URL %s: %v\n", url, err) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		nodes = append(nodes, node) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nodes | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-15 18:38:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | func makeAccountManager(conf *Config) (am *accounts.Manager, ephemeralKeystore string, err error) { | 
					
						
							|  |  |  | 	scryptN := accounts.StandardScryptN | 
					
						
							|  |  |  | 	scryptP := accounts.StandardScryptP | 
					
						
							|  |  |  | 	if conf.UseLightweightKDF { | 
					
						
							|  |  |  | 		scryptN = accounts.LightScryptN | 
					
						
							|  |  |  | 		scryptP = accounts.LightScryptP | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var keydir string | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case filepath.IsAbs(conf.KeyStoreDir): | 
					
						
							|  |  |  | 		keydir = conf.KeyStoreDir | 
					
						
							|  |  |  | 	case conf.DataDir != "": | 
					
						
							|  |  |  | 		if conf.KeyStoreDir == "" { | 
					
						
							|  |  |  | 			keydir = filepath.Join(conf.DataDir, datadirDefaultKeyStore) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			keydir, err = filepath.Abs(conf.KeyStoreDir) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case conf.KeyStoreDir != "": | 
					
						
							|  |  |  | 		keydir, err = filepath.Abs(conf.KeyStoreDir) | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		// There is no datadir. | 
					
						
							|  |  |  | 		keydir, err = ioutil.TempDir("", "go-ethereum-keystore") | 
					
						
							|  |  |  | 		ephemeralKeystore = keydir | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := os.MkdirAll(keydir, 0700); err != nil { | 
					
						
							|  |  |  | 		return nil, "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return accounts.NewManager(keydir, scryptN, scryptP), ephemeralKeystore, nil | 
					
						
							|  |  |  | } |