github.com/needkane/go-ethereum@v1.7.4-0.20180131070256-c212876ea2b7/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/go-ethereum/accounts"
    32  	"github.com/ethereum/go-ethereum/accounts/keystore"
    33  	"github.com/ethereum/go-ethereum/common"
    34  	"github.com/ethereum/go-ethereum/common/fdlimit"
    35  	"github.com/ethereum/go-ethereum/consensus"
    36  	"github.com/ethereum/go-ethereum/consensus/clique"
    37  	"github.com/ethereum/go-ethereum/consensus/ethash"
    38  	"github.com/ethereum/go-ethereum/core"
    39  	"github.com/ethereum/go-ethereum/core/state"
    40  	"github.com/ethereum/go-ethereum/core/vm"
    41  	"github.com/ethereum/go-ethereum/crypto"
    42  	"github.com/ethereum/go-ethereum/dashboard"
    43  	"github.com/ethereum/go-ethereum/eth"
    44  	"github.com/ethereum/go-ethereum/eth/downloader"
    45  	"github.com/ethereum/go-ethereum/eth/gasprice"
    46  	"github.com/ethereum/go-ethereum/ethdb"
    47  	"github.com/ethereum/go-ethereum/ethstats"
    48  	"github.com/ethereum/go-ethereum/les"
    49  	"github.com/ethereum/go-ethereum/log"
    50  	"github.com/ethereum/go-ethereum/metrics"
    51  	"github.com/ethereum/go-ethereum/node"
    52  	"github.com/ethereum/go-ethereum/p2p"
    53  	"github.com/ethereum/go-ethereum/p2p/discover"
    54  	"github.com/ethereum/go-ethereum/p2p/discv5"
    55  	"github.com/ethereum/go-ethereum/p2p/nat"
    56  	"github.com/ethereum/go-ethereum/p2p/netutil"
    57  	"github.com/ethereum/go-ethereum/params"
    58  	whisper "github.com/ethereum/go-ethereum/whisper/whisperv5"
    59  	"gopkg.in/urfave/cli.v1"
    60  )
    61  
    62  var (
    63  	CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...]
    64  {{if .cmd.Description}}{{.cmd.Description}}
    65  {{end}}{{if .cmd.Subcommands}}
    66  SUBCOMMANDS:
    67  	{{range .cmd.Subcommands}}{{.cmd.Name}}{{with .cmd.ShortName}}, {{.cmd}}{{end}}{{ "\t" }}{{.cmd.Usage}}
    68  	{{end}}{{end}}{{if .categorizedFlags}}
    69  {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS:
    70  {{range $categorized.Flags}}{{"\t"}}{{.}}
    71  {{end}}
    72  {{end}}{{end}}`
    73  )
    74  
    75  func init() {
    76  	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
    77  
    78  VERSION:
    79     {{.Version}}
    80  
    81  COMMANDS:
    82     {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    83     {{end}}{{if .Flags}}
    84  GLOBAL OPTIONS:
    85     {{range .Flags}}{{.}}
    86     {{end}}{{end}}
    87  `
    88  
    89  	cli.CommandHelpTemplate = CommandHelpTemplate
    90  }
    91  
    92  // NewApp creates an app with sane defaults.
    93  func NewApp(gitCommit, usage string) *cli.App {
    94  	app := cli.NewApp()
    95  	app.Name = filepath.Base(os.Args[0])
    96  	app.Author = ""
    97  	//app.Authors = nil
    98  	app.Email = ""
    99  	app.Version = params.Version
   100  	if len(gitCommit) >= 8 {
   101  		app.Version += "-" + gitCommit[:8]
   102  	}
   103  	app.Usage = usage
   104  	return app
   105  }
   106  
   107  // These are all the command line flags we support.
   108  // If you add to this list, please remember to include the
   109  // flag in the appropriate command definition.
   110  //
   111  // The flags are defined here so their names and help texts
   112  // are the same for all commands.
   113  
   114  var (
   115  	// General settings
   116  	DataDirFlag = DirectoryFlag{
   117  		Name:  "datadir",
   118  		Usage: "Data directory for the databases and keystore",
   119  		Value: DirectoryString{node.DefaultDataDir()},
   120  	}
   121  	KeyStoreDirFlag = DirectoryFlag{
   122  		Name:  "keystore",
   123  		Usage: "Directory for the keystore (default = inside the datadir)",
   124  	}
   125  	NoUSBFlag = cli.BoolFlag{
   126  		Name:  "nousb",
   127  		Usage: "Disables monitoring for and managing USB hardware wallets",
   128  	}
   129  	NetworkIdFlag = cli.Uint64Flag{
   130  		Name:  "networkid",
   131  		Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)",
   132  		Value: eth.DefaultConfig.NetworkId,
   133  	}
   134  	TestnetFlag = cli.BoolFlag{
   135  		Name:  "testnet",
   136  		Usage: "Ropsten network: pre-configured proof-of-work test network",
   137  	}
   138  	RinkebyFlag = cli.BoolFlag{
   139  		Name:  "rinkeby",
   140  		Usage: "Rinkeby network: pre-configured proof-of-authority test network",
   141  	}
   142  	DeveloperFlag = cli.BoolFlag{
   143  		Name:  "dev",
   144  		Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
   145  	}
   146  	DeveloperPeriodFlag = cli.IntFlag{
   147  		Name:  "dev.period",
   148  		Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
   149  	}
   150  	IdentityFlag = cli.StringFlag{
   151  		Name:  "identity",
   152  		Usage: "Custom node name",
   153  	}
   154  	DocRootFlag = DirectoryFlag{
   155  		Name:  "docroot",
   156  		Usage: "Document Root for HTTPClient file scheme",
   157  		Value: DirectoryString{homeDir()},
   158  	}
   159  	FastSyncFlag = cli.BoolFlag{
   160  		Name:  "fast",
   161  		Usage: "Enable fast syncing through state downloads",
   162  	}
   163  	LightModeFlag = cli.BoolFlag{
   164  		Name:  "light",
   165  		Usage: "Enable light client mode",
   166  	}
   167  	defaultSyncMode = eth.DefaultConfig.SyncMode
   168  	SyncModeFlag    = TextMarshalerFlag{
   169  		Name:  "syncmode",
   170  		Usage: `Blockchain sync mode ("fast", "full", or "light")`,
   171  		Value: &defaultSyncMode,
   172  	}
   173  
   174  	LightServFlag = cli.IntFlag{
   175  		Name:  "lightserv",
   176  		Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
   177  		Value: 0,
   178  	}
   179  	LightPeersFlag = cli.IntFlag{
   180  		Name:  "lightpeers",
   181  		Usage: "Maximum number of LES client peers",
   182  		Value: 20,
   183  	}
   184  	LightKDFFlag = cli.BoolFlag{
   185  		Name:  "lightkdf",
   186  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   187  	}
   188  	// Dashboard settings
   189  	DashboardEnabledFlag = cli.BoolFlag{
   190  		Name:  "dashboard",
   191  		Usage: "Enable the dashboard",
   192  	}
   193  	DashboardAddrFlag = cli.StringFlag{
   194  		Name:  "dashboard.addr",
   195  		Usage: "Dashboard listening interface",
   196  		Value: dashboard.DefaultConfig.Host,
   197  	}
   198  	DashboardPortFlag = cli.IntFlag{
   199  		Name:  "dashboard.host",
   200  		Usage: "Dashboard listening port",
   201  		Value: dashboard.DefaultConfig.Port,
   202  	}
   203  	DashboardRefreshFlag = cli.DurationFlag{
   204  		Name:  "dashboard.refresh",
   205  		Usage: "Dashboard metrics collection refresh rate",
   206  		Value: dashboard.DefaultConfig.Refresh,
   207  	}
   208  	DashboardAssetsFlag = cli.StringFlag{
   209  		Name:  "dashboard.assets",
   210  		Usage: "Developer flag to serve the dashboard from the local file system",
   211  		Value: dashboard.DefaultConfig.Assets,
   212  	}
   213  	// Ethash settings
   214  	EthashCacheDirFlag = DirectoryFlag{
   215  		Name:  "ethash.cachedir",
   216  		Usage: "Directory to store the ethash verification caches (default = inside the datadir)",
   217  	}
   218  	EthashCachesInMemoryFlag = cli.IntFlag{
   219  		Name:  "ethash.cachesinmem",
   220  		Usage: "Number of recent ethash caches to keep in memory (16MB each)",
   221  		Value: eth.DefaultConfig.Ethash.CachesInMem,
   222  	}
   223  	EthashCachesOnDiskFlag = cli.IntFlag{
   224  		Name:  "ethash.cachesondisk",
   225  		Usage: "Number of recent ethash caches to keep on disk (16MB each)",
   226  		Value: eth.DefaultConfig.Ethash.CachesOnDisk,
   227  	}
   228  	EthashDatasetDirFlag = DirectoryFlag{
   229  		Name:  "ethash.dagdir",
   230  		Usage: "Directory to store the ethash mining DAGs (default = inside home folder)",
   231  		Value: DirectoryString{eth.DefaultConfig.Ethash.DatasetDir},
   232  	}
   233  	EthashDatasetsInMemoryFlag = cli.IntFlag{
   234  		Name:  "ethash.dagsinmem",
   235  		Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
   236  		Value: eth.DefaultConfig.Ethash.DatasetsInMem,
   237  	}
   238  	EthashDatasetsOnDiskFlag = cli.IntFlag{
   239  		Name:  "ethash.dagsondisk",
   240  		Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
   241  		Value: eth.DefaultConfig.Ethash.DatasetsOnDisk,
   242  	}
   243  	// Transaction pool settings
   244  	TxPoolNoLocalsFlag = cli.BoolFlag{
   245  		Name:  "txpool.nolocals",
   246  		Usage: "Disables price exemptions for locally submitted transactions",
   247  	}
   248  	TxPoolJournalFlag = cli.StringFlag{
   249  		Name:  "txpool.journal",
   250  		Usage: "Disk journal for local transaction to survive node restarts",
   251  		Value: core.DefaultTxPoolConfig.Journal,
   252  	}
   253  	TxPoolRejournalFlag = cli.DurationFlag{
   254  		Name:  "txpool.rejournal",
   255  		Usage: "Time interval to regenerate the local transaction journal",
   256  		Value: core.DefaultTxPoolConfig.Rejournal,
   257  	}
   258  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   259  		Name:  "txpool.pricelimit",
   260  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   261  		Value: eth.DefaultConfig.TxPool.PriceLimit,
   262  	}
   263  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   264  		Name:  "txpool.pricebump",
   265  		Usage: "Price bump percentage to replace an already existing transaction",
   266  		Value: eth.DefaultConfig.TxPool.PriceBump,
   267  	}
   268  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   269  		Name:  "txpool.accountslots",
   270  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   271  		Value: eth.DefaultConfig.TxPool.AccountSlots,
   272  	}
   273  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   274  		Name:  "txpool.globalslots",
   275  		Usage: "Maximum number of executable transaction slots for all accounts",
   276  		Value: eth.DefaultConfig.TxPool.GlobalSlots,
   277  	}
   278  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   279  		Name:  "txpool.accountqueue",
   280  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   281  		Value: eth.DefaultConfig.TxPool.AccountQueue,
   282  	}
   283  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   284  		Name:  "txpool.globalqueue",
   285  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   286  		Value: eth.DefaultConfig.TxPool.GlobalQueue,
   287  	}
   288  	TxPoolLifetimeFlag = cli.DurationFlag{
   289  		Name:  "txpool.lifetime",
   290  		Usage: "Maximum amount of time non-executable transaction are queued",
   291  		Value: eth.DefaultConfig.TxPool.Lifetime,
   292  	}
   293  	// Performance tuning settings
   294  	CacheFlag = cli.IntFlag{
   295  		Name:  "cache",
   296  		Usage: "Megabytes of memory allocated to internal caching (min 16MB / database forced)",
   297  		Value: 128,
   298  	}
   299  	TrieCacheGenFlag = cli.IntFlag{
   300  		Name:  "trie-cache-gens",
   301  		Usage: "Number of trie node generations to keep in memory",
   302  		Value: int(state.MaxTrieCacheGen),
   303  	}
   304  	// Miner settings
   305  	MiningEnabledFlag = cli.BoolFlag{
   306  		Name:  "mine",
   307  		Usage: "Enable mining",
   308  	}
   309  	MinerThreadsFlag = cli.IntFlag{
   310  		Name:  "minerthreads",
   311  		Usage: "Number of CPU threads to use for mining",
   312  		Value: runtime.NumCPU(),
   313  	}
   314  	TargetGasLimitFlag = cli.Uint64Flag{
   315  		Name:  "targetgaslimit",
   316  		Usage: "Target gas limit sets the artificial target gas floor for the blocks to mine",
   317  		Value: params.GenesisGasLimit,
   318  	}
   319  	EtherbaseFlag = cli.StringFlag{
   320  		Name:  "etherbase",
   321  		Usage: "Public address for block mining rewards (default = first account created)",
   322  		Value: "0",
   323  	}
   324  	GasPriceFlag = BigFlag{
   325  		Name:  "gasprice",
   326  		Usage: "Minimal gas price to accept for mining a transactions",
   327  		Value: eth.DefaultConfig.GasPrice,
   328  	}
   329  	ExtraDataFlag = cli.StringFlag{
   330  		Name:  "extradata",
   331  		Usage: "Block extra data set by the miner (default = client version)",
   332  	}
   333  	// Account settings
   334  	UnlockedAccountFlag = cli.StringFlag{
   335  		Name:  "unlock",
   336  		Usage: "Comma separated list of accounts to unlock",
   337  		Value: "",
   338  	}
   339  	PasswordFileFlag = cli.StringFlag{
   340  		Name:  "password",
   341  		Usage: "Password file to use for non-interactive password input",
   342  		Value: "",
   343  	}
   344  
   345  	VMEnableDebugFlag = cli.BoolFlag{
   346  		Name:  "vmdebug",
   347  		Usage: "Record information useful for VM and contract debugging",
   348  	}
   349  	// Logging and debug settings
   350  	EthStatsURLFlag = cli.StringFlag{
   351  		Name:  "ethstats",
   352  		Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
   353  	}
   354  	MetricsEnabledFlag = cli.BoolFlag{
   355  		Name:  metrics.MetricsEnabledFlag,
   356  		Usage: "Enable metrics collection and reporting",
   357  	}
   358  	FakePoWFlag = cli.BoolFlag{
   359  		Name:  "fakepow",
   360  		Usage: "Disables proof-of-work verification",
   361  	}
   362  	NoCompactionFlag = cli.BoolFlag{
   363  		Name:  "nocompaction",
   364  		Usage: "Disables db compaction after import",
   365  	}
   366  	// RPC settings
   367  	RPCEnabledFlag = cli.BoolFlag{
   368  		Name:  "rpc",
   369  		Usage: "Enable the HTTP-RPC server",
   370  	}
   371  	RPCListenAddrFlag = cli.StringFlag{
   372  		Name:  "rpcaddr",
   373  		Usage: "HTTP-RPC server listening interface",
   374  		Value: node.DefaultHTTPHost,
   375  	}
   376  	RPCPortFlag = cli.IntFlag{
   377  		Name:  "rpcport",
   378  		Usage: "HTTP-RPC server listening port",
   379  		Value: node.DefaultHTTPPort,
   380  	}
   381  	RPCCORSDomainFlag = cli.StringFlag{
   382  		Name:  "rpccorsdomain",
   383  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   384  		Value: "",
   385  	}
   386  	RPCApiFlag = cli.StringFlag{
   387  		Name:  "rpcapi",
   388  		Usage: "API's offered over the HTTP-RPC interface",
   389  		Value: "",
   390  	}
   391  	IPCDisabledFlag = cli.BoolFlag{
   392  		Name:  "ipcdisable",
   393  		Usage: "Disable the IPC-RPC server",
   394  	}
   395  	IPCPathFlag = DirectoryFlag{
   396  		Name:  "ipcpath",
   397  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   398  	}
   399  	WSEnabledFlag = cli.BoolFlag{
   400  		Name:  "ws",
   401  		Usage: "Enable the WS-RPC server",
   402  	}
   403  	WSListenAddrFlag = cli.StringFlag{
   404  		Name:  "wsaddr",
   405  		Usage: "WS-RPC server listening interface",
   406  		Value: node.DefaultWSHost,
   407  	}
   408  	WSPortFlag = cli.IntFlag{
   409  		Name:  "wsport",
   410  		Usage: "WS-RPC server listening port",
   411  		Value: node.DefaultWSPort,
   412  	}
   413  	WSApiFlag = cli.StringFlag{
   414  		Name:  "wsapi",
   415  		Usage: "API's offered over the WS-RPC interface",
   416  		Value: "",
   417  	}
   418  	WSAllowedOriginsFlag = cli.StringFlag{
   419  		Name:  "wsorigins",
   420  		Usage: "Origins from which to accept websockets requests",
   421  		Value: "",
   422  	}
   423  	ExecFlag = cli.StringFlag{
   424  		Name:  "exec",
   425  		Usage: "Execute JavaScript statement",
   426  	}
   427  	PreloadJSFlag = cli.StringFlag{
   428  		Name:  "preload",
   429  		Usage: "Comma separated list of JavaScript files to preload into the console",
   430  	}
   431  
   432  	// Network Settings
   433  	MaxPeersFlag = cli.IntFlag{
   434  		Name:  "maxpeers",
   435  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   436  		Value: 25,
   437  	}
   438  	MaxPendingPeersFlag = cli.IntFlag{
   439  		Name:  "maxpendpeers",
   440  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   441  		Value: 0,
   442  	}
   443  	ListenPortFlag = cli.IntFlag{
   444  		Name:  "port",
   445  		Usage: "Network listening port",
   446  		Value: 30303,
   447  	}
   448  	BootnodesFlag = cli.StringFlag{
   449  		Name:  "bootnodes",
   450  		Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)",
   451  		Value: "",
   452  	}
   453  	BootnodesV4Flag = cli.StringFlag{
   454  		Name:  "bootnodesv4",
   455  		Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)",
   456  		Value: "",
   457  	}
   458  	BootnodesV5Flag = cli.StringFlag{
   459  		Name:  "bootnodesv5",
   460  		Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)",
   461  		Value: "",
   462  	}
   463  	NodeKeyFileFlag = cli.StringFlag{
   464  		Name:  "nodekey",
   465  		Usage: "P2P node key file",
   466  	}
   467  	NodeKeyHexFlag = cli.StringFlag{
   468  		Name:  "nodekeyhex",
   469  		Usage: "P2P node key as hex (for testing)",
   470  	}
   471  	NATFlag = cli.StringFlag{
   472  		Name:  "nat",
   473  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   474  		Value: "any",
   475  	}
   476  	NoDiscoverFlag = cli.BoolFlag{
   477  		Name:  "nodiscover",
   478  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   479  	}
   480  	DiscoveryV5Flag = cli.BoolFlag{
   481  		Name:  "v5disc",
   482  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   483  	}
   484  	NetrestrictFlag = cli.StringFlag{
   485  		Name:  "netrestrict",
   486  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   487  	}
   488  
   489  	// ATM the url is left to the user and deployment to
   490  	JSpathFlag = cli.StringFlag{
   491  		Name:  "jspath",
   492  		Usage: "JavaScript root path for `loadScript`",
   493  		Value: ".",
   494  	}
   495  
   496  	// Gas price oracle settings
   497  	GpoBlocksFlag = cli.IntFlag{
   498  		Name:  "gpoblocks",
   499  		Usage: "Number of recent blocks to check for gas prices",
   500  		Value: eth.DefaultConfig.GPO.Blocks,
   501  	}
   502  	GpoPercentileFlag = cli.IntFlag{
   503  		Name:  "gpopercentile",
   504  		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   505  		Value: eth.DefaultConfig.GPO.Percentile,
   506  	}
   507  	WhisperEnabledFlag = cli.BoolFlag{
   508  		Name:  "shh",
   509  		Usage: "Enable Whisper",
   510  	}
   511  	WhisperMaxMessageSizeFlag = cli.IntFlag{
   512  		Name:  "shh.maxmessagesize",
   513  		Usage: "Max message size accepted",
   514  		Value: int(whisper.DefaultMaxMessageSize),
   515  	}
   516  	WhisperMinPOWFlag = cli.Float64Flag{
   517  		Name:  "shh.pow",
   518  		Usage: "Minimum POW accepted",
   519  		Value: whisper.DefaultMinimumPoW,
   520  	}
   521  )
   522  
   523  // MakeDataDir retrieves the currently requested data directory, terminating
   524  // if none (or the empty string) is specified. If the node is starting a testnet,
   525  // the a subdirectory of the specified datadir will be used.
   526  func MakeDataDir(ctx *cli.Context) string {
   527  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   528  		if ctx.GlobalBool(TestnetFlag.Name) {
   529  			return filepath.Join(path, "testnet")
   530  		}
   531  		if ctx.GlobalBool(RinkebyFlag.Name) {
   532  			return filepath.Join(path, "rinkeby")
   533  		}
   534  		return path
   535  	}
   536  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   537  	return ""
   538  }
   539  
   540  // setNodeKey creates a node key from set command line flags, either loading it
   541  // from a file or as a specified hex value. If neither flags were provided, this
   542  // method returns nil and an emphemeral key is to be generated.
   543  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   544  	var (
   545  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   546  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   547  		key  *ecdsa.PrivateKey
   548  		err  error
   549  	)
   550  	switch {
   551  	case file != "" && hex != "":
   552  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   553  	case file != "":
   554  		if key, err = crypto.LoadECDSA(file); err != nil {
   555  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   556  		}
   557  		cfg.PrivateKey = key
   558  	case hex != "":
   559  		if key, err = crypto.HexToECDSA(hex); err != nil {
   560  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   561  		}
   562  		cfg.PrivateKey = key
   563  	}
   564  }
   565  
   566  // setNodeUserIdent creates the user identifier from CLI flags.
   567  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   568  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   569  		cfg.UserIdent = identity
   570  	}
   571  }
   572  
   573  // setBootstrapNodes creates a list of bootstrap nodes from the command line
   574  // flags, reverting to pre-configured ones if none have been specified.
   575  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   576  	urls := params.MainnetBootnodes
   577  	switch {
   578  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name):
   579  		if ctx.GlobalIsSet(BootnodesV4Flag.Name) {
   580  			urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",")
   581  		} else {
   582  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   583  		}
   584  	case ctx.GlobalBool(TestnetFlag.Name):
   585  		urls = params.TestnetBootnodes
   586  	case ctx.GlobalBool(RinkebyFlag.Name):
   587  		urls = params.RinkebyBootnodes
   588  	case cfg.BootstrapNodes != nil:
   589  		return // already set, don't apply defaults.
   590  	}
   591  
   592  	cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls))
   593  	for _, url := range urls {
   594  		node, err := discover.ParseNode(url)
   595  		if err != nil {
   596  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   597  			continue
   598  		}
   599  		cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   600  	}
   601  }
   602  
   603  // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
   604  // flags, reverting to pre-configured ones if none have been specified.
   605  func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
   606  	urls := params.DiscoveryV5Bootnodes
   607  	switch {
   608  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name):
   609  		if ctx.GlobalIsSet(BootnodesV5Flag.Name) {
   610  			urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",")
   611  		} else {
   612  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   613  		}
   614  	case ctx.GlobalBool(RinkebyFlag.Name):
   615  		urls = params.RinkebyBootnodes
   616  	case cfg.BootstrapNodesV5 != nil:
   617  		return // already set, don't apply defaults.
   618  	}
   619  
   620  	cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls))
   621  	for _, url := range urls {
   622  		node, err := discv5.ParseNode(url)
   623  		if err != nil {
   624  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   625  			continue
   626  		}
   627  		cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
   628  	}
   629  }
   630  
   631  // setListenAddress creates a TCP listening address string from set command
   632  // line flags.
   633  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   634  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   635  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   636  	}
   637  }
   638  
   639  // setNAT creates a port mapper from command line flags.
   640  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   641  	if ctx.GlobalIsSet(NATFlag.Name) {
   642  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   643  		if err != nil {
   644  			Fatalf("Option %s: %v", NATFlag.Name, err)
   645  		}
   646  		cfg.NAT = natif
   647  	}
   648  }
   649  
   650  // splitAndTrim splits input separated by a comma
   651  // and trims excessive white space from the substrings.
   652  func splitAndTrim(input string) []string {
   653  	result := strings.Split(input, ",")
   654  	for i, r := range result {
   655  		result[i] = strings.TrimSpace(r)
   656  	}
   657  	return result
   658  }
   659  
   660  // setHTTP creates the HTTP RPC listener interface string from the set
   661  // command line flags, returning empty if the HTTP endpoint is disabled.
   662  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   663  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   664  		cfg.HTTPHost = "127.0.0.1"
   665  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   666  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   667  		}
   668  	}
   669  
   670  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   671  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   672  	}
   673  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   674  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   675  	}
   676  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   677  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   678  	}
   679  }
   680  
   681  // setWS creates the WebSocket RPC listener interface string from the set
   682  // command line flags, returning empty if the HTTP endpoint is disabled.
   683  func setWS(ctx *cli.Context, cfg *node.Config) {
   684  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   685  		cfg.WSHost = "127.0.0.1"
   686  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   687  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   688  		}
   689  	}
   690  
   691  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   692  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   693  	}
   694  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   695  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   696  	}
   697  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   698  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   699  	}
   700  }
   701  
   702  // setIPC creates an IPC path configuration from the set command line flags,
   703  // returning an empty string if IPC was explicitly disabled, or the set path.
   704  func setIPC(ctx *cli.Context, cfg *node.Config) {
   705  	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   706  	switch {
   707  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   708  		cfg.IPCPath = ""
   709  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   710  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   711  	}
   712  }
   713  
   714  // makeDatabaseHandles raises out the number of allowed file handles per process
   715  // for Geth and returns half of the allowance to assign to the database.
   716  func makeDatabaseHandles() int {
   717  	if err := fdlimit.Raise(2048); err != nil {
   718  		Fatalf("Failed to raise file descriptor allowance: %v", err)
   719  	}
   720  	limit, err := fdlimit.Current()
   721  	if err != nil {
   722  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   723  	}
   724  	if limit > 2048 { // cap database file descriptors even if more is available
   725  		limit = 2048
   726  	}
   727  	return limit / 2 // Leave half for networking and other stuff
   728  }
   729  
   730  // MakeAddress converts an account specified directly as a hex encoded string or
   731  // a key index in the key store to an internal account representation.
   732  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   733  	// If the specified account is a valid address, return it
   734  	if common.IsHexAddress(account) {
   735  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   736  	}
   737  	// Otherwise try to interpret the account as a keystore index
   738  	index, err := strconv.Atoi(account)
   739  	if err != nil || index < 0 {
   740  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   741  	}
   742  	log.Warn("-------------------------------------------------------------------")
   743  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
   744  	log.Warn("This functionality is deprecated and will be removed in the future!")
   745  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
   746  	log.Warn("-------------------------------------------------------------------")
   747  
   748  	accs := ks.Accounts()
   749  	if len(accs) <= index {
   750  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   751  	}
   752  	return accs[index], nil
   753  }
   754  
   755  // setEtherbase retrieves the etherbase either from the directly specified
   756  // command line flags or from the keystore if CLI indexed.
   757  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) {
   758  	if ctx.GlobalIsSet(EtherbaseFlag.Name) {
   759  		account, err := MakeAddress(ks, ctx.GlobalString(EtherbaseFlag.Name))
   760  		if err != nil {
   761  			Fatalf("Option %q: %v", EtherbaseFlag.Name, err)
   762  		}
   763  		cfg.Etherbase = account.Address
   764  	}
   765  }
   766  
   767  // MakePasswordList reads password lines from the file specified by the global --password flag.
   768  func MakePasswordList(ctx *cli.Context) []string {
   769  	path := ctx.GlobalString(PasswordFileFlag.Name)
   770  	if path == "" {
   771  		return nil
   772  	}
   773  	text, err := ioutil.ReadFile(path)
   774  	if err != nil {
   775  		Fatalf("Failed to read password file: %v", err)
   776  	}
   777  	lines := strings.Split(string(text), "\n")
   778  	// Sanitise DOS line endings.
   779  	for i := range lines {
   780  		lines[i] = strings.TrimRight(lines[i], "\r")
   781  	}
   782  	return lines
   783  }
   784  
   785  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
   786  	setNodeKey(ctx, cfg)
   787  	setNAT(ctx, cfg)
   788  	setListenAddress(ctx, cfg)
   789  	setBootstrapNodes(ctx, cfg)
   790  	setBootstrapNodesV5(ctx, cfg)
   791  
   792  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   793  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   794  	}
   795  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   796  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   797  	}
   798  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || ctx.GlobalBool(LightModeFlag.Name) {
   799  		cfg.NoDiscovery = true
   800  	}
   801  
   802  	// if we're running a light client or server, force enable the v5 peer discovery
   803  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
   804  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   805  	forceV5Discovery := (ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalInt(LightServFlag.Name) > 0) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   806  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   807  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   808  	} else if forceV5Discovery {
   809  		cfg.DiscoveryV5 = true
   810  	}
   811  
   812  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   813  		list, err := netutil.ParseNetlist(netrestrict)
   814  		if err != nil {
   815  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   816  		}
   817  		cfg.NetRestrict = list
   818  	}
   819  
   820  	if ctx.GlobalBool(DeveloperFlag.Name) {
   821  		// --dev mode can't use p2p networking.
   822  		cfg.MaxPeers = 0
   823  		cfg.ListenAddr = ":0"
   824  		cfg.NoDiscovery = true
   825  		cfg.DiscoveryV5 = false
   826  	}
   827  }
   828  
   829  // SetNodeConfig applies node-related command line flags to the config.
   830  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
   831  	SetP2PConfig(ctx, &cfg.P2P)
   832  	setIPC(ctx, cfg)
   833  	setHTTP(ctx, cfg)
   834  	setWS(ctx, cfg)
   835  	setNodeUserIdent(ctx, cfg)
   836  
   837  	switch {
   838  	case ctx.GlobalIsSet(DataDirFlag.Name):
   839  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
   840  	case ctx.GlobalBool(DeveloperFlag.Name):
   841  		cfg.DataDir = "" // unless explicitly requested, use memory databases
   842  	case ctx.GlobalBool(TestnetFlag.Name):
   843  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet")
   844  	case ctx.GlobalBool(RinkebyFlag.Name):
   845  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
   846  	}
   847  
   848  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
   849  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
   850  	}
   851  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
   852  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
   853  	}
   854  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
   855  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
   856  	}
   857  }
   858  
   859  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
   860  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
   861  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
   862  	}
   863  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
   864  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
   865  	}
   866  }
   867  
   868  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
   869  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
   870  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
   871  	}
   872  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
   873  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
   874  	}
   875  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
   876  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
   877  	}
   878  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
   879  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
   880  	}
   881  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
   882  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
   883  	}
   884  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
   885  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
   886  	}
   887  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
   888  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
   889  	}
   890  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
   891  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
   892  	}
   893  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
   894  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
   895  	}
   896  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
   897  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
   898  	}
   899  }
   900  
   901  func setEthash(ctx *cli.Context, cfg *eth.Config) {
   902  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
   903  		cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
   904  	}
   905  	if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
   906  		cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name)
   907  	}
   908  	if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) {
   909  		cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name)
   910  	}
   911  	if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) {
   912  		cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name)
   913  	}
   914  	if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) {
   915  		cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name)
   916  	}
   917  	if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) {
   918  		cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name)
   919  	}
   920  }
   921  
   922  // checkExclusive verifies that only a single isntance of the provided flags was
   923  // set by the user. Each flag might optionally be followed by a string type to
   924  // specialize it further.
   925  func checkExclusive(ctx *cli.Context, args ...interface{}) {
   926  	set := make([]string, 0, 1)
   927  	for i := 0; i < len(args); i++ {
   928  		// Make sure the next argument is a flag and skip if not set
   929  		flag, ok := args[i].(cli.Flag)
   930  		if !ok {
   931  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
   932  		}
   933  		// Check if next arg extends current and expand its name if so
   934  		name := flag.GetName()
   935  
   936  		if i+1 < len(args) {
   937  			switch option := args[i+1].(type) {
   938  			case string:
   939  				// Extended flag, expand the name and shift the arguments
   940  				if ctx.GlobalString(flag.GetName()) == option {
   941  					name += "=" + option
   942  				}
   943  				i++
   944  
   945  			case cli.Flag:
   946  			default:
   947  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
   948  			}
   949  		}
   950  		// Mark the flag if it's set
   951  		if ctx.GlobalIsSet(flag.GetName()) {
   952  			set = append(set, "--"+name)
   953  		}
   954  	}
   955  	if len(set) > 1 {
   956  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
   957  	}
   958  }
   959  
   960  // SetShhConfig applies shh-related command line flags to the config.
   961  func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
   962  	if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) {
   963  		cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name))
   964  	}
   965  	if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) {
   966  		cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name)
   967  	}
   968  }
   969  
   970  // SetEthConfig applies eth-related command line flags to the config.
   971  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
   972  	// Avoid conflicting network flags
   973  	checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag)
   974  	checkExclusive(ctx, FastSyncFlag, LightModeFlag, SyncModeFlag)
   975  	checkExclusive(ctx, LightServFlag, LightModeFlag)
   976  	checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")
   977  
   978  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   979  	setEtherbase(ctx, ks, cfg)
   980  	setGPO(ctx, &cfg.GPO)
   981  	setTxPool(ctx, &cfg.TxPool)
   982  	setEthash(ctx, cfg)
   983  
   984  	switch {
   985  	case ctx.GlobalIsSet(SyncModeFlag.Name):
   986  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
   987  	case ctx.GlobalBool(FastSyncFlag.Name):
   988  		cfg.SyncMode = downloader.FastSync
   989  	case ctx.GlobalBool(LightModeFlag.Name):
   990  		cfg.SyncMode = downloader.LightSync
   991  	}
   992  	if ctx.GlobalIsSet(LightServFlag.Name) {
   993  		cfg.LightServ = ctx.GlobalInt(LightServFlag.Name)
   994  	}
   995  	if ctx.GlobalIsSet(LightPeersFlag.Name) {
   996  		cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
   997  	}
   998  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
   999  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1000  	}
  1001  
  1002  	if ctx.GlobalIsSet(CacheFlag.Name) {
  1003  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name)
  1004  	}
  1005  	cfg.DatabaseHandles = makeDatabaseHandles()
  1006  
  1007  	if ctx.GlobalIsSet(MinerThreadsFlag.Name) {
  1008  		cfg.MinerThreads = ctx.GlobalInt(MinerThreadsFlag.Name)
  1009  	}
  1010  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1011  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1012  	}
  1013  	if ctx.GlobalIsSet(ExtraDataFlag.Name) {
  1014  		cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name))
  1015  	}
  1016  	if ctx.GlobalIsSet(GasPriceFlag.Name) {
  1017  		cfg.GasPrice = GlobalBig(ctx, GasPriceFlag.Name)
  1018  	}
  1019  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1020  		// TODO(fjl): force-enable this in --dev mode
  1021  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1022  	}
  1023  
  1024  	// Override any default configs for hard coded networks.
  1025  	switch {
  1026  	case ctx.GlobalBool(TestnetFlag.Name):
  1027  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1028  			cfg.NetworkId = 3
  1029  		}
  1030  		cfg.Genesis = core.DefaultTestnetGenesisBlock()
  1031  	case ctx.GlobalBool(RinkebyFlag.Name):
  1032  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1033  			cfg.NetworkId = 4
  1034  		}
  1035  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1036  	case ctx.GlobalBool(DeveloperFlag.Name):
  1037  		// Create new developer account or reuse existing one
  1038  		var (
  1039  			developer accounts.Account
  1040  			err       error
  1041  		)
  1042  		if accs := ks.Accounts(); len(accs) > 0 {
  1043  			developer = ks.Accounts()[0]
  1044  		} else {
  1045  			developer, err = ks.NewAccount("")
  1046  			if err != nil {
  1047  				Fatalf("Failed to create developer account: %v", err)
  1048  			}
  1049  		}
  1050  		if err := ks.Unlock(developer, ""); err != nil {
  1051  			Fatalf("Failed to unlock developer account: %v", err)
  1052  		}
  1053  		log.Info("Using developer account", "address", developer.Address)
  1054  
  1055  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
  1056  		if !ctx.GlobalIsSet(GasPriceFlag.Name) {
  1057  			cfg.GasPrice = big.NewInt(1)
  1058  		}
  1059  	}
  1060  	// TODO(fjl): move trie cache generations into config
  1061  	if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
  1062  		state.MaxTrieCacheGen = uint16(gen)
  1063  	}
  1064  }
  1065  
  1066  // SetDashboardConfig applies dashboard related command line flags to the config.
  1067  func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
  1068  	cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name)
  1069  	cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name)
  1070  	cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
  1071  	cfg.Assets = ctx.GlobalString(DashboardAssetsFlag.Name)
  1072  }
  1073  
  1074  // RegisterEthService adds an Ethereum client to the stack.
  1075  func RegisterEthService(stack *node.Node, cfg *eth.Config) {
  1076  	var err error
  1077  	if cfg.SyncMode == downloader.LightSync {
  1078  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1079  			return les.New(ctx, cfg)
  1080  		})
  1081  	} else {
  1082  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1083  			fullNode, err := eth.New(ctx, cfg)
  1084  			if fullNode != nil && cfg.LightServ > 0 {
  1085  				ls, _ := les.NewLesServer(fullNode, cfg)
  1086  				fullNode.AddLesServer(ls)
  1087  			}
  1088  			return fullNode, err
  1089  		})
  1090  	}
  1091  	if err != nil {
  1092  		Fatalf("Failed to register the Ethereum service: %v", err)
  1093  	}
  1094  }
  1095  
  1096  // RegisterDashboardService adds a dashboard to the stack.
  1097  func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
  1098  	stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1099  		return dashboard.New(cfg, commit)
  1100  	})
  1101  }
  1102  
  1103  // RegisterShhService configures Whisper and adds it to the given node.
  1104  func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
  1105  	if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
  1106  		return whisper.New(cfg), nil
  1107  	}); err != nil {
  1108  		Fatalf("Failed to register the Whisper service: %v", err)
  1109  	}
  1110  }
  1111  
  1112  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  1113  // th egiven node.
  1114  func RegisterEthStatsService(stack *node.Node, url string) {
  1115  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1116  		// Retrieve both eth and les services
  1117  		var ethServ *eth.Ethereum
  1118  		ctx.Service(&ethServ)
  1119  
  1120  		var lesServ *les.LightEthereum
  1121  		ctx.Service(&lesServ)
  1122  
  1123  		return ethstats.New(url, ethServ, lesServ)
  1124  	}); err != nil {
  1125  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  1126  	}
  1127  }
  1128  
  1129  // SetupNetwork configures the system for either the main net or some test network.
  1130  func SetupNetwork(ctx *cli.Context) {
  1131  	// TODO(fjl): move target gas limit into config
  1132  	params.TargetGasLimit = ctx.GlobalUint64(TargetGasLimitFlag.Name)
  1133  }
  1134  
  1135  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1136  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
  1137  	var (
  1138  		cache   = ctx.GlobalInt(CacheFlag.Name)
  1139  		handles = makeDatabaseHandles()
  1140  	)
  1141  	name := "chaindata"
  1142  	if ctx.GlobalBool(LightModeFlag.Name) {
  1143  		name = "lightchaindata"
  1144  	}
  1145  	chainDb, err := stack.OpenDatabase(name, cache, handles)
  1146  	if err != nil {
  1147  		Fatalf("Could not open database: %v", err)
  1148  	}
  1149  	return chainDb
  1150  }
  1151  
  1152  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1153  	var genesis *core.Genesis
  1154  	switch {
  1155  	case ctx.GlobalBool(TestnetFlag.Name):
  1156  		genesis = core.DefaultTestnetGenesisBlock()
  1157  	case ctx.GlobalBool(RinkebyFlag.Name):
  1158  		genesis = core.DefaultRinkebyGenesisBlock()
  1159  	case ctx.GlobalBool(DeveloperFlag.Name):
  1160  		Fatalf("Developer chains are ephemeral")
  1161  	}
  1162  	return genesis
  1163  }
  1164  
  1165  // MakeChain creates a chain manager from set command line flags.
  1166  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
  1167  	var err error
  1168  	chainDb = MakeChainDatabase(ctx, stack)
  1169  
  1170  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  1171  	if err != nil {
  1172  		Fatalf("%v", err)
  1173  	}
  1174  	var engine consensus.Engine
  1175  	if config.Clique != nil {
  1176  		engine = clique.New(config.Clique, chainDb)
  1177  	} else {
  1178  		engine = ethash.NewFaker()
  1179  		if !ctx.GlobalBool(FakePoWFlag.Name) {
  1180  			engine = ethash.New(ethash.Config{
  1181  				CacheDir:       stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
  1182  				CachesInMem:    eth.DefaultConfig.Ethash.CachesInMem,
  1183  				CachesOnDisk:   eth.DefaultConfig.Ethash.CachesOnDisk,
  1184  				DatasetDir:     stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
  1185  				DatasetsInMem:  eth.DefaultConfig.Ethash.DatasetsInMem,
  1186  				DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
  1187  			})
  1188  		}
  1189  	}
  1190  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  1191  	chain, err = core.NewBlockChain(chainDb, config, engine, vmcfg)
  1192  	if err != nil {
  1193  		Fatalf("Can't create BlockChain: %v", err)
  1194  	}
  1195  	return chain, chainDb
  1196  }
  1197  
  1198  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1199  // scripts to preload before starting.
  1200  func MakeConsolePreloads(ctx *cli.Context) []string {
  1201  	// Skip preloading if there's nothing to preload
  1202  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1203  		return nil
  1204  	}
  1205  	// Otherwise resolve absolute paths and return them
  1206  	preloads := []string{}
  1207  
  1208  	assets := ctx.GlobalString(JSpathFlag.Name)
  1209  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1210  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
  1211  	}
  1212  	return preloads
  1213  }
  1214  
  1215  // MigrateFlags sets the global flag from a local flag when it's set.
  1216  // This is a temporary function used for migrating old command/flags to the
  1217  // new format.
  1218  //
  1219  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  1220  //
  1221  // is equivalent after calling this method with:
  1222  //
  1223  // geth --keystore /tmp/mykeystore --lightkdf account new
  1224  //
  1225  // This allows the use of the existing configuration functionality.
  1226  // When all flags are migrated this function can be removed and the existing
  1227  // configuration functionality must be changed that is uses local flags
  1228  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1229  	return func(ctx *cli.Context) error {
  1230  		for _, name := range ctx.FlagNames() {
  1231  			if ctx.IsSet(name) {
  1232  				ctx.GlobalSet(name, ctx.String(name))
  1233  			}
  1234  		}
  1235  		return action(ctx)
  1236  	}
  1237  }