github.com/devfans/go-ethereum@v1.5.10-0.20170326212234-7419d0c38291/cmd/utils/flags.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package utils contains internal helper functions for go-ethereum commands.
    18  package utils
    19  
    20  import (
    21  	"crypto/ecdsa"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"os"
    26  	"os/user"
    27  	"path/filepath"
    28  	"runtime"
    29  	"strconv"
    30  	"strings"
    31  
    32  	"github.com/ethereum/go-ethereum/accounts"
    33  	"github.com/ethereum/go-ethereum/accounts/keystore"
    34  	"github.com/ethereum/go-ethereum/common"
    35  	"github.com/ethereum/go-ethereum/core"
    36  	"github.com/ethereum/go-ethereum/core/state"
    37  	"github.com/ethereum/go-ethereum/core/vm"
    38  	"github.com/ethereum/go-ethereum/crypto"
    39  	"github.com/ethereum/go-ethereum/eth"
    40  	"github.com/ethereum/go-ethereum/ethdb"
    41  	"github.com/ethereum/go-ethereum/ethstats"
    42  	"github.com/ethereum/go-ethereum/event"
    43  	"github.com/ethereum/go-ethereum/les"
    44  	"github.com/ethereum/go-ethereum/log"
    45  	"github.com/ethereum/go-ethereum/metrics"
    46  	"github.com/ethereum/go-ethereum/node"
    47  	"github.com/ethereum/go-ethereum/p2p/discover"
    48  	"github.com/ethereum/go-ethereum/p2p/discv5"
    49  	"github.com/ethereum/go-ethereum/p2p/nat"
    50  	"github.com/ethereum/go-ethereum/p2p/netutil"
    51  	"github.com/ethereum/go-ethereum/params"
    52  	"github.com/ethereum/go-ethereum/pow"
    53  	"github.com/ethereum/go-ethereum/rpc"
    54  	whisper "github.com/ethereum/go-ethereum/whisper/whisperv2"
    55  	"gopkg.in/urfave/cli.v1"
    56  )
    57  
    58  func init() {
    59  	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
    60  
    61  VERSION:
    62     {{.Version}}
    63  
    64  COMMANDS:
    65     {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    66     {{end}}{{if .Flags}}
    67  GLOBAL OPTIONS:
    68     {{range .Flags}}{{.}}
    69     {{end}}{{end}}
    70  `
    71  
    72  	cli.CommandHelpTemplate = `{{.Name}}{{if .Subcommands}} command{{end}}{{if .Flags}} [command options]{{end}} [arguments...]
    73  {{if .Description}}{{.Description}}
    74  {{end}}{{if .Subcommands}}
    75  SUBCOMMANDS:
    76  	{{range .Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    77  	{{end}}{{end}}{{if .Flags}}
    78  OPTIONS:
    79  	{{range .Flags}}{{.}}
    80  	{{end}}{{end}}
    81  `
    82  }
    83  
    84  // NewApp creates an app with sane defaults.
    85  func NewApp(gitCommit, usage string) *cli.App {
    86  	app := cli.NewApp()
    87  	app.Name = filepath.Base(os.Args[0])
    88  	app.Author = ""
    89  	//app.Authors = nil
    90  	app.Email = ""
    91  	app.Version = params.Version
    92  	if gitCommit != "" {
    93  		app.Version += "-" + gitCommit[:8]
    94  	}
    95  	app.Usage = usage
    96  	return app
    97  }
    98  
    99  // These are all the command line flags we support.
   100  // If you add to this list, please remember to include the
   101  // flag in the appropriate command definition.
   102  //
   103  // The flags are defined here so their names and help texts
   104  // are the same for all commands.
   105  
   106  var (
   107  	// General settings
   108  	DataDirFlag = DirectoryFlag{
   109  		Name:  "datadir",
   110  		Usage: "Data directory for the databases and keystore",
   111  		Value: DirectoryString{node.DefaultDataDir()},
   112  	}
   113  	KeyStoreDirFlag = DirectoryFlag{
   114  		Name:  "keystore",
   115  		Usage: "Directory for the keystore (default = inside the datadir)",
   116  	}
   117  	EthashCacheDirFlag = DirectoryFlag{
   118  		Name:  "ethash.cachedir",
   119  		Usage: "Directory to store the ethash verification caches (default = inside the datadir)",
   120  	}
   121  	EthashCachesInMemoryFlag = cli.IntFlag{
   122  		Name:  "ethash.cachesinmem",
   123  		Usage: "Number of recent ethash caches to keep in memory (16MB each)",
   124  		Value: 2,
   125  	}
   126  	EthashCachesOnDiskFlag = cli.IntFlag{
   127  		Name:  "ethash.cachesondisk",
   128  		Usage: "Number of recent ethash caches to keep on disk (16MB each)",
   129  		Value: 3,
   130  	}
   131  	EthashDatasetDirFlag = DirectoryFlag{
   132  		Name:  "ethash.dagdir",
   133  		Usage: "Directory to store the ethash mining DAGs (default = inside home folder)",
   134  	}
   135  	EthashDatasetsInMemoryFlag = cli.IntFlag{
   136  		Name:  "ethash.dagsinmem",
   137  		Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
   138  		Value: 1,
   139  	}
   140  	EthashDatasetsOnDiskFlag = cli.IntFlag{
   141  		Name:  "ethash.dagsondisk",
   142  		Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
   143  		Value: 2,
   144  	}
   145  	NetworkIdFlag = cli.IntFlag{
   146  		Name:  "networkid",
   147  		Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten)",
   148  		Value: eth.NetworkId,
   149  	}
   150  	TestNetFlag = cli.BoolFlag{
   151  		Name:  "testnet",
   152  		Usage: "Ropsten network: pre-configured test network",
   153  	}
   154  	DevModeFlag = cli.BoolFlag{
   155  		Name:  "dev",
   156  		Usage: "Developer mode: pre-configured private network with several debugging flags",
   157  	}
   158  	IdentityFlag = cli.StringFlag{
   159  		Name:  "identity",
   160  		Usage: "Custom node name",
   161  	}
   162  	DocRootFlag = DirectoryFlag{
   163  		Name:  "docroot",
   164  		Usage: "Document Root for HTTPClient file scheme",
   165  		Value: DirectoryString{homeDir()},
   166  	}
   167  	FastSyncFlag = cli.BoolFlag{
   168  		Name:  "fast",
   169  		Usage: "Enable fast syncing through state downloads",
   170  	}
   171  	LightModeFlag = cli.BoolFlag{
   172  		Name:  "light",
   173  		Usage: "Enable light client mode",
   174  	}
   175  	LightServFlag = cli.IntFlag{
   176  		Name:  "lightserv",
   177  		Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
   178  		Value: 0,
   179  	}
   180  	LightPeersFlag = cli.IntFlag{
   181  		Name:  "lightpeers",
   182  		Usage: "Maximum number of LES client peers",
   183  		Value: 20,
   184  	}
   185  	LightKDFFlag = cli.BoolFlag{
   186  		Name:  "lightkdf",
   187  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   188  	}
   189  	// Performance tuning settings
   190  	CacheFlag = cli.IntFlag{
   191  		Name:  "cache",
   192  		Usage: "Megabytes of memory allocated to internal caching (min 16MB / database forced)",
   193  		Value: 128,
   194  	}
   195  	TrieCacheGenFlag = cli.IntFlag{
   196  		Name:  "trie-cache-gens",
   197  		Usage: "Number of trie node generations to keep in memory",
   198  		Value: int(state.MaxTrieCacheGen),
   199  	}
   200  	// Miner settings
   201  	MiningEnabledFlag = cli.BoolFlag{
   202  		Name:  "mine",
   203  		Usage: "Enable mining",
   204  	}
   205  	MinerThreadsFlag = cli.IntFlag{
   206  		Name:  "minerthreads",
   207  		Usage: "Number of CPU threads to use for mining",
   208  		Value: runtime.NumCPU(),
   209  	}
   210  	TargetGasLimitFlag = cli.Uint64Flag{
   211  		Name:  "targetgaslimit",
   212  		Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine",
   213  		Value: params.GenesisGasLimit.Uint64(),
   214  	}
   215  	EtherbaseFlag = cli.StringFlag{
   216  		Name:  "etherbase",
   217  		Usage: "Public address for block mining rewards (default = first account created)",
   218  		Value: "0",
   219  	}
   220  	GasPriceFlag = BigFlag{
   221  		Name:  "gasprice",
   222  		Usage: "Minimal gas price to accept for mining a transactions",
   223  		Value: big.NewInt(20 * params.Shannon),
   224  	}
   225  	ExtraDataFlag = cli.StringFlag{
   226  		Name:  "extradata",
   227  		Usage: "Block extra data set by the miner (default = client version)",
   228  	}
   229  	// Account settings
   230  	UnlockedAccountFlag = cli.StringFlag{
   231  		Name:  "unlock",
   232  		Usage: "Comma separated list of accounts to unlock",
   233  		Value: "",
   234  	}
   235  	PasswordFileFlag = cli.StringFlag{
   236  		Name:  "password",
   237  		Usage: "Password file to use for non-inteactive password input",
   238  		Value: "",
   239  	}
   240  
   241  	VMForceJitFlag = cli.BoolFlag{
   242  		Name:  "forcejit",
   243  		Usage: "Force the JIT VM to take precedence",
   244  	}
   245  	VMJitCacheFlag = cli.IntFlag{
   246  		Name:  "jitcache",
   247  		Usage: "Amount of cached JIT VM programs",
   248  		Value: 64,
   249  	}
   250  	VMEnableJitFlag = cli.BoolFlag{
   251  		Name:  "jitvm",
   252  		Usage: "Enable the JIT VM",
   253  	}
   254  	VMEnableDebugFlag = cli.BoolFlag{
   255  		Name:  "vmdebug",
   256  		Usage: "Record information useful for VM and contract debugging",
   257  	}
   258  	// Logging and debug settings
   259  	EthStatsURLFlag = cli.StringFlag{
   260  		Name:  "ethstats",
   261  		Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
   262  	}
   263  	MetricsEnabledFlag = cli.BoolFlag{
   264  		Name:  metrics.MetricsEnabledFlag,
   265  		Usage: "Enable metrics collection and reporting",
   266  	}
   267  	FakePoWFlag = cli.BoolFlag{
   268  		Name:  "fakepow",
   269  		Usage: "Disables proof-of-work verification",
   270  	}
   271  	NoCompactionFlag = cli.BoolFlag{
   272  		Name:  "nocompaction",
   273  		Usage: "Disables db compaction after import",
   274  	}
   275  	// RPC settings
   276  	RPCEnabledFlag = cli.BoolFlag{
   277  		Name:  "rpc",
   278  		Usage: "Enable the HTTP-RPC server",
   279  	}
   280  	RPCListenAddrFlag = cli.StringFlag{
   281  		Name:  "rpcaddr",
   282  		Usage: "HTTP-RPC server listening interface",
   283  		Value: node.DefaultHTTPHost,
   284  	}
   285  	RPCPortFlag = cli.IntFlag{
   286  		Name:  "rpcport",
   287  		Usage: "HTTP-RPC server listening port",
   288  		Value: node.DefaultHTTPPort,
   289  	}
   290  	RPCCORSDomainFlag = cli.StringFlag{
   291  		Name:  "rpccorsdomain",
   292  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   293  		Value: "",
   294  	}
   295  	RPCApiFlag = cli.StringFlag{
   296  		Name:  "rpcapi",
   297  		Usage: "API's offered over the HTTP-RPC interface",
   298  		Value: rpc.DefaultHTTPApis,
   299  	}
   300  	IPCDisabledFlag = cli.BoolFlag{
   301  		Name:  "ipcdisable",
   302  		Usage: "Disable the IPC-RPC server",
   303  	}
   304  	IPCApiFlag = cli.StringFlag{
   305  		Name:  "ipcapi",
   306  		Usage: "APIs offered over the IPC-RPC interface",
   307  		Value: rpc.DefaultIPCApis,
   308  	}
   309  	IPCPathFlag = DirectoryFlag{
   310  		Name:  "ipcpath",
   311  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   312  		Value: DirectoryString{"geth.ipc"},
   313  	}
   314  	WSEnabledFlag = cli.BoolFlag{
   315  		Name:  "ws",
   316  		Usage: "Enable the WS-RPC server",
   317  	}
   318  	WSListenAddrFlag = cli.StringFlag{
   319  		Name:  "wsaddr",
   320  		Usage: "WS-RPC server listening interface",
   321  		Value: node.DefaultWSHost,
   322  	}
   323  	WSPortFlag = cli.IntFlag{
   324  		Name:  "wsport",
   325  		Usage: "WS-RPC server listening port",
   326  		Value: node.DefaultWSPort,
   327  	}
   328  	WSApiFlag = cli.StringFlag{
   329  		Name:  "wsapi",
   330  		Usage: "API's offered over the WS-RPC interface",
   331  		Value: rpc.DefaultHTTPApis,
   332  	}
   333  	WSAllowedOriginsFlag = cli.StringFlag{
   334  		Name:  "wsorigins",
   335  		Usage: "Origins from which to accept websockets requests",
   336  		Value: "",
   337  	}
   338  	ExecFlag = cli.StringFlag{
   339  		Name:  "exec",
   340  		Usage: "Execute JavaScript statement (only in combination with console/attach)",
   341  	}
   342  	PreloadJSFlag = cli.StringFlag{
   343  		Name:  "preload",
   344  		Usage: "Comma separated list of JavaScript files to preload into the console",
   345  	}
   346  
   347  	// Network Settings
   348  	MaxPeersFlag = cli.IntFlag{
   349  		Name:  "maxpeers",
   350  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   351  		Value: 25,
   352  	}
   353  	MaxPendingPeersFlag = cli.IntFlag{
   354  		Name:  "maxpendpeers",
   355  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   356  		Value: 0,
   357  	}
   358  	ListenPortFlag = cli.IntFlag{
   359  		Name:  "port",
   360  		Usage: "Network listening port",
   361  		Value: 30303,
   362  	}
   363  	BootnodesFlag = cli.StringFlag{
   364  		Name:  "bootnodes",
   365  		Usage: "Comma separated enode URLs for P2P discovery bootstrap",
   366  		Value: "",
   367  	}
   368  	NodeKeyFileFlag = cli.StringFlag{
   369  		Name:  "nodekey",
   370  		Usage: "P2P node key file",
   371  	}
   372  	NodeKeyHexFlag = cli.StringFlag{
   373  		Name:  "nodekeyhex",
   374  		Usage: "P2P node key as hex (for testing)",
   375  	}
   376  	NATFlag = cli.StringFlag{
   377  		Name:  "nat",
   378  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   379  		Value: "any",
   380  	}
   381  	NoDiscoverFlag = cli.BoolFlag{
   382  		Name:  "nodiscover",
   383  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   384  	}
   385  	DiscoveryV5Flag = cli.BoolFlag{
   386  		Name:  "v5disc",
   387  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   388  	}
   389  	NetrestrictFlag = cli.StringFlag{
   390  		Name:  "netrestrict",
   391  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   392  	}
   393  
   394  	WhisperEnabledFlag = cli.BoolFlag{
   395  		Name:  "shh",
   396  		Usage: "Enable Whisper",
   397  	}
   398  
   399  	// ATM the url is left to the user and deployment to
   400  	JSpathFlag = cli.StringFlag{
   401  		Name:  "jspath",
   402  		Usage: "JavaScript root path for `loadScript`",
   403  		Value: ".",
   404  	}
   405  	SolcPathFlag = cli.StringFlag{
   406  		Name:  "solc",
   407  		Usage: "Solidity compiler command to be used",
   408  		Value: "solc",
   409  	}
   410  
   411  	// Gas price oracle settings
   412  	GpoMinGasPriceFlag = BigFlag{
   413  		Name:  "gpomin",
   414  		Usage: "Minimum suggested gas price",
   415  		Value: big.NewInt(20 * params.Shannon),
   416  	}
   417  	GpoMaxGasPriceFlag = BigFlag{
   418  		Name:  "gpomax",
   419  		Usage: "Maximum suggested gas price",
   420  		Value: big.NewInt(500 * params.Shannon),
   421  	}
   422  	GpoFullBlockRatioFlag = cli.IntFlag{
   423  		Name:  "gpofull",
   424  		Usage: "Full block threshold for gas price calculation (%)",
   425  		Value: 80,
   426  	}
   427  	GpobaseStepDownFlag = cli.IntFlag{
   428  		Name:  "gpobasedown",
   429  		Usage: "Suggested gas price base step down ratio (1/1000)",
   430  		Value: 10,
   431  	}
   432  	GpobaseStepUpFlag = cli.IntFlag{
   433  		Name:  "gpobaseup",
   434  		Usage: "Suggested gas price base step up ratio (1/1000)",
   435  		Value: 100,
   436  	}
   437  	GpobaseCorrectionFactorFlag = cli.IntFlag{
   438  		Name:  "gpobasecf",
   439  		Usage: "Suggested gas price base correction factor (%)",
   440  		Value: 110,
   441  	}
   442  )
   443  
   444  // MakeDataDir retrieves the currently requested data directory, terminating
   445  // if none (or the empty string) is specified. If the node is starting a testnet,
   446  // the a subdirectory of the specified datadir will be used.
   447  func MakeDataDir(ctx *cli.Context) string {
   448  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   449  		// TODO: choose a different location outside of the regular datadir.
   450  		if ctx.GlobalBool(TestNetFlag.Name) {
   451  			return filepath.Join(path, "testnet")
   452  		}
   453  		return path
   454  	}
   455  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   456  	return ""
   457  }
   458  
   459  // MakeEthashCacheDir returns the directory to use for storing the ethash cache
   460  // dumps.
   461  func MakeEthashCacheDir(ctx *cli.Context) string {
   462  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) && ctx.GlobalString(EthashCacheDirFlag.Name) == "" {
   463  		return ""
   464  	}
   465  	if !ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
   466  		return "ethash"
   467  	}
   468  	return ctx.GlobalString(EthashCacheDirFlag.Name)
   469  }
   470  
   471  // MakeEthashDatasetDir returns the directory to use for storing the full ethash
   472  // dataset dumps.
   473  func MakeEthashDatasetDir(ctx *cli.Context) string {
   474  	if !ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
   475  		home := os.Getenv("HOME")
   476  		if home == "" {
   477  			if user, err := user.Current(); err == nil {
   478  				home = user.HomeDir
   479  			}
   480  		}
   481  		if runtime.GOOS == "windows" {
   482  			return filepath.Join(home, "AppData", "Ethash")
   483  		}
   484  		return filepath.Join(home, ".ethash")
   485  	}
   486  	return ctx.GlobalString(EthashDatasetDirFlag.Name)
   487  }
   488  
   489  // MakeIPCPath creates an IPC path configuration from the set command line flags,
   490  // returning an empty string if IPC was explicitly disabled, or the set path.
   491  func MakeIPCPath(ctx *cli.Context) string {
   492  	if ctx.GlobalBool(IPCDisabledFlag.Name) {
   493  		return ""
   494  	}
   495  	return ctx.GlobalString(IPCPathFlag.Name)
   496  }
   497  
   498  // MakeNodeKey creates a node key from set command line flags, either loading it
   499  // from a file or as a specified hex value. If neither flags were provided, this
   500  // method returns nil and an emphemeral key is to be generated.
   501  func MakeNodeKey(ctx *cli.Context) *ecdsa.PrivateKey {
   502  	var (
   503  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   504  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   505  
   506  		key *ecdsa.PrivateKey
   507  		err error
   508  	)
   509  	switch {
   510  	case file != "" && hex != "":
   511  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   512  
   513  	case file != "":
   514  		if key, err = crypto.LoadECDSA(file); err != nil {
   515  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   516  		}
   517  
   518  	case hex != "":
   519  		if key, err = crypto.HexToECDSA(hex); err != nil {
   520  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   521  		}
   522  	}
   523  	return key
   524  }
   525  
   526  // makeNodeUserIdent creates the user identifier from CLI flags.
   527  func makeNodeUserIdent(ctx *cli.Context) string {
   528  	var comps []string
   529  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   530  		comps = append(comps, identity)
   531  	}
   532  	if ctx.GlobalBool(VMEnableJitFlag.Name) {
   533  		comps = append(comps, "JIT")
   534  	}
   535  	return strings.Join(comps, "/")
   536  }
   537  
   538  // MakeBootstrapNodes creates a list of bootstrap nodes from the command line
   539  // flags, reverting to pre-configured ones if none have been specified.
   540  func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node {
   541  	urls := params.MainnetBootnodes
   542  	if ctx.GlobalIsSet(BootnodesFlag.Name) {
   543  		urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   544  	} else if ctx.GlobalBool(TestNetFlag.Name) {
   545  		urls = params.TestnetBootnodes
   546  	}
   547  
   548  	bootnodes := make([]*discover.Node, 0, len(urls))
   549  	for _, url := range urls {
   550  		node, err := discover.ParseNode(url)
   551  		if err != nil {
   552  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   553  			continue
   554  		}
   555  		bootnodes = append(bootnodes, node)
   556  	}
   557  	return bootnodes
   558  }
   559  
   560  // MakeBootstrapNodesV5 creates a list of bootstrap nodes from the command line
   561  // flags, reverting to pre-configured ones if none have been specified.
   562  func MakeBootstrapNodesV5(ctx *cli.Context) []*discv5.Node {
   563  	urls := params.DiscoveryV5Bootnodes
   564  	if ctx.GlobalIsSet(BootnodesFlag.Name) {
   565  		urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   566  	}
   567  
   568  	bootnodes := make([]*discv5.Node, 0, len(urls))
   569  	for _, url := range urls {
   570  		node, err := discv5.ParseNode(url)
   571  		if err != nil {
   572  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   573  			continue
   574  		}
   575  		bootnodes = append(bootnodes, node)
   576  	}
   577  	return bootnodes
   578  }
   579  
   580  // MakeListenAddress creates a TCP listening address string from set command
   581  // line flags.
   582  func MakeListenAddress(ctx *cli.Context) string {
   583  	return fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   584  }
   585  
   586  // MakeDiscoveryV5Address creates a UDP listening address string from set command
   587  // line flags for the V5 discovery protocol.
   588  func MakeDiscoveryV5Address(ctx *cli.Context) string {
   589  	return fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)+1)
   590  }
   591  
   592  // MakeNAT creates a port mapper from set command line flags.
   593  func MakeNAT(ctx *cli.Context) nat.Interface {
   594  	natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   595  	if err != nil {
   596  		Fatalf("Option %s: %v", NATFlag.Name, err)
   597  	}
   598  	return natif
   599  }
   600  
   601  // MakeRPCModules splits input separated by a comma and trims excessive white
   602  // space from the substrings.
   603  func MakeRPCModules(input string) []string {
   604  	result := strings.Split(input, ",")
   605  	for i, r := range result {
   606  		result[i] = strings.TrimSpace(r)
   607  	}
   608  	return result
   609  }
   610  
   611  // MakeHTTPRpcHost creates the HTTP RPC listener interface string from the set
   612  // command line flags, returning empty if the HTTP endpoint is disabled.
   613  func MakeHTTPRpcHost(ctx *cli.Context) string {
   614  	if !ctx.GlobalBool(RPCEnabledFlag.Name) {
   615  		return ""
   616  	}
   617  	return ctx.GlobalString(RPCListenAddrFlag.Name)
   618  }
   619  
   620  // MakeWSRpcHost creates the WebSocket RPC listener interface string from the set
   621  // command line flags, returning empty if the HTTP endpoint is disabled.
   622  func MakeWSRpcHost(ctx *cli.Context) string {
   623  	if !ctx.GlobalBool(WSEnabledFlag.Name) {
   624  		return ""
   625  	}
   626  	return ctx.GlobalString(WSListenAddrFlag.Name)
   627  }
   628  
   629  // MakeDatabaseHandles raises out the number of allowed file handles per process
   630  // for Geth and returns half of the allowance to assign to the database.
   631  func MakeDatabaseHandles() int {
   632  	if err := raiseFdLimit(2048); err != nil {
   633  		Fatalf("Failed to raise file descriptor allowance: %v", err)
   634  	}
   635  	limit, err := getFdLimit()
   636  	if err != nil {
   637  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   638  	}
   639  	if limit > 2048 { // cap database file descriptors even if more is available
   640  		limit = 2048
   641  	}
   642  	return limit / 2 // Leave half for networking and other stuff
   643  }
   644  
   645  // MakeAddress converts an account specified directly as a hex encoded string or
   646  // a key index in the key store to an internal account representation.
   647  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   648  	// If the specified account is a valid address, return it
   649  	if common.IsHexAddress(account) {
   650  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   651  	}
   652  	// Otherwise try to interpret the account as a keystore index
   653  	index, err := strconv.Atoi(account)
   654  	if err != nil || index < 0 {
   655  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   656  	}
   657  	accs := ks.Accounts()
   658  	if len(accs) <= index {
   659  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   660  	}
   661  	return accs[index], nil
   662  }
   663  
   664  // MakeEtherbase retrieves the etherbase either from the directly specified
   665  // command line flags or from the keystore if CLI indexed.
   666  func MakeEtherbase(ks *keystore.KeyStore, ctx *cli.Context) common.Address {
   667  	accounts := ks.Accounts()
   668  	if !ctx.GlobalIsSet(EtherbaseFlag.Name) && len(accounts) == 0 {
   669  		log.Warn("No etherbase set and no accounts found as default")
   670  		return common.Address{}
   671  	}
   672  	etherbase := ctx.GlobalString(EtherbaseFlag.Name)
   673  	if etherbase == "" {
   674  		return common.Address{}
   675  	}
   676  	// If the specified etherbase is a valid address, return it
   677  	account, err := MakeAddress(ks, etherbase)
   678  	if err != nil {
   679  		Fatalf("Option %q: %v", EtherbaseFlag.Name, err)
   680  	}
   681  	return account.Address
   682  }
   683  
   684  // MakeMinerExtra resolves extradata for the miner from the set command line flags
   685  // or returns a default one composed on the client, runtime and OS metadata.
   686  func MakeMinerExtra(extra []byte, ctx *cli.Context) []byte {
   687  	if ctx.GlobalIsSet(ExtraDataFlag.Name) {
   688  		return []byte(ctx.GlobalString(ExtraDataFlag.Name))
   689  	}
   690  	return extra
   691  }
   692  
   693  // MakePasswordList reads password lines from the file specified by --password.
   694  func MakePasswordList(ctx *cli.Context) []string {
   695  	path := ctx.GlobalString(PasswordFileFlag.Name)
   696  	if path == "" {
   697  		return nil
   698  	}
   699  	text, err := ioutil.ReadFile(path)
   700  	if err != nil {
   701  		Fatalf("Failed to read password file: %v", err)
   702  	}
   703  	lines := strings.Split(string(text), "\n")
   704  	// Sanitise DOS line endings.
   705  	for i := range lines {
   706  		lines[i] = strings.TrimRight(lines[i], "\r")
   707  	}
   708  	return lines
   709  }
   710  
   711  // MakeNode configures a node with no services from command line flags.
   712  func MakeNode(ctx *cli.Context, name, gitCommit string) *node.Node {
   713  	vsn := params.Version
   714  	if gitCommit != "" {
   715  		vsn += "-" + gitCommit[:8]
   716  	}
   717  
   718  	// if we're running a light client or server, force enable the v5 peer discovery unless it is explicitly disabled with --nodiscover
   719  	// note that explicitly specifying --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   720  	forceV5Discovery := (ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalInt(LightServFlag.Name) > 0) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   721  
   722  	config := &node.Config{
   723  		DataDir:           MakeDataDir(ctx),
   724  		KeyStoreDir:       ctx.GlobalString(KeyStoreDirFlag.Name),
   725  		UseLightweightKDF: ctx.GlobalBool(LightKDFFlag.Name),
   726  		PrivateKey:        MakeNodeKey(ctx),
   727  		Name:              name,
   728  		Version:           vsn,
   729  		UserIdent:         makeNodeUserIdent(ctx),
   730  		NoDiscovery:       ctx.GlobalBool(NoDiscoverFlag.Name) || ctx.GlobalBool(LightModeFlag.Name), // always disable v4 discovery in light client mode
   731  		DiscoveryV5:       ctx.GlobalBool(DiscoveryV5Flag.Name) || forceV5Discovery,
   732  		DiscoveryV5Addr:   MakeDiscoveryV5Address(ctx),
   733  		BootstrapNodes:    MakeBootstrapNodes(ctx),
   734  		BootstrapNodesV5:  MakeBootstrapNodesV5(ctx),
   735  		ListenAddr:        MakeListenAddress(ctx),
   736  		NAT:               MakeNAT(ctx),
   737  		MaxPeers:          ctx.GlobalInt(MaxPeersFlag.Name),
   738  		MaxPendingPeers:   ctx.GlobalInt(MaxPendingPeersFlag.Name),
   739  		IPCPath:           MakeIPCPath(ctx),
   740  		HTTPHost:          MakeHTTPRpcHost(ctx),
   741  		HTTPPort:          ctx.GlobalInt(RPCPortFlag.Name),
   742  		HTTPCors:          ctx.GlobalString(RPCCORSDomainFlag.Name),
   743  		HTTPModules:       MakeRPCModules(ctx.GlobalString(RPCApiFlag.Name)),
   744  		WSHost:            MakeWSRpcHost(ctx),
   745  		WSPort:            ctx.GlobalInt(WSPortFlag.Name),
   746  		WSOrigins:         ctx.GlobalString(WSAllowedOriginsFlag.Name),
   747  		WSModules:         MakeRPCModules(ctx.GlobalString(WSApiFlag.Name)),
   748  	}
   749  	if ctx.GlobalBool(DevModeFlag.Name) {
   750  		if !ctx.GlobalIsSet(DataDirFlag.Name) {
   751  			config.DataDir = filepath.Join(os.TempDir(), "/ethereum_dev_mode")
   752  		}
   753  		// --dev mode does not need p2p networking.
   754  		config.MaxPeers = 0
   755  		config.ListenAddr = ":0"
   756  	}
   757  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   758  		list, err := netutil.ParseNetlist(netrestrict)
   759  		if err != nil {
   760  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   761  		}
   762  		config.NetRestrict = list
   763  	}
   764  
   765  	stack, err := node.New(config)
   766  	if err != nil {
   767  		Fatalf("Failed to create the protocol stack: %v", err)
   768  	}
   769  	return stack
   770  }
   771  
   772  // RegisterEthService configures eth.Ethereum from command line flags and adds it to the
   773  // given node.
   774  func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
   775  	// Avoid conflicting network flags
   776  	networks, netFlags := 0, []cli.BoolFlag{DevModeFlag, TestNetFlag}
   777  	for _, flag := range netFlags {
   778  		if ctx.GlobalBool(flag.Name) {
   779  			networks++
   780  		}
   781  	}
   782  	if networks > 1 {
   783  		Fatalf("The %v flags are mutually exclusive", netFlags)
   784  	}
   785  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   786  
   787  	ethConf := &eth.Config{
   788  		Etherbase:               MakeEtherbase(ks, ctx),
   789  		FastSync:                ctx.GlobalBool(FastSyncFlag.Name),
   790  		LightMode:               ctx.GlobalBool(LightModeFlag.Name),
   791  		LightServ:               ctx.GlobalInt(LightServFlag.Name),
   792  		LightPeers:              ctx.GlobalInt(LightPeersFlag.Name),
   793  		MaxPeers:                ctx.GlobalInt(MaxPeersFlag.Name),
   794  		DatabaseCache:           ctx.GlobalInt(CacheFlag.Name),
   795  		DatabaseHandles:         MakeDatabaseHandles(),
   796  		NetworkId:               ctx.GlobalInt(NetworkIdFlag.Name),
   797  		MinerThreads:            ctx.GlobalInt(MinerThreadsFlag.Name),
   798  		ExtraData:               MakeMinerExtra(extra, ctx),
   799  		DocRoot:                 ctx.GlobalString(DocRootFlag.Name),
   800  		GasPrice:                GlobalBig(ctx, GasPriceFlag.Name),
   801  		GpoMinGasPrice:          GlobalBig(ctx, GpoMinGasPriceFlag.Name),
   802  		GpoMaxGasPrice:          GlobalBig(ctx, GpoMaxGasPriceFlag.Name),
   803  		GpoFullBlockRatio:       ctx.GlobalInt(GpoFullBlockRatioFlag.Name),
   804  		GpobaseStepDown:         ctx.GlobalInt(GpobaseStepDownFlag.Name),
   805  		GpobaseStepUp:           ctx.GlobalInt(GpobaseStepUpFlag.Name),
   806  		GpobaseCorrectionFactor: ctx.GlobalInt(GpobaseCorrectionFactorFlag.Name),
   807  		SolcPath:                ctx.GlobalString(SolcPathFlag.Name),
   808  		EthashCacheDir:          MakeEthashCacheDir(ctx),
   809  		EthashCachesInMem:       ctx.GlobalInt(EthashCachesInMemoryFlag.Name),
   810  		EthashCachesOnDisk:      ctx.GlobalInt(EthashCachesOnDiskFlag.Name),
   811  		EthashDatasetDir:        MakeEthashDatasetDir(ctx),
   812  		EthashDatasetsInMem:     ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name),
   813  		EthashDatasetsOnDisk:    ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name),
   814  		EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name),
   815  	}
   816  
   817  	// Override any default configs in dev mode or the test net
   818  	switch {
   819  	case ctx.GlobalBool(TestNetFlag.Name):
   820  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
   821  			ethConf.NetworkId = 3
   822  		}
   823  		ethConf.Genesis = core.DefaultTestnetGenesisBlock()
   824  	case ctx.GlobalBool(DevModeFlag.Name):
   825  		ethConf.Genesis = core.DevGenesisBlock()
   826  		if !ctx.GlobalIsSet(GasPriceFlag.Name) {
   827  			ethConf.GasPrice = new(big.Int)
   828  		}
   829  		ethConf.PowTest = true
   830  	}
   831  	// Override any global options pertaining to the Ethereum protocol
   832  	if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
   833  		state.MaxTrieCacheGen = uint16(gen)
   834  	}
   835  
   836  	if ethConf.LightMode {
   837  		if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
   838  			return les.New(ctx, ethConf)
   839  		}); err != nil {
   840  			Fatalf("Failed to register the Ethereum light node service: %v", err)
   841  		}
   842  	} else {
   843  		if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
   844  			fullNode, err := eth.New(ctx, ethConf)
   845  			if fullNode != nil && ethConf.LightServ > 0 {
   846  				ls, _ := les.NewLesServer(fullNode, ethConf)
   847  				fullNode.AddLesServer(ls)
   848  			}
   849  			return fullNode, err
   850  		}); err != nil {
   851  			Fatalf("Failed to register the Ethereum full node service: %v", err)
   852  		}
   853  	}
   854  }
   855  
   856  // RegisterShhService configures Whisper and adds it to the given node.
   857  func RegisterShhService(stack *node.Node) {
   858  	if err := stack.Register(func(*node.ServiceContext) (node.Service, error) { return whisper.New(), nil }); err != nil {
   859  		Fatalf("Failed to register the Whisper service: %v", err)
   860  	}
   861  }
   862  
   863  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
   864  // th egiven node.
   865  func RegisterEthStatsService(stack *node.Node, url string) {
   866  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
   867  		// Retrieve both eth and les services
   868  		var ethServ *eth.Ethereum
   869  		ctx.Service(&ethServ)
   870  
   871  		var lesServ *les.LightEthereum
   872  		ctx.Service(&lesServ)
   873  
   874  		return ethstats.New(url, ethServ, lesServ)
   875  	}); err != nil {
   876  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
   877  	}
   878  }
   879  
   880  // SetupNetwork configures the system for either the main net or some test network.
   881  func SetupNetwork(ctx *cli.Context) {
   882  	params.TargetGasLimit = new(big.Int).SetUint64(ctx.GlobalUint64(TargetGasLimitFlag.Name))
   883  }
   884  
   885  func ChainDbName(ctx *cli.Context) string {
   886  	if ctx.GlobalBool(LightModeFlag.Name) {
   887  		return "lightchaindata"
   888  	} else {
   889  		return "chaindata"
   890  	}
   891  }
   892  
   893  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
   894  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
   895  	var (
   896  		cache   = ctx.GlobalInt(CacheFlag.Name)
   897  		handles = MakeDatabaseHandles()
   898  		name    = ChainDbName(ctx)
   899  	)
   900  
   901  	chainDb, err := stack.OpenDatabase(name, cache, handles)
   902  	if err != nil {
   903  		Fatalf("Could not open database: %v", err)
   904  	}
   905  	return chainDb
   906  }
   907  
   908  func MakeGenesis(ctx *cli.Context) *core.Genesis {
   909  	var genesis *core.Genesis
   910  	switch {
   911  	case ctx.GlobalBool(TestNetFlag.Name):
   912  		genesis = core.DefaultTestnetGenesisBlock()
   913  	case ctx.GlobalBool(DevModeFlag.Name):
   914  		genesis = core.DevGenesisBlock()
   915  	}
   916  	return genesis
   917  }
   918  
   919  // MakeChain creates a chain manager from set command line flags.
   920  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
   921  	var err error
   922  	chainDb = MakeChainDatabase(ctx, stack)
   923  
   924  	seal := pow.PoW(pow.FakePow{})
   925  	if !ctx.GlobalBool(FakePoWFlag.Name) {
   926  		seal = pow.NewFullEthash("", 1, 0, "", 1, 0)
   927  	}
   928  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
   929  	if err != nil {
   930  		Fatalf("%v", err)
   931  	}
   932  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
   933  	chain, err = core.NewBlockChain(chainDb, config, seal, new(event.TypeMux), vmcfg)
   934  	if err != nil {
   935  		Fatalf("Can't create BlockChain: %v", err)
   936  	}
   937  	return chain, chainDb
   938  }
   939  
   940  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
   941  // scripts to preload before starting.
   942  func MakeConsolePreloads(ctx *cli.Context) []string {
   943  	// Skip preloading if there's nothing to preload
   944  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
   945  		return nil
   946  	}
   947  	// Otherwise resolve absolute paths and return them
   948  	preloads := []string{}
   949  
   950  	assets := ctx.GlobalString(JSpathFlag.Name)
   951  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
   952  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
   953  	}
   954  	return preloads
   955  }