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