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