github.com/tyler-smith/go-ethereum@v1.9.7/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  	"errors"
    23  	"fmt"
    24  	"io"
    25  	"io/ioutil"
    26  	"math/big"
    27  	"os"
    28  	"path/filepath"
    29  	"strconv"
    30  	"strings"
    31  	"text/tabwriter"
    32  	"text/template"
    33  	"time"
    34  
    35  	"github.com/ethereum/go-ethereum/accounts"
    36  	"github.com/ethereum/go-ethereum/accounts/keystore"
    37  	"github.com/ethereum/go-ethereum/common"
    38  	"github.com/ethereum/go-ethereum/common/fdlimit"
    39  	"github.com/ethereum/go-ethereum/consensus"
    40  	"github.com/ethereum/go-ethereum/consensus/clique"
    41  	"github.com/ethereum/go-ethereum/consensus/ethash"
    42  	"github.com/ethereum/go-ethereum/core"
    43  	"github.com/ethereum/go-ethereum/core/vm"
    44  	"github.com/ethereum/go-ethereum/crypto"
    45  	"github.com/ethereum/go-ethereum/dashboard"
    46  	"github.com/ethereum/go-ethereum/eth"
    47  	"github.com/ethereum/go-ethereum/eth/downloader"
    48  	"github.com/ethereum/go-ethereum/eth/gasprice"
    49  	"github.com/ethereum/go-ethereum/ethdb"
    50  	"github.com/ethereum/go-ethereum/ethstats"
    51  	"github.com/ethereum/go-ethereum/graphql"
    52  	"github.com/ethereum/go-ethereum/les"
    53  	"github.com/ethereum/go-ethereum/log"
    54  	"github.com/ethereum/go-ethereum/metrics"
    55  	"github.com/ethereum/go-ethereum/metrics/influxdb"
    56  	"github.com/ethereum/go-ethereum/miner"
    57  	"github.com/ethereum/go-ethereum/node"
    58  	"github.com/ethereum/go-ethereum/p2p"
    59  	"github.com/ethereum/go-ethereum/p2p/discv5"
    60  	"github.com/ethereum/go-ethereum/p2p/enode"
    61  	"github.com/ethereum/go-ethereum/p2p/nat"
    62  	"github.com/ethereum/go-ethereum/p2p/netutil"
    63  	"github.com/ethereum/go-ethereum/params"
    64  	"github.com/ethereum/go-ethereum/rpc"
    65  	whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
    66  	pcsclite "github.com/gballet/go-libpcsclite"
    67  	cli "gopkg.in/urfave/cli.v1"
    68  )
    69  
    70  var (
    71  	CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...]
    72  {{if .cmd.Description}}{{.cmd.Description}}
    73  {{end}}{{if .cmd.Subcommands}}
    74  SUBCOMMANDS:
    75  	{{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    76  	{{end}}{{end}}{{if .categorizedFlags}}
    77  {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS:
    78  {{range $categorized.Flags}}{{"\t"}}{{.}}
    79  {{end}}
    80  {{end}}{{end}}`
    81  )
    82  
    83  func init() {
    84  	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
    85  
    86  VERSION:
    87     {{.Version}}
    88  
    89  COMMANDS:
    90     {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    91     {{end}}{{if .Flags}}
    92  GLOBAL OPTIONS:
    93     {{range .Flags}}{{.}}
    94     {{end}}{{end}}
    95  `
    96  	cli.CommandHelpTemplate = CommandHelpTemplate
    97  	cli.HelpPrinter = printHelp
    98  }
    99  
   100  // NewApp creates an app with sane defaults.
   101  func NewApp(gitCommit, gitDate, usage string) *cli.App {
   102  	app := cli.NewApp()
   103  	app.Name = filepath.Base(os.Args[0])
   104  	app.Author = ""
   105  	app.Email = ""
   106  	app.Version = params.VersionWithCommit(gitCommit, gitDate)
   107  	app.Usage = usage
   108  	return app
   109  }
   110  
   111  func printHelp(out io.Writer, templ string, data interface{}) {
   112  	funcMap := template.FuncMap{"join": strings.Join}
   113  	t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
   114  	w := tabwriter.NewWriter(out, 38, 8, 2, ' ', 0)
   115  	err := t.Execute(w, data)
   116  	if err != nil {
   117  		panic(err)
   118  	}
   119  	w.Flush()
   120  }
   121  
   122  // These are all the command line flags we support.
   123  // If you add to this list, please remember to include the
   124  // flag in the appropriate command definition.
   125  //
   126  // The flags are defined here so their names and help texts
   127  // are the same for all commands.
   128  
   129  var (
   130  	// General settings
   131  	DataDirFlag = DirectoryFlag{
   132  		Name:  "datadir",
   133  		Usage: "Data directory for the databases and keystore",
   134  		Value: DirectoryString(node.DefaultDataDir()),
   135  	}
   136  	AncientFlag = DirectoryFlag{
   137  		Name:  "datadir.ancient",
   138  		Usage: "Data directory for ancient chain segments (default = inside chaindata)",
   139  	}
   140  	KeyStoreDirFlag = DirectoryFlag{
   141  		Name:  "keystore",
   142  		Usage: "Directory for the keystore (default = inside the datadir)",
   143  	}
   144  	NoUSBFlag = cli.BoolFlag{
   145  		Name:  "nousb",
   146  		Usage: "Disables monitoring for and managing USB hardware wallets",
   147  	}
   148  	SmartCardDaemonPathFlag = cli.StringFlag{
   149  		Name:  "pcscdpath",
   150  		Usage: "Path to the smartcard daemon (pcscd) socket file",
   151  		Value: pcsclite.PCSCDSockName,
   152  	}
   153  	NetworkIdFlag = cli.Uint64Flag{
   154  		Name:  "networkid",
   155  		Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)",
   156  		Value: eth.DefaultConfig.NetworkId,
   157  	}
   158  	TestnetFlag = cli.BoolFlag{
   159  		Name:  "testnet",
   160  		Usage: "Ropsten network: pre-configured proof-of-work test network",
   161  	}
   162  	RinkebyFlag = cli.BoolFlag{
   163  		Name:  "rinkeby",
   164  		Usage: "Rinkeby network: pre-configured proof-of-authority test network",
   165  	}
   166  	GoerliFlag = cli.BoolFlag{
   167  		Name:  "goerli",
   168  		Usage: "Görli network: pre-configured proof-of-authority test network",
   169  	}
   170  	DeveloperFlag = cli.BoolFlag{
   171  		Name:  "dev",
   172  		Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
   173  	}
   174  	DeveloperPeriodFlag = cli.IntFlag{
   175  		Name:  "dev.period",
   176  		Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
   177  	}
   178  	IdentityFlag = cli.StringFlag{
   179  		Name:  "identity",
   180  		Usage: "Custom node name",
   181  	}
   182  	DocRootFlag = DirectoryFlag{
   183  		Name:  "docroot",
   184  		Usage: "Document Root for HTTPClient file scheme",
   185  		Value: DirectoryString(homeDir()),
   186  	}
   187  	ExitWhenSyncedFlag = cli.BoolFlag{
   188  		Name:  "exitwhensynced",
   189  		Usage: "Exits after block synchronisation completes",
   190  	}
   191  	IterativeOutputFlag = cli.BoolFlag{
   192  		Name:  "iterative",
   193  		Usage: "Print streaming JSON iteratively, delimited by newlines",
   194  	}
   195  	ExcludeStorageFlag = cli.BoolFlag{
   196  		Name:  "nostorage",
   197  		Usage: "Exclude storage entries (save db lookups)",
   198  	}
   199  	IncludeIncompletesFlag = cli.BoolFlag{
   200  		Name:  "incompletes",
   201  		Usage: "Include accounts for which we don't have the address (missing preimage)",
   202  	}
   203  	ExcludeCodeFlag = cli.BoolFlag{
   204  		Name:  "nocode",
   205  		Usage: "Exclude contract code (save db lookups)",
   206  	}
   207  	defaultSyncMode = eth.DefaultConfig.SyncMode
   208  	SyncModeFlag    = TextMarshalerFlag{
   209  		Name:  "syncmode",
   210  		Usage: `Blockchain sync mode ("fast", "full", or "light")`,
   211  		Value: &defaultSyncMode,
   212  	}
   213  	GCModeFlag = cli.StringFlag{
   214  		Name:  "gcmode",
   215  		Usage: `Blockchain garbage collection mode ("full", "archive")`,
   216  		Value: "full",
   217  	}
   218  	LightKDFFlag = cli.BoolFlag{
   219  		Name:  "lightkdf",
   220  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   221  	}
   222  	WhitelistFlag = cli.StringFlag{
   223  		Name:  "whitelist",
   224  		Usage: "Comma separated block number-to-hash mappings to enforce (<number>=<hash>)",
   225  	}
   226  	OverrideIstanbulFlag = cli.Uint64Flag{
   227  		Name:  "override.istanbul",
   228  		Usage: "Manually specify Istanbul fork-block, overriding the bundled setting",
   229  	}
   230  	// Light server and client settings
   231  	LightLegacyServFlag = cli.IntFlag{ // Deprecated in favor of light.serve, remove in 2021
   232  		Name:  "lightserv",
   233  		Usage: "Maximum percentage of time allowed for serving LES requests (deprecated, use --light.serve)",
   234  		Value: eth.DefaultConfig.LightServ,
   235  	}
   236  	LightServeFlag = cli.IntFlag{
   237  		Name:  "light.serve",
   238  		Usage: "Maximum percentage of time allowed for serving LES requests (multi-threaded processing allows values over 100)",
   239  		Value: eth.DefaultConfig.LightServ,
   240  	}
   241  	LightIngressFlag = cli.IntFlag{
   242  		Name:  "light.ingress",
   243  		Usage: "Incoming bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)",
   244  		Value: eth.DefaultConfig.LightIngress,
   245  	}
   246  	LightEgressFlag = cli.IntFlag{
   247  		Name:  "light.egress",
   248  		Usage: "Outgoing bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)",
   249  		Value: eth.DefaultConfig.LightEgress,
   250  	}
   251  	LightLegacyPeersFlag = cli.IntFlag{ // Deprecated in favor of light.maxpeers, remove in 2021
   252  		Name:  "lightpeers",
   253  		Usage: "Maximum number of light clients to serve, or light servers to attach to  (deprecated, use --light.maxpeers)",
   254  		Value: eth.DefaultConfig.LightPeers,
   255  	}
   256  	LightMaxPeersFlag = cli.IntFlag{
   257  		Name:  "light.maxpeers",
   258  		Usage: "Maximum number of light clients to serve, or light servers to attach to",
   259  		Value: eth.DefaultConfig.LightPeers,
   260  	}
   261  	UltraLightServersFlag = cli.StringFlag{
   262  		Name:  "ulc.servers",
   263  		Usage: "List of trusted ultra-light servers",
   264  		Value: strings.Join(eth.DefaultConfig.UltraLightServers, ","),
   265  	}
   266  	UltraLightFractionFlag = cli.IntFlag{
   267  		Name:  "ulc.fraction",
   268  		Usage: "Minimum % of trusted ultra-light servers required to announce a new head",
   269  		Value: eth.DefaultConfig.UltraLightFraction,
   270  	}
   271  	UltraLightOnlyAnnounceFlag = cli.BoolFlag{
   272  		Name:  "ulc.onlyannounce",
   273  		Usage: "Ultra light server sends announcements only",
   274  	}
   275  	// Dashboard settings
   276  	DashboardEnabledFlag = cli.BoolFlag{
   277  		Name:  "dashboard",
   278  		Usage: "Enable the dashboard",
   279  	}
   280  	DashboardAddrFlag = cli.StringFlag{
   281  		Name:  "dashboard.addr",
   282  		Usage: "Dashboard listening interface",
   283  		Value: dashboard.DefaultConfig.Host,
   284  	}
   285  	DashboardPortFlag = cli.IntFlag{
   286  		Name:  "dashboard.host",
   287  		Usage: "Dashboard listening port",
   288  		Value: dashboard.DefaultConfig.Port,
   289  	}
   290  	DashboardRefreshFlag = cli.DurationFlag{
   291  		Name:  "dashboard.refresh",
   292  		Usage: "Dashboard metrics collection refresh rate",
   293  		Value: dashboard.DefaultConfig.Refresh,
   294  	}
   295  	// Ethash settings
   296  	EthashCacheDirFlag = DirectoryFlag{
   297  		Name:  "ethash.cachedir",
   298  		Usage: "Directory to store the ethash verification caches (default = inside the datadir)",
   299  	}
   300  	EthashCachesInMemoryFlag = cli.IntFlag{
   301  		Name:  "ethash.cachesinmem",
   302  		Usage: "Number of recent ethash caches to keep in memory (16MB each)",
   303  		Value: eth.DefaultConfig.Ethash.CachesInMem,
   304  	}
   305  	EthashCachesOnDiskFlag = cli.IntFlag{
   306  		Name:  "ethash.cachesondisk",
   307  		Usage: "Number of recent ethash caches to keep on disk (16MB each)",
   308  		Value: eth.DefaultConfig.Ethash.CachesOnDisk,
   309  	}
   310  	EthashDatasetDirFlag = DirectoryFlag{
   311  		Name:  "ethash.dagdir",
   312  		Usage: "Directory to store the ethash mining DAGs",
   313  		Value: DirectoryString(eth.DefaultConfig.Ethash.DatasetDir),
   314  	}
   315  	EthashDatasetsInMemoryFlag = cli.IntFlag{
   316  		Name:  "ethash.dagsinmem",
   317  		Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
   318  		Value: eth.DefaultConfig.Ethash.DatasetsInMem,
   319  	}
   320  	EthashDatasetsOnDiskFlag = cli.IntFlag{
   321  		Name:  "ethash.dagsondisk",
   322  		Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
   323  		Value: eth.DefaultConfig.Ethash.DatasetsOnDisk,
   324  	}
   325  	// Transaction pool settings
   326  	TxPoolLocalsFlag = cli.StringFlag{
   327  		Name:  "txpool.locals",
   328  		Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)",
   329  	}
   330  	TxPoolNoLocalsFlag = cli.BoolFlag{
   331  		Name:  "txpool.nolocals",
   332  		Usage: "Disables price exemptions for locally submitted transactions",
   333  	}
   334  	TxPoolJournalFlag = cli.StringFlag{
   335  		Name:  "txpool.journal",
   336  		Usage: "Disk journal for local transaction to survive node restarts",
   337  		Value: core.DefaultTxPoolConfig.Journal,
   338  	}
   339  	TxPoolRejournalFlag = cli.DurationFlag{
   340  		Name:  "txpool.rejournal",
   341  		Usage: "Time interval to regenerate the local transaction journal",
   342  		Value: core.DefaultTxPoolConfig.Rejournal,
   343  	}
   344  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   345  		Name:  "txpool.pricelimit",
   346  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   347  		Value: eth.DefaultConfig.TxPool.PriceLimit,
   348  	}
   349  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   350  		Name:  "txpool.pricebump",
   351  		Usage: "Price bump percentage to replace an already existing transaction",
   352  		Value: eth.DefaultConfig.TxPool.PriceBump,
   353  	}
   354  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   355  		Name:  "txpool.accountslots",
   356  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   357  		Value: eth.DefaultConfig.TxPool.AccountSlots,
   358  	}
   359  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   360  		Name:  "txpool.globalslots",
   361  		Usage: "Maximum number of executable transaction slots for all accounts",
   362  		Value: eth.DefaultConfig.TxPool.GlobalSlots,
   363  	}
   364  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   365  		Name:  "txpool.accountqueue",
   366  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   367  		Value: eth.DefaultConfig.TxPool.AccountQueue,
   368  	}
   369  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   370  		Name:  "txpool.globalqueue",
   371  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   372  		Value: eth.DefaultConfig.TxPool.GlobalQueue,
   373  	}
   374  	TxPoolLifetimeFlag = cli.DurationFlag{
   375  		Name:  "txpool.lifetime",
   376  		Usage: "Maximum amount of time non-executable transaction are queued",
   377  		Value: eth.DefaultConfig.TxPool.Lifetime,
   378  	}
   379  	// Performance tuning settings
   380  	CacheFlag = cli.IntFlag{
   381  		Name:  "cache",
   382  		Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node, 128 light mode)",
   383  		Value: 1024,
   384  	}
   385  	CacheDatabaseFlag = cli.IntFlag{
   386  		Name:  "cache.database",
   387  		Usage: "Percentage of cache memory allowance to use for database io",
   388  		Value: 50,
   389  	}
   390  	CacheTrieFlag = cli.IntFlag{
   391  		Name:  "cache.trie",
   392  		Usage: "Percentage of cache memory allowance to use for trie caching (default = 25% full mode, 50% archive mode)",
   393  		Value: 25,
   394  	}
   395  	CacheGCFlag = cli.IntFlag{
   396  		Name:  "cache.gc",
   397  		Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
   398  		Value: 25,
   399  	}
   400  	CacheNoPrefetchFlag = cli.BoolFlag{
   401  		Name:  "cache.noprefetch",
   402  		Usage: "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)",
   403  	}
   404  	// Miner settings
   405  	MiningEnabledFlag = cli.BoolFlag{
   406  		Name:  "mine",
   407  		Usage: "Enable mining",
   408  	}
   409  	MinerThreadsFlag = cli.IntFlag{
   410  		Name:  "miner.threads",
   411  		Usage: "Number of CPU threads to use for mining",
   412  		Value: 0,
   413  	}
   414  	MinerLegacyThreadsFlag = cli.IntFlag{
   415  		Name:  "minerthreads",
   416  		Usage: "Number of CPU threads to use for mining (deprecated, use --miner.threads)",
   417  		Value: 0,
   418  	}
   419  	MinerNotifyFlag = cli.StringFlag{
   420  		Name:  "miner.notify",
   421  		Usage: "Comma separated HTTP URL list to notify of new work packages",
   422  	}
   423  	MinerGasTargetFlag = cli.Uint64Flag{
   424  		Name:  "miner.gastarget",
   425  		Usage: "Target gas floor for mined blocks",
   426  		Value: eth.DefaultConfig.Miner.GasFloor,
   427  	}
   428  	MinerLegacyGasTargetFlag = cli.Uint64Flag{
   429  		Name:  "targetgaslimit",
   430  		Usage: "Target gas floor for mined blocks (deprecated, use --miner.gastarget)",
   431  		Value: eth.DefaultConfig.Miner.GasFloor,
   432  	}
   433  	MinerGasLimitFlag = cli.Uint64Flag{
   434  		Name:  "miner.gaslimit",
   435  		Usage: "Target gas ceiling for mined blocks",
   436  		Value: eth.DefaultConfig.Miner.GasCeil,
   437  	}
   438  	MinerGasPriceFlag = BigFlag{
   439  		Name:  "miner.gasprice",
   440  		Usage: "Minimum gas price for mining a transaction",
   441  		Value: eth.DefaultConfig.Miner.GasPrice,
   442  	}
   443  	MinerLegacyGasPriceFlag = BigFlag{
   444  		Name:  "gasprice",
   445  		Usage: "Minimum gas price for mining a transaction (deprecated, use --miner.gasprice)",
   446  		Value: eth.DefaultConfig.Miner.GasPrice,
   447  	}
   448  	MinerEtherbaseFlag = cli.StringFlag{
   449  		Name:  "miner.etherbase",
   450  		Usage: "Public address for block mining rewards (default = first account)",
   451  		Value: "0",
   452  	}
   453  	MinerLegacyEtherbaseFlag = cli.StringFlag{
   454  		Name:  "etherbase",
   455  		Usage: "Public address for block mining rewards (default = first account, deprecated, use --miner.etherbase)",
   456  		Value: "0",
   457  	}
   458  	MinerExtraDataFlag = cli.StringFlag{
   459  		Name:  "miner.extradata",
   460  		Usage: "Block extra data set by the miner (default = client version)",
   461  	}
   462  	MinerLegacyExtraDataFlag = cli.StringFlag{
   463  		Name:  "extradata",
   464  		Usage: "Block extra data set by the miner (default = client version, deprecated, use --miner.extradata)",
   465  	}
   466  	MinerRecommitIntervalFlag = cli.DurationFlag{
   467  		Name:  "miner.recommit",
   468  		Usage: "Time interval to recreate the block being mined",
   469  		Value: eth.DefaultConfig.Miner.Recommit,
   470  	}
   471  	MinerNoVerfiyFlag = cli.BoolFlag{
   472  		Name:  "miner.noverify",
   473  		Usage: "Disable remote sealing verification",
   474  	}
   475  	// Account settings
   476  	UnlockedAccountFlag = cli.StringFlag{
   477  		Name:  "unlock",
   478  		Usage: "Comma separated list of accounts to unlock",
   479  		Value: "",
   480  	}
   481  	PasswordFileFlag = cli.StringFlag{
   482  		Name:  "password",
   483  		Usage: "Password file to use for non-interactive password input",
   484  		Value: "",
   485  	}
   486  	ExternalSignerFlag = cli.StringFlag{
   487  		Name:  "signer",
   488  		Usage: "External signer (url or path to ipc file)",
   489  		Value: "",
   490  	}
   491  	VMEnableDebugFlag = cli.BoolFlag{
   492  		Name:  "vmdebug",
   493  		Usage: "Record information useful for VM and contract debugging",
   494  	}
   495  	InsecureUnlockAllowedFlag = cli.BoolFlag{
   496  		Name:  "allow-insecure-unlock",
   497  		Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http",
   498  	}
   499  	RPCGlobalGasCap = cli.Uint64Flag{
   500  		Name:  "rpc.gascap",
   501  		Usage: "Sets a cap on gas that can be used in eth_call/estimateGas",
   502  	}
   503  	// Logging and debug settings
   504  	EthStatsURLFlag = cli.StringFlag{
   505  		Name:  "ethstats",
   506  		Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
   507  	}
   508  	FakePoWFlag = cli.BoolFlag{
   509  		Name:  "fakepow",
   510  		Usage: "Disables proof-of-work verification",
   511  	}
   512  	NoCompactionFlag = cli.BoolFlag{
   513  		Name:  "nocompaction",
   514  		Usage: "Disables db compaction after import",
   515  	}
   516  	// RPC settings
   517  	IPCDisabledFlag = cli.BoolFlag{
   518  		Name:  "ipcdisable",
   519  		Usage: "Disable the IPC-RPC server",
   520  	}
   521  	IPCPathFlag = DirectoryFlag{
   522  		Name:  "ipcpath",
   523  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   524  	}
   525  	RPCEnabledFlag = cli.BoolFlag{
   526  		Name:  "rpc",
   527  		Usage: "Enable the HTTP-RPC server",
   528  	}
   529  	RPCListenAddrFlag = cli.StringFlag{
   530  		Name:  "rpcaddr",
   531  		Usage: "HTTP-RPC server listening interface",
   532  		Value: node.DefaultHTTPHost,
   533  	}
   534  	RPCPortFlag = cli.IntFlag{
   535  		Name:  "rpcport",
   536  		Usage: "HTTP-RPC server listening port",
   537  		Value: node.DefaultHTTPPort,
   538  	}
   539  	RPCCORSDomainFlag = cli.StringFlag{
   540  		Name:  "rpccorsdomain",
   541  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   542  		Value: "",
   543  	}
   544  	RPCVirtualHostsFlag = cli.StringFlag{
   545  		Name:  "rpcvhosts",
   546  		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   547  		Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","),
   548  	}
   549  	RPCApiFlag = cli.StringFlag{
   550  		Name:  "rpcapi",
   551  		Usage: "API's offered over the HTTP-RPC interface",
   552  		Value: "",
   553  	}
   554  	WSEnabledFlag = cli.BoolFlag{
   555  		Name:  "ws",
   556  		Usage: "Enable the WS-RPC server",
   557  	}
   558  	WSListenAddrFlag = cli.StringFlag{
   559  		Name:  "wsaddr",
   560  		Usage: "WS-RPC server listening interface",
   561  		Value: node.DefaultWSHost,
   562  	}
   563  	WSPortFlag = cli.IntFlag{
   564  		Name:  "wsport",
   565  		Usage: "WS-RPC server listening port",
   566  		Value: node.DefaultWSPort,
   567  	}
   568  	WSApiFlag = cli.StringFlag{
   569  		Name:  "wsapi",
   570  		Usage: "API's offered over the WS-RPC interface",
   571  		Value: "",
   572  	}
   573  	WSAllowedOriginsFlag = cli.StringFlag{
   574  		Name:  "wsorigins",
   575  		Usage: "Origins from which to accept websockets requests",
   576  		Value: "",
   577  	}
   578  	GraphQLEnabledFlag = cli.BoolFlag{
   579  		Name:  "graphql",
   580  		Usage: "Enable the GraphQL server",
   581  	}
   582  	GraphQLListenAddrFlag = cli.StringFlag{
   583  		Name:  "graphql.addr",
   584  		Usage: "GraphQL server listening interface",
   585  		Value: node.DefaultGraphQLHost,
   586  	}
   587  	GraphQLPortFlag = cli.IntFlag{
   588  		Name:  "graphql.port",
   589  		Usage: "GraphQL server listening port",
   590  		Value: node.DefaultGraphQLPort,
   591  	}
   592  	GraphQLCORSDomainFlag = cli.StringFlag{
   593  		Name:  "graphql.corsdomain",
   594  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   595  		Value: "",
   596  	}
   597  	GraphQLVirtualHostsFlag = cli.StringFlag{
   598  		Name:  "graphql.vhosts",
   599  		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   600  		Value: strings.Join(node.DefaultConfig.GraphQLVirtualHosts, ","),
   601  	}
   602  	ExecFlag = cli.StringFlag{
   603  		Name:  "exec",
   604  		Usage: "Execute JavaScript statement",
   605  	}
   606  	PreloadJSFlag = cli.StringFlag{
   607  		Name:  "preload",
   608  		Usage: "Comma separated list of JavaScript files to preload into the console",
   609  	}
   610  
   611  	// Network Settings
   612  	MaxPeersFlag = cli.IntFlag{
   613  		Name:  "maxpeers",
   614  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   615  		Value: node.DefaultConfig.P2P.MaxPeers,
   616  	}
   617  	MaxPendingPeersFlag = cli.IntFlag{
   618  		Name:  "maxpendpeers",
   619  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   620  		Value: node.DefaultConfig.P2P.MaxPendingPeers,
   621  	}
   622  	ListenPortFlag = cli.IntFlag{
   623  		Name:  "port",
   624  		Usage: "Network listening port",
   625  		Value: 30303,
   626  	}
   627  	BootnodesFlag = cli.StringFlag{
   628  		Name:  "bootnodes",
   629  		Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)",
   630  		Value: "",
   631  	}
   632  	BootnodesV4Flag = cli.StringFlag{
   633  		Name:  "bootnodesv4",
   634  		Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)",
   635  		Value: "",
   636  	}
   637  	BootnodesV5Flag = cli.StringFlag{
   638  		Name:  "bootnodesv5",
   639  		Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)",
   640  		Value: "",
   641  	}
   642  	NodeKeyFileFlag = cli.StringFlag{
   643  		Name:  "nodekey",
   644  		Usage: "P2P node key file",
   645  	}
   646  	NodeKeyHexFlag = cli.StringFlag{
   647  		Name:  "nodekeyhex",
   648  		Usage: "P2P node key as hex (for testing)",
   649  	}
   650  	NATFlag = cli.StringFlag{
   651  		Name:  "nat",
   652  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   653  		Value: "any",
   654  	}
   655  	NoDiscoverFlag = cli.BoolFlag{
   656  		Name:  "nodiscover",
   657  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   658  	}
   659  	DiscoveryV5Flag = cli.BoolFlag{
   660  		Name:  "v5disc",
   661  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   662  	}
   663  	NetrestrictFlag = cli.StringFlag{
   664  		Name:  "netrestrict",
   665  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   666  	}
   667  
   668  	// ATM the url is left to the user and deployment to
   669  	JSpathFlag = cli.StringFlag{
   670  		Name:  "jspath",
   671  		Usage: "JavaScript root path for `loadScript`",
   672  		Value: ".",
   673  	}
   674  
   675  	// Gas price oracle settings
   676  	GpoBlocksFlag = cli.IntFlag{
   677  		Name:  "gpoblocks",
   678  		Usage: "Number of recent blocks to check for gas prices",
   679  		Value: eth.DefaultConfig.GPO.Blocks,
   680  	}
   681  	GpoPercentileFlag = cli.IntFlag{
   682  		Name:  "gpopercentile",
   683  		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   684  		Value: eth.DefaultConfig.GPO.Percentile,
   685  	}
   686  	WhisperEnabledFlag = cli.BoolFlag{
   687  		Name:  "shh",
   688  		Usage: "Enable Whisper",
   689  	}
   690  	WhisperMaxMessageSizeFlag = cli.IntFlag{
   691  		Name:  "shh.maxmessagesize",
   692  		Usage: "Max message size accepted",
   693  		Value: int(whisper.DefaultMaxMessageSize),
   694  	}
   695  	WhisperMinPOWFlag = cli.Float64Flag{
   696  		Name:  "shh.pow",
   697  		Usage: "Minimum POW accepted",
   698  		Value: whisper.DefaultMinimumPoW,
   699  	}
   700  	WhisperRestrictConnectionBetweenLightClientsFlag = cli.BoolFlag{
   701  		Name:  "shh.restrict-light",
   702  		Usage: "Restrict connection between two whisper light clients",
   703  	}
   704  
   705  	// Metrics flags
   706  	MetricsEnabledFlag = cli.BoolFlag{
   707  		Name:  "metrics",
   708  		Usage: "Enable metrics collection and reporting",
   709  	}
   710  	MetricsEnabledExpensiveFlag = cli.BoolFlag{
   711  		Name:  "metrics.expensive",
   712  		Usage: "Enable expensive metrics collection and reporting",
   713  	}
   714  	MetricsEnableInfluxDBFlag = cli.BoolFlag{
   715  		Name:  "metrics.influxdb",
   716  		Usage: "Enable metrics export/push to an external InfluxDB database",
   717  	}
   718  	MetricsInfluxDBEndpointFlag = cli.StringFlag{
   719  		Name:  "metrics.influxdb.endpoint",
   720  		Usage: "InfluxDB API endpoint to report metrics to",
   721  		Value: "http://localhost:8086",
   722  	}
   723  	MetricsInfluxDBDatabaseFlag = cli.StringFlag{
   724  		Name:  "metrics.influxdb.database",
   725  		Usage: "InfluxDB database name to push reported metrics to",
   726  		Value: "geth",
   727  	}
   728  	MetricsInfluxDBUsernameFlag = cli.StringFlag{
   729  		Name:  "metrics.influxdb.username",
   730  		Usage: "Username to authorize access to the database",
   731  		Value: "test",
   732  	}
   733  	MetricsInfluxDBPasswordFlag = cli.StringFlag{
   734  		Name:  "metrics.influxdb.password",
   735  		Usage: "Password to authorize access to the database",
   736  		Value: "test",
   737  	}
   738  	// Tags are part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB.
   739  	// For example `host` tag could be used so that we can group all nodes and average a measurement
   740  	// across all of them, but also so that we can select a specific node and inspect its measurements.
   741  	// https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key
   742  	MetricsInfluxDBTagsFlag = cli.StringFlag{
   743  		Name:  "metrics.influxdb.tags",
   744  		Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements",
   745  		Value: "host=localhost",
   746  	}
   747  
   748  	EWASMInterpreterFlag = cli.StringFlag{
   749  		Name:  "vm.ewasm",
   750  		Usage: "External ewasm configuration (default = built-in interpreter)",
   751  		Value: "",
   752  	}
   753  	EVMInterpreterFlag = cli.StringFlag{
   754  		Name:  "vm.evm",
   755  		Usage: "External EVM configuration (default = built-in interpreter)",
   756  		Value: "",
   757  	}
   758  )
   759  
   760  // MakeDataDir retrieves the currently requested data directory, terminating
   761  // if none (or the empty string) is specified. If the node is starting a testnet,
   762  // the a subdirectory of the specified datadir will be used.
   763  func MakeDataDir(ctx *cli.Context) string {
   764  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   765  		if ctx.GlobalBool(TestnetFlag.Name) {
   766  			return filepath.Join(path, "testnet")
   767  		}
   768  		if ctx.GlobalBool(RinkebyFlag.Name) {
   769  			return filepath.Join(path, "rinkeby")
   770  		}
   771  		if ctx.GlobalBool(GoerliFlag.Name) {
   772  			return filepath.Join(path, "goerli")
   773  		}
   774  		return path
   775  	}
   776  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   777  	return ""
   778  }
   779  
   780  // setNodeKey creates a node key from set command line flags, either loading it
   781  // from a file or as a specified hex value. If neither flags were provided, this
   782  // method returns nil and an emphemeral key is to be generated.
   783  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   784  	var (
   785  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   786  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   787  		key  *ecdsa.PrivateKey
   788  		err  error
   789  	)
   790  	switch {
   791  	case file != "" && hex != "":
   792  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   793  	case file != "":
   794  		if key, err = crypto.LoadECDSA(file); err != nil {
   795  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   796  		}
   797  		cfg.PrivateKey = key
   798  	case hex != "":
   799  		if key, err = crypto.HexToECDSA(hex); err != nil {
   800  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   801  		}
   802  		cfg.PrivateKey = key
   803  	}
   804  }
   805  
   806  // setNodeUserIdent creates the user identifier from CLI flags.
   807  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   808  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   809  		cfg.UserIdent = identity
   810  	}
   811  }
   812  
   813  // setBootstrapNodes creates a list of bootstrap nodes from the command line
   814  // flags, reverting to pre-configured ones if none have been specified.
   815  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   816  	urls := params.MainnetBootnodes
   817  	switch {
   818  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name):
   819  		if ctx.GlobalIsSet(BootnodesV4Flag.Name) {
   820  			urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",")
   821  		} else {
   822  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   823  		}
   824  	case ctx.GlobalBool(TestnetFlag.Name):
   825  		urls = params.TestnetBootnodes
   826  	case ctx.GlobalBool(RinkebyFlag.Name):
   827  		urls = params.RinkebyBootnodes
   828  	case ctx.GlobalBool(GoerliFlag.Name):
   829  		urls = params.GoerliBootnodes
   830  	case cfg.BootstrapNodes != nil:
   831  		return // already set, don't apply defaults.
   832  	}
   833  
   834  	cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls))
   835  	for _, url := range urls {
   836  		if url != "" {
   837  			node, err := enode.Parse(enode.ValidSchemes, url)
   838  			if err != nil {
   839  				log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
   840  				continue
   841  			}
   842  			cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   843  		}
   844  	}
   845  }
   846  
   847  // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
   848  // flags, reverting to pre-configured ones if none have been specified.
   849  func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
   850  	urls := params.DiscoveryV5Bootnodes
   851  	switch {
   852  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name):
   853  		if ctx.GlobalIsSet(BootnodesV5Flag.Name) {
   854  			urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",")
   855  		} else {
   856  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   857  		}
   858  	case ctx.GlobalBool(RinkebyFlag.Name):
   859  		urls = params.RinkebyBootnodes
   860  	case ctx.GlobalBool(GoerliFlag.Name):
   861  		urls = params.GoerliBootnodes
   862  	case cfg.BootstrapNodesV5 != nil:
   863  		return // already set, don't apply defaults.
   864  	}
   865  
   866  	cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls))
   867  	for _, url := range urls {
   868  		if url != "" {
   869  			node, err := discv5.ParseNode(url)
   870  			if err != nil {
   871  				log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   872  				continue
   873  			}
   874  			cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
   875  		}
   876  	}
   877  }
   878  
   879  // setListenAddress creates a TCP listening address string from set command
   880  // line flags.
   881  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   882  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   883  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   884  	}
   885  }
   886  
   887  // setNAT creates a port mapper from command line flags.
   888  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   889  	if ctx.GlobalIsSet(NATFlag.Name) {
   890  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   891  		if err != nil {
   892  			Fatalf("Option %s: %v", NATFlag.Name, err)
   893  		}
   894  		cfg.NAT = natif
   895  	}
   896  }
   897  
   898  // splitAndTrim splits input separated by a comma
   899  // and trims excessive white space from the substrings.
   900  func splitAndTrim(input string) []string {
   901  	result := strings.Split(input, ",")
   902  	for i, r := range result {
   903  		result[i] = strings.TrimSpace(r)
   904  	}
   905  	return result
   906  }
   907  
   908  // setHTTP creates the HTTP RPC listener interface string from the set
   909  // command line flags, returning empty if the HTTP endpoint is disabled.
   910  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   911  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   912  		cfg.HTTPHost = "127.0.0.1"
   913  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   914  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   915  		}
   916  	}
   917  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   918  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   919  	}
   920  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   921  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   922  	}
   923  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   924  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   925  	}
   926  	if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) {
   927  		cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name))
   928  	}
   929  }
   930  
   931  // setGraphQL creates the GraphQL listener interface string from the set
   932  // command line flags, returning empty if the GraphQL endpoint is disabled.
   933  func setGraphQL(ctx *cli.Context, cfg *node.Config) {
   934  	if ctx.GlobalBool(GraphQLEnabledFlag.Name) && cfg.GraphQLHost == "" {
   935  		cfg.GraphQLHost = "127.0.0.1"
   936  		if ctx.GlobalIsSet(GraphQLListenAddrFlag.Name) {
   937  			cfg.GraphQLHost = ctx.GlobalString(GraphQLListenAddrFlag.Name)
   938  		}
   939  	}
   940  	cfg.GraphQLPort = ctx.GlobalInt(GraphQLPortFlag.Name)
   941  	if ctx.GlobalIsSet(GraphQLCORSDomainFlag.Name) {
   942  		cfg.GraphQLCors = splitAndTrim(ctx.GlobalString(GraphQLCORSDomainFlag.Name))
   943  	}
   944  	if ctx.GlobalIsSet(GraphQLVirtualHostsFlag.Name) {
   945  		cfg.GraphQLVirtualHosts = splitAndTrim(ctx.GlobalString(GraphQLVirtualHostsFlag.Name))
   946  	}
   947  }
   948  
   949  // setWS creates the WebSocket RPC listener interface string from the set
   950  // command line flags, returning empty if the HTTP endpoint is disabled.
   951  func setWS(ctx *cli.Context, cfg *node.Config) {
   952  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   953  		cfg.WSHost = "127.0.0.1"
   954  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   955  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   956  		}
   957  	}
   958  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   959  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   960  	}
   961  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   962  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   963  	}
   964  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   965  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   966  	}
   967  }
   968  
   969  // setIPC creates an IPC path configuration from the set command line flags,
   970  // returning an empty string if IPC was explicitly disabled, or the set path.
   971  func setIPC(ctx *cli.Context, cfg *node.Config) {
   972  	CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   973  	switch {
   974  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   975  		cfg.IPCPath = ""
   976  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   977  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   978  	}
   979  }
   980  
   981  // setLes configures the les server and ultra light client settings from the command line flags.
   982  func setLes(ctx *cli.Context, cfg *eth.Config) {
   983  	if ctx.GlobalIsSet(LightLegacyServFlag.Name) {
   984  		cfg.LightServ = ctx.GlobalInt(LightLegacyServFlag.Name)
   985  	}
   986  	if ctx.GlobalIsSet(LightServeFlag.Name) {
   987  		cfg.LightServ = ctx.GlobalInt(LightServeFlag.Name)
   988  	}
   989  	if ctx.GlobalIsSet(LightIngressFlag.Name) {
   990  		cfg.LightIngress = ctx.GlobalInt(LightIngressFlag.Name)
   991  	}
   992  	if ctx.GlobalIsSet(LightEgressFlag.Name) {
   993  		cfg.LightEgress = ctx.GlobalInt(LightEgressFlag.Name)
   994  	}
   995  	if ctx.GlobalIsSet(LightLegacyPeersFlag.Name) {
   996  		cfg.LightPeers = ctx.GlobalInt(LightLegacyPeersFlag.Name)
   997  	}
   998  	if ctx.GlobalIsSet(LightMaxPeersFlag.Name) {
   999  		cfg.LightPeers = ctx.GlobalInt(LightMaxPeersFlag.Name)
  1000  	}
  1001  	if ctx.GlobalIsSet(UltraLightServersFlag.Name) {
  1002  		cfg.UltraLightServers = strings.Split(ctx.GlobalString(UltraLightServersFlag.Name), ",")
  1003  	}
  1004  	if ctx.GlobalIsSet(UltraLightFractionFlag.Name) {
  1005  		cfg.UltraLightFraction = ctx.GlobalInt(UltraLightFractionFlag.Name)
  1006  	}
  1007  	if cfg.UltraLightFraction <= 0 && cfg.UltraLightFraction > 100 {
  1008  		log.Error("Ultra light fraction is invalid", "had", cfg.UltraLightFraction, "updated", eth.DefaultConfig.UltraLightFraction)
  1009  		cfg.UltraLightFraction = eth.DefaultConfig.UltraLightFraction
  1010  	}
  1011  	if ctx.GlobalIsSet(UltraLightOnlyAnnounceFlag.Name) {
  1012  		cfg.UltraLightOnlyAnnounce = ctx.GlobalBool(UltraLightOnlyAnnounceFlag.Name)
  1013  	}
  1014  }
  1015  
  1016  // makeDatabaseHandles raises out the number of allowed file handles per process
  1017  // for Geth and returns half of the allowance to assign to the database.
  1018  func makeDatabaseHandles() int {
  1019  	limit, err := fdlimit.Maximum()
  1020  	if err != nil {
  1021  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
  1022  	}
  1023  	raised, err := fdlimit.Raise(uint64(limit))
  1024  	if err != nil {
  1025  		Fatalf("Failed to raise file descriptor allowance: %v", err)
  1026  	}
  1027  	return int(raised / 2) // Leave half for networking and other stuff
  1028  }
  1029  
  1030  // MakeAddress converts an account specified directly as a hex encoded string or
  1031  // a key index in the key store to an internal account representation.
  1032  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
  1033  	// If the specified account is a valid address, return it
  1034  	if common.IsHexAddress(account) {
  1035  		return accounts.Account{Address: common.HexToAddress(account)}, nil
  1036  	}
  1037  	// Otherwise try to interpret the account as a keystore index
  1038  	index, err := strconv.Atoi(account)
  1039  	if err != nil || index < 0 {
  1040  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
  1041  	}
  1042  	log.Warn("-------------------------------------------------------------------")
  1043  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
  1044  	log.Warn("This functionality is deprecated and will be removed in the future!")
  1045  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
  1046  	log.Warn("-------------------------------------------------------------------")
  1047  
  1048  	accs := ks.Accounts()
  1049  	if len(accs) <= index {
  1050  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
  1051  	}
  1052  	return accs[index], nil
  1053  }
  1054  
  1055  // setEtherbase retrieves the etherbase either from the directly specified
  1056  // command line flags or from the keystore if CLI indexed.
  1057  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) {
  1058  	// Extract the current etherbase, new flag overriding legacy one
  1059  	var etherbase string
  1060  	if ctx.GlobalIsSet(MinerLegacyEtherbaseFlag.Name) {
  1061  		etherbase = ctx.GlobalString(MinerLegacyEtherbaseFlag.Name)
  1062  	}
  1063  	if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) {
  1064  		etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name)
  1065  	}
  1066  	// Convert the etherbase into an address and configure it
  1067  	if etherbase != "" {
  1068  		if ks != nil {
  1069  			account, err := MakeAddress(ks, etherbase)
  1070  			if err != nil {
  1071  				Fatalf("Invalid miner etherbase: %v", err)
  1072  			}
  1073  			cfg.Miner.Etherbase = account.Address
  1074  		} else {
  1075  			Fatalf("No etherbase configured")
  1076  		}
  1077  	}
  1078  }
  1079  
  1080  // MakePasswordList reads password lines from the file specified by the global --password flag.
  1081  func MakePasswordList(ctx *cli.Context) []string {
  1082  	path := ctx.GlobalString(PasswordFileFlag.Name)
  1083  	if path == "" {
  1084  		return nil
  1085  	}
  1086  	text, err := ioutil.ReadFile(path)
  1087  	if err != nil {
  1088  		Fatalf("Failed to read password file: %v", err)
  1089  	}
  1090  	lines := strings.Split(string(text), "\n")
  1091  	// Sanitise DOS line endings.
  1092  	for i := range lines {
  1093  		lines[i] = strings.TrimRight(lines[i], "\r")
  1094  	}
  1095  	return lines
  1096  }
  1097  
  1098  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
  1099  	setNodeKey(ctx, cfg)
  1100  	setNAT(ctx, cfg)
  1101  	setListenAddress(ctx, cfg)
  1102  	setBootstrapNodes(ctx, cfg)
  1103  	setBootstrapNodesV5(ctx, cfg)
  1104  
  1105  	lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light"
  1106  	lightServer := (ctx.GlobalInt(LightLegacyServFlag.Name) != 0 || ctx.GlobalInt(LightServeFlag.Name) != 0)
  1107  
  1108  	lightPeers := ctx.GlobalInt(LightLegacyPeersFlag.Name)
  1109  	if ctx.GlobalIsSet(LightMaxPeersFlag.Name) {
  1110  		lightPeers = ctx.GlobalInt(LightMaxPeersFlag.Name)
  1111  	}
  1112  	if lightClient && !ctx.GlobalIsSet(LightLegacyPeersFlag.Name) && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) {
  1113  		// dynamic default - for clients we use 1/10th of the default for servers
  1114  		lightPeers /= 10
  1115  	}
  1116  
  1117  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
  1118  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
  1119  		if lightServer && !ctx.GlobalIsSet(LightLegacyPeersFlag.Name) && !ctx.GlobalIsSet(LightMaxPeersFlag.Name) {
  1120  			cfg.MaxPeers += lightPeers
  1121  		}
  1122  	} else {
  1123  		if lightServer {
  1124  			cfg.MaxPeers += lightPeers
  1125  		}
  1126  		if lightClient && (ctx.GlobalIsSet(LightLegacyPeersFlag.Name) || ctx.GlobalIsSet(LightMaxPeersFlag.Name)) && cfg.MaxPeers < lightPeers {
  1127  			cfg.MaxPeers = lightPeers
  1128  		}
  1129  	}
  1130  	if !(lightClient || lightServer) {
  1131  		lightPeers = 0
  1132  	}
  1133  	ethPeers := cfg.MaxPeers - lightPeers
  1134  	if lightClient {
  1135  		ethPeers = 0
  1136  	}
  1137  	log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
  1138  
  1139  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
  1140  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
  1141  	}
  1142  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient {
  1143  		cfg.NoDiscovery = true
  1144  	}
  1145  
  1146  	// if we're running a light client or server, force enable the v5 peer discovery
  1147  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
  1148  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
  1149  	forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name)
  1150  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
  1151  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
  1152  	} else if forceV5Discovery {
  1153  		cfg.DiscoveryV5 = true
  1154  	}
  1155  
  1156  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
  1157  		list, err := netutil.ParseNetlist(netrestrict)
  1158  		if err != nil {
  1159  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
  1160  		}
  1161  		cfg.NetRestrict = list
  1162  	}
  1163  
  1164  	if ctx.GlobalBool(DeveloperFlag.Name) {
  1165  		// --dev mode can't use p2p networking.
  1166  		cfg.MaxPeers = 0
  1167  		cfg.ListenAddr = ":0"
  1168  		cfg.NoDiscovery = true
  1169  		cfg.DiscoveryV5 = false
  1170  	}
  1171  }
  1172  
  1173  // SetNodeConfig applies node-related command line flags to the config.
  1174  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
  1175  	SetP2PConfig(ctx, &cfg.P2P)
  1176  	setIPC(ctx, cfg)
  1177  	setHTTP(ctx, cfg)
  1178  	setGraphQL(ctx, cfg)
  1179  	setWS(ctx, cfg)
  1180  	setNodeUserIdent(ctx, cfg)
  1181  	setDataDir(ctx, cfg)
  1182  	setSmartCard(ctx, cfg)
  1183  
  1184  	if ctx.GlobalIsSet(ExternalSignerFlag.Name) {
  1185  		cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name)
  1186  	}
  1187  
  1188  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
  1189  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
  1190  	}
  1191  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
  1192  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
  1193  	}
  1194  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
  1195  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
  1196  	}
  1197  	if ctx.GlobalIsSet(InsecureUnlockAllowedFlag.Name) {
  1198  		cfg.InsecureUnlockAllowed = ctx.GlobalBool(InsecureUnlockAllowedFlag.Name)
  1199  	}
  1200  }
  1201  
  1202  func setSmartCard(ctx *cli.Context, cfg *node.Config) {
  1203  	// Skip enabling smartcards if no path is set
  1204  	path := ctx.GlobalString(SmartCardDaemonPathFlag.Name)
  1205  	if path == "" {
  1206  		return
  1207  	}
  1208  	// Sanity check that the smartcard path is valid
  1209  	fi, err := os.Stat(path)
  1210  	if err != nil {
  1211  		log.Info("Smartcard socket not found, disabling", "err", err)
  1212  		return
  1213  	}
  1214  	if fi.Mode()&os.ModeType != os.ModeSocket {
  1215  		log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String())
  1216  		return
  1217  	}
  1218  	// Smartcard daemon path exists and is a socket, enable it
  1219  	cfg.SmartCardDaemonPath = path
  1220  }
  1221  
  1222  func setDataDir(ctx *cli.Context, cfg *node.Config) {
  1223  	switch {
  1224  	case ctx.GlobalIsSet(DataDirFlag.Name):
  1225  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
  1226  	case ctx.GlobalBool(DeveloperFlag.Name):
  1227  		cfg.DataDir = "" // unless explicitly requested, use memory databases
  1228  	case ctx.GlobalBool(TestnetFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1229  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet")
  1230  	case ctx.GlobalBool(RinkebyFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1231  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
  1232  	case ctx.GlobalBool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1233  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli")
  1234  	}
  1235  }
  1236  
  1237  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
  1238  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
  1239  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
  1240  	}
  1241  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
  1242  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
  1243  	}
  1244  }
  1245  
  1246  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
  1247  	if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) {
  1248  		locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",")
  1249  		for _, account := range locals {
  1250  			if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
  1251  				Fatalf("Invalid account in --txpool.locals: %s", trimmed)
  1252  			} else {
  1253  				cfg.Locals = append(cfg.Locals, common.HexToAddress(account))
  1254  			}
  1255  		}
  1256  	}
  1257  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
  1258  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
  1259  	}
  1260  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
  1261  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
  1262  	}
  1263  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
  1264  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
  1265  	}
  1266  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
  1267  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
  1268  	}
  1269  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
  1270  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
  1271  	}
  1272  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
  1273  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
  1274  	}
  1275  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
  1276  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
  1277  	}
  1278  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
  1279  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
  1280  	}
  1281  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
  1282  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
  1283  	}
  1284  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
  1285  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
  1286  	}
  1287  }
  1288  
  1289  func setEthash(ctx *cli.Context, cfg *eth.Config) {
  1290  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
  1291  		cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
  1292  	}
  1293  	if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
  1294  		cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name)
  1295  	}
  1296  	if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) {
  1297  		cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name)
  1298  	}
  1299  	if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) {
  1300  		cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name)
  1301  	}
  1302  	if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) {
  1303  		cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name)
  1304  	}
  1305  	if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) {
  1306  		cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name)
  1307  	}
  1308  }
  1309  
  1310  func setMiner(ctx *cli.Context, cfg *miner.Config) {
  1311  	if ctx.GlobalIsSet(MinerNotifyFlag.Name) {
  1312  		cfg.Notify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",")
  1313  	}
  1314  	if ctx.GlobalIsSet(MinerLegacyExtraDataFlag.Name) {
  1315  		cfg.ExtraData = []byte(ctx.GlobalString(MinerLegacyExtraDataFlag.Name))
  1316  	}
  1317  	if ctx.GlobalIsSet(MinerExtraDataFlag.Name) {
  1318  		cfg.ExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name))
  1319  	}
  1320  	if ctx.GlobalIsSet(MinerLegacyGasTargetFlag.Name) {
  1321  		cfg.GasFloor = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name)
  1322  	}
  1323  	if ctx.GlobalIsSet(MinerGasTargetFlag.Name) {
  1324  		cfg.GasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name)
  1325  	}
  1326  	if ctx.GlobalIsSet(MinerGasLimitFlag.Name) {
  1327  		cfg.GasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name)
  1328  	}
  1329  	if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1330  		cfg.GasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name)
  1331  	}
  1332  	if ctx.GlobalIsSet(MinerGasPriceFlag.Name) {
  1333  		cfg.GasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name)
  1334  	}
  1335  	if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) {
  1336  		cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name)
  1337  	}
  1338  	if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) {
  1339  		cfg.Noverify = ctx.Bool(MinerNoVerfiyFlag.Name)
  1340  	}
  1341  }
  1342  
  1343  func setWhitelist(ctx *cli.Context, cfg *eth.Config) {
  1344  	whitelist := ctx.GlobalString(WhitelistFlag.Name)
  1345  	if whitelist == "" {
  1346  		return
  1347  	}
  1348  	cfg.Whitelist = make(map[uint64]common.Hash)
  1349  	for _, entry := range strings.Split(whitelist, ",") {
  1350  		parts := strings.Split(entry, "=")
  1351  		if len(parts) != 2 {
  1352  			Fatalf("Invalid whitelist entry: %s", entry)
  1353  		}
  1354  		number, err := strconv.ParseUint(parts[0], 0, 64)
  1355  		if err != nil {
  1356  			Fatalf("Invalid whitelist block number %s: %v", parts[0], err)
  1357  		}
  1358  		var hash common.Hash
  1359  		if err = hash.UnmarshalText([]byte(parts[1])); err != nil {
  1360  			Fatalf("Invalid whitelist hash %s: %v", parts[1], err)
  1361  		}
  1362  		cfg.Whitelist[number] = hash
  1363  	}
  1364  }
  1365  
  1366  // CheckExclusive verifies that only a single instance of the provided flags was
  1367  // set by the user. Each flag might optionally be followed by a string type to
  1368  // specialize it further.
  1369  func CheckExclusive(ctx *cli.Context, args ...interface{}) {
  1370  	set := make([]string, 0, 1)
  1371  	for i := 0; i < len(args); i++ {
  1372  		// Make sure the next argument is a flag and skip if not set
  1373  		flag, ok := args[i].(cli.Flag)
  1374  		if !ok {
  1375  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
  1376  		}
  1377  		// Check if next arg extends current and expand its name if so
  1378  		name := flag.GetName()
  1379  
  1380  		if i+1 < len(args) {
  1381  			switch option := args[i+1].(type) {
  1382  			case string:
  1383  				// Extended flag check, make sure value set doesn't conflict with passed in option
  1384  				if ctx.GlobalString(flag.GetName()) == option {
  1385  					name += "=" + option
  1386  					set = append(set, "--"+name)
  1387  				}
  1388  				// shift arguments and continue
  1389  				i++
  1390  				continue
  1391  
  1392  			case cli.Flag:
  1393  			default:
  1394  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
  1395  			}
  1396  		}
  1397  		// Mark the flag if it's set
  1398  		if ctx.GlobalIsSet(flag.GetName()) {
  1399  			set = append(set, "--"+name)
  1400  		}
  1401  	}
  1402  	if len(set) > 1 {
  1403  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
  1404  	}
  1405  }
  1406  
  1407  // SetShhConfig applies shh-related command line flags to the config.
  1408  func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
  1409  	if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) {
  1410  		cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name))
  1411  	}
  1412  	if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) {
  1413  		cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name)
  1414  	}
  1415  	if ctx.GlobalIsSet(WhisperRestrictConnectionBetweenLightClientsFlag.Name) {
  1416  		cfg.RestrictConnectionBetweenLightClients = true
  1417  	}
  1418  }
  1419  
  1420  // SetEthConfig applies eth-related command line flags to the config.
  1421  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
  1422  	// Avoid conflicting network flags
  1423  	CheckExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag, GoerliFlag)
  1424  	CheckExclusive(ctx, LightLegacyServFlag, LightServeFlag, SyncModeFlag, "light")
  1425  	CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
  1426  
  1427  	var ks *keystore.KeyStore
  1428  	if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
  1429  		ks = keystores[0].(*keystore.KeyStore)
  1430  	}
  1431  	setEtherbase(ctx, ks, cfg)
  1432  	setGPO(ctx, &cfg.GPO)
  1433  	setTxPool(ctx, &cfg.TxPool)
  1434  	setEthash(ctx, cfg)
  1435  	setMiner(ctx, &cfg.Miner)
  1436  	setWhitelist(ctx, cfg)
  1437  	setLes(ctx, cfg)
  1438  
  1439  	if ctx.GlobalIsSet(SyncModeFlag.Name) {
  1440  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
  1441  	}
  1442  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1443  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1444  	}
  1445  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
  1446  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1447  	}
  1448  	cfg.DatabaseHandles = makeDatabaseHandles()
  1449  	if ctx.GlobalIsSet(AncientFlag.Name) {
  1450  		cfg.DatabaseFreezer = ctx.GlobalString(AncientFlag.Name)
  1451  	}
  1452  
  1453  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1454  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1455  	}
  1456  	if ctx.GlobalIsSet(GCModeFlag.Name) {
  1457  		cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
  1458  	}
  1459  	if ctx.GlobalIsSet(CacheNoPrefetchFlag.Name) {
  1460  		cfg.NoPrefetch = ctx.GlobalBool(CacheNoPrefetchFlag.Name)
  1461  	}
  1462  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
  1463  		cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100
  1464  	}
  1465  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1466  		cfg.TrieDirtyCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1467  	}
  1468  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1469  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1470  	}
  1471  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1472  		// TODO(fjl): force-enable this in --dev mode
  1473  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1474  	}
  1475  
  1476  	if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) {
  1477  		cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name)
  1478  	}
  1479  
  1480  	if ctx.GlobalIsSet(EVMInterpreterFlag.Name) {
  1481  		cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name)
  1482  	}
  1483  	if ctx.GlobalIsSet(RPCGlobalGasCap.Name) {
  1484  		cfg.RPCGasCap = new(big.Int).SetUint64(ctx.GlobalUint64(RPCGlobalGasCap.Name))
  1485  	}
  1486  
  1487  	// Override any default configs for hard coded networks.
  1488  	switch {
  1489  	case ctx.GlobalBool(TestnetFlag.Name):
  1490  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1491  			cfg.NetworkId = 3
  1492  		}
  1493  		cfg.Genesis = core.DefaultTestnetGenesisBlock()
  1494  	case ctx.GlobalBool(RinkebyFlag.Name):
  1495  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1496  			cfg.NetworkId = 4
  1497  		}
  1498  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1499  	case ctx.GlobalBool(GoerliFlag.Name):
  1500  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1501  			cfg.NetworkId = 5
  1502  		}
  1503  		cfg.Genesis = core.DefaultGoerliGenesisBlock()
  1504  	case ctx.GlobalBool(DeveloperFlag.Name):
  1505  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1506  			cfg.NetworkId = 1337
  1507  		}
  1508  		// Create new developer account or reuse existing one
  1509  		var (
  1510  			developer accounts.Account
  1511  			err       error
  1512  		)
  1513  		if accs := ks.Accounts(); len(accs) > 0 {
  1514  			developer = ks.Accounts()[0]
  1515  		} else {
  1516  			developer, err = ks.NewAccount("")
  1517  			if err != nil {
  1518  				Fatalf("Failed to create developer account: %v", err)
  1519  			}
  1520  		}
  1521  		if err := ks.Unlock(developer, ""); err != nil {
  1522  			Fatalf("Failed to unlock developer account: %v", err)
  1523  		}
  1524  		log.Info("Using developer account", "address", developer.Address)
  1525  
  1526  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
  1527  		if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1528  			cfg.Miner.GasPrice = big.NewInt(1)
  1529  		}
  1530  	}
  1531  }
  1532  
  1533  // SetDashboardConfig applies dashboard related command line flags to the config.
  1534  func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
  1535  	cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name)
  1536  	cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name)
  1537  	cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
  1538  }
  1539  
  1540  // RegisterEthService adds an Ethereum client to the stack.
  1541  func RegisterEthService(stack *node.Node, cfg *eth.Config) {
  1542  	var err error
  1543  	if cfg.SyncMode == downloader.LightSync {
  1544  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1545  			return les.New(ctx, cfg)
  1546  		})
  1547  	} else {
  1548  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1549  			fullNode, err := eth.New(ctx, cfg)
  1550  			if fullNode != nil && cfg.LightServ > 0 {
  1551  				ls, _ := les.NewLesServer(fullNode, cfg)
  1552  				fullNode.AddLesServer(ls)
  1553  			}
  1554  			return fullNode, err
  1555  		})
  1556  	}
  1557  	if err != nil {
  1558  		Fatalf("Failed to register the Ethereum service: %v", err)
  1559  	}
  1560  }
  1561  
  1562  // RegisterDashboardService adds a dashboard to the stack.
  1563  func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
  1564  	stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1565  		return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil
  1566  	})
  1567  }
  1568  
  1569  // RegisterShhService configures Whisper and adds it to the given node.
  1570  func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
  1571  	if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
  1572  		return whisper.New(cfg), nil
  1573  	}); err != nil {
  1574  		Fatalf("Failed to register the Whisper service: %v", err)
  1575  	}
  1576  }
  1577  
  1578  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  1579  // the given node.
  1580  func RegisterEthStatsService(stack *node.Node, url string) {
  1581  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1582  		// Retrieve both eth and les services
  1583  		var ethServ *eth.Ethereum
  1584  		ctx.Service(&ethServ)
  1585  
  1586  		var lesServ *les.LightEthereum
  1587  		ctx.Service(&lesServ)
  1588  
  1589  		// Let ethstats use whichever is not nil
  1590  		return ethstats.New(url, ethServ, lesServ)
  1591  	}); err != nil {
  1592  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  1593  	}
  1594  }
  1595  
  1596  // RegisterGraphQLService is a utility function to construct a new service and register it against a node.
  1597  func RegisterGraphQLService(stack *node.Node, endpoint string, cors, vhosts []string, timeouts rpc.HTTPTimeouts) {
  1598  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1599  		// Try to construct the GraphQL service backed by a full node
  1600  		var ethServ *eth.Ethereum
  1601  		if err := ctx.Service(&ethServ); err == nil {
  1602  			return graphql.New(ethServ.APIBackend, endpoint, cors, vhosts, timeouts)
  1603  		}
  1604  		// Try to construct the GraphQL service backed by a light node
  1605  		var lesServ *les.LightEthereum
  1606  		if err := ctx.Service(&lesServ); err == nil {
  1607  			return graphql.New(lesServ.ApiBackend, endpoint, cors, vhosts, timeouts)
  1608  		}
  1609  		// Well, this should not have happened, bail out
  1610  		return nil, errors.New("no Ethereum service")
  1611  	}); err != nil {
  1612  		Fatalf("Failed to register the GraphQL service: %v", err)
  1613  	}
  1614  }
  1615  
  1616  func SetupMetrics(ctx *cli.Context) {
  1617  	if metrics.Enabled {
  1618  		log.Info("Enabling metrics collection")
  1619  		var (
  1620  			enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name)
  1621  			endpoint     = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name)
  1622  			database     = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name)
  1623  			username     = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name)
  1624  			password     = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name)
  1625  		)
  1626  
  1627  		if enableExport {
  1628  			tagsMap := SplitTagsFlag(ctx.GlobalString(MetricsInfluxDBTagsFlag.Name))
  1629  
  1630  			log.Info("Enabling metrics export to InfluxDB")
  1631  
  1632  			go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap)
  1633  		}
  1634  	}
  1635  }
  1636  
  1637  func SplitTagsFlag(tagsFlag string) map[string]string {
  1638  	tags := strings.Split(tagsFlag, ",")
  1639  	tagsMap := map[string]string{}
  1640  
  1641  	for _, t := range tags {
  1642  		if t != "" {
  1643  			kv := strings.Split(t, "=")
  1644  
  1645  			if len(kv) == 2 {
  1646  				tagsMap[kv[0]] = kv[1]
  1647  			}
  1648  		}
  1649  	}
  1650  
  1651  	return tagsMap
  1652  }
  1653  
  1654  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1655  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
  1656  	var (
  1657  		cache   = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1658  		handles = makeDatabaseHandles()
  1659  	)
  1660  	name := "chaindata"
  1661  	if ctx.GlobalString(SyncModeFlag.Name) == "light" {
  1662  		name = "lightchaindata"
  1663  	}
  1664  	chainDb, err := stack.OpenDatabaseWithFreezer(name, cache, handles, ctx.GlobalString(AncientFlag.Name), "")
  1665  	if err != nil {
  1666  		Fatalf("Could not open database: %v", err)
  1667  	}
  1668  	return chainDb
  1669  }
  1670  
  1671  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1672  	var genesis *core.Genesis
  1673  	switch {
  1674  	case ctx.GlobalBool(TestnetFlag.Name):
  1675  		genesis = core.DefaultTestnetGenesisBlock()
  1676  	case ctx.GlobalBool(RinkebyFlag.Name):
  1677  		genesis = core.DefaultRinkebyGenesisBlock()
  1678  	case ctx.GlobalBool(GoerliFlag.Name):
  1679  		genesis = core.DefaultGoerliGenesisBlock()
  1680  	case ctx.GlobalBool(DeveloperFlag.Name):
  1681  		Fatalf("Developer chains are ephemeral")
  1682  	}
  1683  	return genesis
  1684  }
  1685  
  1686  // MakeChain creates a chain manager from set command line flags.
  1687  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
  1688  	var err error
  1689  	chainDb = MakeChainDatabase(ctx, stack)
  1690  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  1691  	if err != nil {
  1692  		Fatalf("%v", err)
  1693  	}
  1694  	var engine consensus.Engine
  1695  	if config.Clique != nil {
  1696  		engine = clique.New(config.Clique, chainDb)
  1697  	} else {
  1698  		engine = ethash.NewFaker()
  1699  		if !ctx.GlobalBool(FakePoWFlag.Name) {
  1700  			engine = ethash.New(ethash.Config{
  1701  				CacheDir:       stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
  1702  				CachesInMem:    eth.DefaultConfig.Ethash.CachesInMem,
  1703  				CachesOnDisk:   eth.DefaultConfig.Ethash.CachesOnDisk,
  1704  				DatasetDir:     stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
  1705  				DatasetsInMem:  eth.DefaultConfig.Ethash.DatasetsInMem,
  1706  				DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
  1707  			}, nil, false)
  1708  		}
  1709  	}
  1710  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1711  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1712  	}
  1713  	cache := &core.CacheConfig{
  1714  		TrieCleanLimit:      eth.DefaultConfig.TrieCleanCache,
  1715  		TrieCleanNoPrefetch: ctx.GlobalBool(CacheNoPrefetchFlag.Name),
  1716  		TrieDirtyLimit:      eth.DefaultConfig.TrieDirtyCache,
  1717  		TrieDirtyDisabled:   ctx.GlobalString(GCModeFlag.Name) == "archive",
  1718  		TrieTimeLimit:       eth.DefaultConfig.TrieTimeout,
  1719  	}
  1720  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
  1721  		cache.TrieCleanLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100
  1722  	}
  1723  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1724  		cache.TrieDirtyLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1725  	}
  1726  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  1727  	chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil)
  1728  	if err != nil {
  1729  		Fatalf("Can't create BlockChain: %v", err)
  1730  	}
  1731  	return chain, chainDb
  1732  }
  1733  
  1734  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1735  // scripts to preload before starting.
  1736  func MakeConsolePreloads(ctx *cli.Context) []string {
  1737  	// Skip preloading if there's nothing to preload
  1738  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1739  		return nil
  1740  	}
  1741  	// Otherwise resolve absolute paths and return them
  1742  	var preloads []string
  1743  
  1744  	assets := ctx.GlobalString(JSpathFlag.Name)
  1745  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1746  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
  1747  	}
  1748  	return preloads
  1749  }
  1750  
  1751  // MigrateFlags sets the global flag from a local flag when it's set.
  1752  // This is a temporary function used for migrating old command/flags to the
  1753  // new format.
  1754  //
  1755  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  1756  //
  1757  // is equivalent after calling this method with:
  1758  //
  1759  // geth --keystore /tmp/mykeystore --lightkdf account new
  1760  //
  1761  // This allows the use of the existing configuration functionality.
  1762  // When all flags are migrated this function can be removed and the existing
  1763  // configuration functionality must be changed that is uses local flags
  1764  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1765  	return func(ctx *cli.Context) error {
  1766  		for _, name := range ctx.FlagNames() {
  1767  			if ctx.IsSet(name) {
  1768  				ctx.GlobalSet(name, ctx.String(name))
  1769  			}
  1770  		}
  1771  		return action(ctx)
  1772  	}
  1773  }