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