github.com/notegio/go-ethereum@v1.9.5-4/cmd/utils/flags.go (about)

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