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