github.com/mandrigin/go-ethereum@v1.7.4-0.20180116162341-02aeb3d76652/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.RinkebyV5Bootnodes
   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  // setDiscoveryV5Address creates a UDP listening address string from set command
   640  // line flags for the V5 discovery protocol.
   641  func setDiscoveryV5Address(ctx *cli.Context, cfg *p2p.Config) {
   642  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   643  		cfg.DiscoveryV5Addr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)+1)
   644  	}
   645  }
   646  
   647  // setNAT creates a port mapper from command line flags.
   648  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   649  	if ctx.GlobalIsSet(NATFlag.Name) {
   650  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   651  		if err != nil {
   652  			Fatalf("Option %s: %v", NATFlag.Name, err)
   653  		}
   654  		cfg.NAT = natif
   655  	}
   656  }
   657  
   658  // splitAndTrim splits input separated by a comma
   659  // and trims excessive white space from the substrings.
   660  func splitAndTrim(input string) []string {
   661  	result := strings.Split(input, ",")
   662  	for i, r := range result {
   663  		result[i] = strings.TrimSpace(r)
   664  	}
   665  	return result
   666  }
   667  
   668  // setHTTP creates the HTTP RPC listener interface string from the set
   669  // command line flags, returning empty if the HTTP endpoint is disabled.
   670  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   671  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   672  		cfg.HTTPHost = "127.0.0.1"
   673  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   674  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   675  		}
   676  	}
   677  
   678  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   679  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   680  	}
   681  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   682  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   683  	}
   684  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   685  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   686  	}
   687  }
   688  
   689  // setWS creates the WebSocket RPC listener interface string from the set
   690  // command line flags, returning empty if the HTTP endpoint is disabled.
   691  func setWS(ctx *cli.Context, cfg *node.Config) {
   692  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   693  		cfg.WSHost = "127.0.0.1"
   694  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   695  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   696  		}
   697  	}
   698  
   699  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   700  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   701  	}
   702  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   703  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   704  	}
   705  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   706  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   707  	}
   708  }
   709  
   710  // setIPC creates an IPC path configuration from the set command line flags,
   711  // returning an empty string if IPC was explicitly disabled, or the set path.
   712  func setIPC(ctx *cli.Context, cfg *node.Config) {
   713  	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   714  	switch {
   715  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   716  		cfg.IPCPath = ""
   717  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   718  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   719  	}
   720  }
   721  
   722  // makeDatabaseHandles raises out the number of allowed file handles per process
   723  // for Geth and returns half of the allowance to assign to the database.
   724  func makeDatabaseHandles() int {
   725  	if err := fdlimit.Raise(2048); err != nil {
   726  		Fatalf("Failed to raise file descriptor allowance: %v", err)
   727  	}
   728  	limit, err := fdlimit.Current()
   729  	if err != nil {
   730  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   731  	}
   732  	if limit > 2048 { // cap database file descriptors even if more is available
   733  		limit = 2048
   734  	}
   735  	return limit / 2 // Leave half for networking and other stuff
   736  }
   737  
   738  // MakeAddress converts an account specified directly as a hex encoded string or
   739  // a key index in the key store to an internal account representation.
   740  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   741  	// If the specified account is a valid address, return it
   742  	if common.IsHexAddress(account) {
   743  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   744  	}
   745  	// Otherwise try to interpret the account as a keystore index
   746  	index, err := strconv.Atoi(account)
   747  	if err != nil || index < 0 {
   748  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   749  	}
   750  	log.Warn("-------------------------------------------------------------------")
   751  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
   752  	log.Warn("This functionality is deprecated and will be removed in the future!")
   753  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
   754  	log.Warn("-------------------------------------------------------------------")
   755  
   756  	accs := ks.Accounts()
   757  	if len(accs) <= index {
   758  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   759  	}
   760  	return accs[index], nil
   761  }
   762  
   763  // setEtherbase retrieves the etherbase either from the directly specified
   764  // command line flags or from the keystore if CLI indexed.
   765  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) {
   766  	if ctx.GlobalIsSet(EtherbaseFlag.Name) {
   767  		account, err := MakeAddress(ks, ctx.GlobalString(EtherbaseFlag.Name))
   768  		if err != nil {
   769  			Fatalf("Option %q: %v", EtherbaseFlag.Name, err)
   770  		}
   771  		cfg.Etherbase = account.Address
   772  	}
   773  }
   774  
   775  // MakePasswordList reads password lines from the file specified by the global --password flag.
   776  func MakePasswordList(ctx *cli.Context) []string {
   777  	path := ctx.GlobalString(PasswordFileFlag.Name)
   778  	if path == "" {
   779  		return nil
   780  	}
   781  	text, err := ioutil.ReadFile(path)
   782  	if err != nil {
   783  		Fatalf("Failed to read password file: %v", err)
   784  	}
   785  	lines := strings.Split(string(text), "\n")
   786  	// Sanitise DOS line endings.
   787  	for i := range lines {
   788  		lines[i] = strings.TrimRight(lines[i], "\r")
   789  	}
   790  	return lines
   791  }
   792  
   793  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
   794  	setNodeKey(ctx, cfg)
   795  	setNAT(ctx, cfg)
   796  	setListenAddress(ctx, cfg)
   797  	setDiscoveryV5Address(ctx, cfg)
   798  	setBootstrapNodes(ctx, cfg)
   799  	setBootstrapNodesV5(ctx, cfg)
   800  
   801  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   802  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   803  	}
   804  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   805  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   806  	}
   807  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || ctx.GlobalBool(LightModeFlag.Name) {
   808  		cfg.NoDiscovery = true
   809  	}
   810  
   811  	// if we're running a light client or server, force enable the v5 peer discovery
   812  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
   813  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   814  	forceV5Discovery := (ctx.GlobalBool(LightModeFlag.Name) || ctx.GlobalInt(LightServFlag.Name) > 0) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   815  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   816  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   817  	} else if forceV5Discovery {
   818  		cfg.DiscoveryV5 = true
   819  	}
   820  
   821  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   822  		list, err := netutil.ParseNetlist(netrestrict)
   823  		if err != nil {
   824  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   825  		}
   826  		cfg.NetRestrict = list
   827  	}
   828  
   829  	if ctx.GlobalBool(DeveloperFlag.Name) {
   830  		// --dev mode can't use p2p networking.
   831  		cfg.MaxPeers = 0
   832  		cfg.ListenAddr = ":0"
   833  		cfg.DiscoveryV5Addr = ":0"
   834  		cfg.NoDiscovery = true
   835  		cfg.DiscoveryV5 = false
   836  	}
   837  }
   838  
   839  // SetNodeConfig applies node-related command line flags to the config.
   840  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
   841  	SetP2PConfig(ctx, &cfg.P2P)
   842  	setIPC(ctx, cfg)
   843  	setHTTP(ctx, cfg)
   844  	setWS(ctx, cfg)
   845  	setNodeUserIdent(ctx, cfg)
   846  
   847  	switch {
   848  	case ctx.GlobalIsSet(DataDirFlag.Name):
   849  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
   850  	case ctx.GlobalBool(DeveloperFlag.Name):
   851  		cfg.DataDir = "" // unless explicitly requested, use memory databases
   852  	case ctx.GlobalBool(TestnetFlag.Name):
   853  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet")
   854  	case ctx.GlobalBool(RinkebyFlag.Name):
   855  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
   856  	}
   857  
   858  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
   859  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
   860  	}
   861  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
   862  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
   863  	}
   864  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
   865  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
   866  	}
   867  }
   868  
   869  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
   870  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
   871  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
   872  	}
   873  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
   874  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
   875  	}
   876  }
   877  
   878  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
   879  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
   880  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
   881  	}
   882  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
   883  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
   884  	}
   885  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
   886  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
   887  	}
   888  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
   889  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
   890  	}
   891  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
   892  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
   893  	}
   894  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
   895  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
   896  	}
   897  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
   898  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
   899  	}
   900  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
   901  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
   902  	}
   903  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
   904  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
   905  	}
   906  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
   907  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
   908  	}
   909  }
   910  
   911  func setEthash(ctx *cli.Context, cfg *eth.Config) {
   912  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
   913  		cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
   914  	}
   915  	if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
   916  		cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name)
   917  	}
   918  	if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) {
   919  		cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name)
   920  	}
   921  	if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) {
   922  		cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name)
   923  	}
   924  	if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) {
   925  		cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name)
   926  	}
   927  	if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) {
   928  		cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name)
   929  	}
   930  }
   931  
   932  // checkExclusive verifies that only a single isntance of the provided flags was
   933  // set by the user. Each flag might optionally be followed by a string type to
   934  // specialize it further.
   935  func checkExclusive(ctx *cli.Context, args ...interface{}) {
   936  	set := make([]string, 0, 1)
   937  	for i := 0; i < len(args); i++ {
   938  		// Make sure the next argument is a flag and skip if not set
   939  		flag, ok := args[i].(cli.Flag)
   940  		if !ok {
   941  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
   942  		}
   943  		// Check if next arg extends current and expand its name if so
   944  		name := flag.GetName()
   945  
   946  		if i+1 < len(args) {
   947  			switch option := args[i+1].(type) {
   948  			case string:
   949  				// Extended flag, expand the name and shift the arguments
   950  				if ctx.GlobalString(flag.GetName()) == option {
   951  					name += "=" + option
   952  				}
   953  				i++
   954  
   955  			case cli.Flag:
   956  			default:
   957  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
   958  			}
   959  		}
   960  		// Mark the flag if it's set
   961  		if ctx.GlobalIsSet(flag.GetName()) {
   962  			set = append(set, "--"+name)
   963  		}
   964  	}
   965  	if len(set) > 1 {
   966  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
   967  	}
   968  }
   969  
   970  // SetShhConfig applies shh-related command line flags to the config.
   971  func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
   972  	if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) {
   973  		cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name))
   974  	}
   975  	if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) {
   976  		cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name)
   977  	}
   978  }
   979  
   980  // SetEthConfig applies eth-related command line flags to the config.
   981  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
   982  	// Avoid conflicting network flags
   983  	checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag)
   984  	checkExclusive(ctx, FastSyncFlag, LightModeFlag, SyncModeFlag)
   985  	checkExclusive(ctx, LightServFlag, LightModeFlag)
   986  	checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")
   987  
   988  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   989  	setEtherbase(ctx, ks, cfg)
   990  	setGPO(ctx, &cfg.GPO)
   991  	setTxPool(ctx, &cfg.TxPool)
   992  	setEthash(ctx, cfg)
   993  
   994  	switch {
   995  	case ctx.GlobalIsSet(SyncModeFlag.Name):
   996  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
   997  	case ctx.GlobalBool(FastSyncFlag.Name):
   998  		cfg.SyncMode = downloader.FastSync
   999  	case ctx.GlobalBool(LightModeFlag.Name):
  1000  		cfg.SyncMode = downloader.LightSync
  1001  	}
  1002  	if ctx.GlobalIsSet(LightServFlag.Name) {
  1003  		cfg.LightServ = ctx.GlobalInt(LightServFlag.Name)
  1004  	}
  1005  	if ctx.GlobalIsSet(LightPeersFlag.Name) {
  1006  		cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
  1007  	}
  1008  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1009  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1010  	}
  1011  
  1012  	if ctx.GlobalIsSet(CacheFlag.Name) {
  1013  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name)
  1014  	}
  1015  	cfg.DatabaseHandles = makeDatabaseHandles()
  1016  
  1017  	if ctx.GlobalIsSet(MinerThreadsFlag.Name) {
  1018  		cfg.MinerThreads = ctx.GlobalInt(MinerThreadsFlag.Name)
  1019  	}
  1020  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1021  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1022  	}
  1023  	if ctx.GlobalIsSet(ExtraDataFlag.Name) {
  1024  		cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name))
  1025  	}
  1026  	if ctx.GlobalIsSet(GasPriceFlag.Name) {
  1027  		cfg.GasPrice = GlobalBig(ctx, GasPriceFlag.Name)
  1028  	}
  1029  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1030  		// TODO(fjl): force-enable this in --dev mode
  1031  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1032  	}
  1033  
  1034  	// Override any default configs for hard coded networks.
  1035  	switch {
  1036  	case ctx.GlobalBool(TestnetFlag.Name):
  1037  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1038  			cfg.NetworkId = 3
  1039  		}
  1040  		cfg.Genesis = core.DefaultTestnetGenesisBlock()
  1041  	case ctx.GlobalBool(RinkebyFlag.Name):
  1042  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1043  			cfg.NetworkId = 4
  1044  		}
  1045  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1046  	case ctx.GlobalBool(DeveloperFlag.Name):
  1047  		// Create new developer account or reuse existing one
  1048  		var (
  1049  			developer accounts.Account
  1050  			err       error
  1051  		)
  1052  		if accs := ks.Accounts(); len(accs) > 0 {
  1053  			developer = ks.Accounts()[0]
  1054  		} else {
  1055  			developer, err = ks.NewAccount("")
  1056  			if err != nil {
  1057  				Fatalf("Failed to create developer account: %v", err)
  1058  			}
  1059  		}
  1060  		if err := ks.Unlock(developer, ""); err != nil {
  1061  			Fatalf("Failed to unlock developer account: %v", err)
  1062  		}
  1063  		log.Info("Using developer account", "address", developer.Address)
  1064  
  1065  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
  1066  		if !ctx.GlobalIsSet(GasPriceFlag.Name) {
  1067  			cfg.GasPrice = big.NewInt(1)
  1068  		}
  1069  	}
  1070  	// TODO(fjl): move trie cache generations into config
  1071  	if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
  1072  		state.MaxTrieCacheGen = uint16(gen)
  1073  	}
  1074  }
  1075  
  1076  // SetDashboardConfig applies dashboard related command line flags to the config.
  1077  func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
  1078  	cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name)
  1079  	cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name)
  1080  	cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
  1081  	cfg.Assets = ctx.GlobalString(DashboardAssetsFlag.Name)
  1082  }
  1083  
  1084  // RegisterEthService adds an Ethereum client to the stack.
  1085  func RegisterEthService(stack *node.Node, cfg *eth.Config) {
  1086  	var err error
  1087  	if cfg.SyncMode == downloader.LightSync {
  1088  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1089  			return les.New(ctx, cfg)
  1090  		})
  1091  	} else {
  1092  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1093  			fullNode, err := eth.New(ctx, cfg)
  1094  			if fullNode != nil && cfg.LightServ > 0 {
  1095  				ls, _ := les.NewLesServer(fullNode, cfg)
  1096  				fullNode.AddLesServer(ls)
  1097  			}
  1098  			return fullNode, err
  1099  		})
  1100  	}
  1101  	if err != nil {
  1102  		Fatalf("Failed to register the Ethereum service: %v", err)
  1103  	}
  1104  }
  1105  
  1106  // RegisterDashboardService adds a dashboard to the stack.
  1107  func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
  1108  	stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1109  		return dashboard.New(cfg, commit)
  1110  	})
  1111  }
  1112  
  1113  // RegisterShhService configures Whisper and adds it to the given node.
  1114  func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
  1115  	if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
  1116  		return whisper.New(cfg), nil
  1117  	}); err != nil {
  1118  		Fatalf("Failed to register the Whisper service: %v", err)
  1119  	}
  1120  }
  1121  
  1122  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  1123  // th egiven node.
  1124  func RegisterEthStatsService(stack *node.Node, url string) {
  1125  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1126  		// Retrieve both eth and les services
  1127  		var ethServ *eth.Ethereum
  1128  		ctx.Service(&ethServ)
  1129  
  1130  		var lesServ *les.LightEthereum
  1131  		ctx.Service(&lesServ)
  1132  
  1133  		return ethstats.New(url, ethServ, lesServ)
  1134  	}); err != nil {
  1135  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  1136  	}
  1137  }
  1138  
  1139  // SetupNetwork configures the system for either the main net or some test network.
  1140  func SetupNetwork(ctx *cli.Context) {
  1141  	// TODO(fjl): move target gas limit into config
  1142  	params.TargetGasLimit = ctx.GlobalUint64(TargetGasLimitFlag.Name)
  1143  }
  1144  
  1145  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1146  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
  1147  	var (
  1148  		cache   = ctx.GlobalInt(CacheFlag.Name)
  1149  		handles = makeDatabaseHandles()
  1150  	)
  1151  	name := "chaindata"
  1152  	if ctx.GlobalBool(LightModeFlag.Name) {
  1153  		name = "lightchaindata"
  1154  	}
  1155  	chainDb, err := stack.OpenDatabase(name, cache, handles)
  1156  	if err != nil {
  1157  		Fatalf("Could not open database: %v", err)
  1158  	}
  1159  	return chainDb
  1160  }
  1161  
  1162  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1163  	var genesis *core.Genesis
  1164  	switch {
  1165  	case ctx.GlobalBool(TestnetFlag.Name):
  1166  		genesis = core.DefaultTestnetGenesisBlock()
  1167  	case ctx.GlobalBool(RinkebyFlag.Name):
  1168  		genesis = core.DefaultRinkebyGenesisBlock()
  1169  	case ctx.GlobalBool(DeveloperFlag.Name):
  1170  		Fatalf("Developer chains are ephemeral")
  1171  	}
  1172  	return genesis
  1173  }
  1174  
  1175  // MakeChain creates a chain manager from set command line flags.
  1176  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
  1177  	var err error
  1178  	chainDb = MakeChainDatabase(ctx, stack)
  1179  
  1180  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  1181  	if err != nil {
  1182  		Fatalf("%v", err)
  1183  	}
  1184  	var engine consensus.Engine
  1185  	if config.Clique != nil {
  1186  		engine = clique.New(config.Clique, chainDb)
  1187  	} else {
  1188  		engine = ethash.NewFaker()
  1189  		if !ctx.GlobalBool(FakePoWFlag.Name) {
  1190  			engine = ethash.New(ethash.Config{
  1191  				CacheDir:       stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
  1192  				CachesInMem:    eth.DefaultConfig.Ethash.CachesInMem,
  1193  				CachesOnDisk:   eth.DefaultConfig.Ethash.CachesOnDisk,
  1194  				DatasetDir:     stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
  1195  				DatasetsInMem:  eth.DefaultConfig.Ethash.DatasetsInMem,
  1196  				DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
  1197  			})
  1198  		}
  1199  	}
  1200  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  1201  	chain, err = core.NewBlockChain(chainDb, config, engine, vmcfg)
  1202  	if err != nil {
  1203  		Fatalf("Can't create BlockChain: %v", err)
  1204  	}
  1205  	return chain, chainDb
  1206  }
  1207  
  1208  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1209  // scripts to preload before starting.
  1210  func MakeConsolePreloads(ctx *cli.Context) []string {
  1211  	// Skip preloading if there's nothing to preload
  1212  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1213  		return nil
  1214  	}
  1215  	// Otherwise resolve absolute paths and return them
  1216  	preloads := []string{}
  1217  
  1218  	assets := ctx.GlobalString(JSpathFlag.Name)
  1219  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1220  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
  1221  	}
  1222  	return preloads
  1223  }
  1224  
  1225  // MigrateFlags sets the global flag from a local flag when it's set.
  1226  // This is a temporary function used for migrating old command/flags to the
  1227  // new format.
  1228  //
  1229  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  1230  //
  1231  // is equivalent after calling this method with:
  1232  //
  1233  // geth --keystore /tmp/mykeystore --lightkdf account new
  1234  //
  1235  // This allows the use of the existing configuration functionality.
  1236  // When all flags are migrated this function can be removed and the existing
  1237  // configuration functionality must be changed that is uses local flags
  1238  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1239  	return func(ctx *cli.Context) error {
  1240  		for _, name := range ctx.FlagNames() {
  1241  			if ctx.IsSet(name) {
  1242  				ctx.GlobalSet(name, ctx.String(name))
  1243  			}
  1244  		}
  1245  		return action(ctx)
  1246  	}
  1247  }