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