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