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