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