github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/cmd/utils/flags.go (about)

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