github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/cmd/utils/flags.go (about)

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