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