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