github.com/aidoskuneen/adk-node@v0.0.0-20220315131952-2e32567cb7f4/cmd/utils/flags.go (about)

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