github.com/ethxdao/go-ethereum@v0.0.0-20221218102228-5ae34a9cc189/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/ethxdao/go-ethereum/accounts"
    33  	"github.com/ethxdao/go-ethereum/accounts/keystore"
    34  	"github.com/ethxdao/go-ethereum/common"
    35  	"github.com/ethxdao/go-ethereum/common/fdlimit"
    36  	"github.com/ethxdao/go-ethereum/consensus"
    37  	"github.com/ethxdao/go-ethereum/consensus/ethash"
    38  	"github.com/ethxdao/go-ethereum/core"
    39  	"github.com/ethxdao/go-ethereum/core/rawdb"
    40  	"github.com/ethxdao/go-ethereum/core/vm"
    41  	"github.com/ethxdao/go-ethereum/crypto"
    42  	"github.com/ethxdao/go-ethereum/eth"
    43  	ethcatalyst "github.com/ethxdao/go-ethereum/eth/catalyst"
    44  	"github.com/ethxdao/go-ethereum/eth/downloader"
    45  	"github.com/ethxdao/go-ethereum/eth/ethconfig"
    46  	"github.com/ethxdao/go-ethereum/eth/filters"
    47  	"github.com/ethxdao/go-ethereum/eth/gasprice"
    48  	"github.com/ethxdao/go-ethereum/eth/tracers"
    49  	"github.com/ethxdao/go-ethereum/ethdb"
    50  	"github.com/ethxdao/go-ethereum/ethdb/remotedb"
    51  	"github.com/ethxdao/go-ethereum/ethstats"
    52  	"github.com/ethxdao/go-ethereum/graphql"
    53  	"github.com/ethxdao/go-ethereum/internal/ethapi"
    54  	"github.com/ethxdao/go-ethereum/internal/flags"
    55  	"github.com/ethxdao/go-ethereum/les"
    56  	lescatalyst "github.com/ethxdao/go-ethereum/les/catalyst"
    57  	"github.com/ethxdao/go-ethereum/log"
    58  	"github.com/ethxdao/go-ethereum/metrics"
    59  	"github.com/ethxdao/go-ethereum/metrics/exp"
    60  	"github.com/ethxdao/go-ethereum/metrics/influxdb"
    61  	"github.com/ethxdao/go-ethereum/miner"
    62  	"github.com/ethxdao/go-ethereum/node"
    63  	"github.com/ethxdao/go-ethereum/p2p"
    64  	"github.com/ethxdao/go-ethereum/p2p/enode"
    65  	"github.com/ethxdao/go-ethereum/p2p/nat"
    66  	"github.com/ethxdao/go-ethereum/p2p/netutil"
    67  	"github.com/ethxdao/go-ethereum/params"
    68  	"github.com/ethxdao/go-ethereum/rpc"
    69  	pcsclite "github.com/gballet/go-libpcsclite"
    70  	gopsutil "github.com/shirou/gopsutil/mem"
    71  )
    72  
    73  // These are all the command line flags we support.
    74  // If you add to this list, please remember to include the
    75  // flag in the appropriate command definition.
    76  //
    77  // The flags are defined here so their names and help texts
    78  // are the same for all commands.
    79  
    80  var (
    81  	// General settings
    82  	DataDirFlag = &flags.DirectoryFlag{
    83  		Name:     "datadir",
    84  		Usage:    "Data directory for the databases and keystore",
    85  		Value:    flags.DirectoryString(node.DefaultDataDir()),
    86  		Category: flags.EthCategory,
    87  	}
    88  	RemoteDBFlag = &cli.StringFlag{
    89  		Name:     "remotedb",
    90  		Usage:    "URL for remote database",
    91  		Category: flags.LoggingCategory,
    92  	}
    93  	AncientFlag = &flags.DirectoryFlag{
    94  		Name:     "datadir.ancient",
    95  		Usage:    "Root directory for ancient data (default = inside chaindata)",
    96  		Category: flags.EthCategory,
    97  	}
    98  	MinFreeDiskSpaceFlag = &flags.DirectoryFlag{
    99  		Name:     "datadir.minfreedisk",
   100  		Usage:    "Minimum free disk space in MB, once reached triggers auto shut down (default = --cache.gc converted to MB, 0 = disabled)",
   101  		Category: flags.EthCategory,
   102  	}
   103  	KeyStoreDirFlag = &flags.DirectoryFlag{
   104  		Name:     "keystore",
   105  		Usage:    "Directory for the keystore (default = inside the datadir)",
   106  		Category: flags.AccountCategory,
   107  	}
   108  	USBFlag = &cli.BoolFlag{
   109  		Name:     "usb",
   110  		Usage:    "Enable monitoring and management of USB hardware wallets",
   111  		Category: flags.AccountCategory,
   112  	}
   113  	SmartCardDaemonPathFlag = &cli.StringFlag{
   114  		Name:     "pcscdpath",
   115  		Usage:    "Path to the smartcard daemon (pcscd) socket file",
   116  		Value:    pcsclite.PCSCDSockName,
   117  		Category: flags.AccountCategory,
   118  	}
   119  	NetworkIdFlag = &cli.Uint64Flag{
   120  		Name:     "networkid",
   121  		Usage:    "Explicitly set network id (integer)(For testnets: use --ropsten, --rinkeby, --goerli instead)",
   122  		Value:    ethconfig.Defaults.NetworkId,
   123  		Category: flags.EthCategory,
   124  	}
   125  	MainnetFlag = &cli.BoolFlag{
   126  		Name:     "mainnet",
   127  		Usage:    "Ethereum mainnet",
   128  		Category: flags.EthCategory,
   129  	}
   130  	RopstenFlag = &cli.BoolFlag{
   131  		Name:     "ropsten",
   132  		Usage:    "Ropsten network: pre-configured proof-of-stake test network",
   133  		Category: flags.EthCategory,
   134  	}
   135  	RinkebyFlag = &cli.BoolFlag{
   136  		Name:     "rinkeby",
   137  		Usage:    "Rinkeby network: pre-configured proof-of-authority test network",
   138  		Category: flags.EthCategory,
   139  	}
   140  	GoerliFlag = &cli.BoolFlag{
   141  		Name:     "goerli",
   142  		Usage:    "Görli network: pre-configured proof-of-authority test network",
   143  		Category: flags.EthCategory,
   144  	}
   145  	SepoliaFlag = &cli.BoolFlag{
   146  		Name:     "sepolia",
   147  		Usage:    "Sepolia network: pre-configured proof-of-work test network",
   148  		Category: flags.EthCategory,
   149  	}
   150  	KilnFlag = &cli.BoolFlag{
   151  		Name:     "kiln",
   152  		Usage:    "Kiln network: pre-configured proof-of-work to proof-of-stake test network",
   153  		Category: flags.EthCategory,
   154  	}
   155  
   156  	// Dev mode
   157  	DeveloperFlag = &cli.BoolFlag{
   158  		Name:     "dev",
   159  		Usage:    "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
   160  		Category: flags.DevCategory,
   161  	}
   162  	DeveloperPeriodFlag = &cli.IntFlag{
   163  		Name:     "dev.period",
   164  		Usage:    "Block period to use in developer mode (0 = mine only if transaction pending)",
   165  		Category: flags.DevCategory,
   166  	}
   167  	DeveloperGasLimitFlag = &cli.Uint64Flag{
   168  		Name:     "dev.gaslimit",
   169  		Usage:    "Initial block gas limit",
   170  		Value:    11500000,
   171  		Category: flags.DevCategory,
   172  	}
   173  
   174  	IdentityFlag = &cli.StringFlag{
   175  		Name:     "identity",
   176  		Usage:    "Custom node name",
   177  		Category: flags.NetworkingCategory,
   178  	}
   179  	DocRootFlag = &flags.DirectoryFlag{
   180  		Name:     "docroot",
   181  		Usage:    "Document Root for HTTPClient file scheme",
   182  		Value:    flags.DirectoryString(flags.HomeDir()),
   183  		Category: flags.APICategory,
   184  	}
   185  	ExitWhenSyncedFlag = &cli.BoolFlag{
   186  		Name:     "exitwhensynced",
   187  		Usage:    "Exits after block synchronisation completes",
   188  		Category: flags.EthCategory,
   189  	}
   190  
   191  	// Dump command options.
   192  	IterativeOutputFlag = &cli.BoolFlag{
   193  		Name:  "iterative",
   194  		Usage: "Print streaming JSON iteratively, delimited by newlines",
   195  		Value: true,
   196  	}
   197  	ExcludeStorageFlag = &cli.BoolFlag{
   198  		Name:  "nostorage",
   199  		Usage: "Exclude storage entries (save db lookups)",
   200  	}
   201  	IncludeIncompletesFlag = &cli.BoolFlag{
   202  		Name:  "incompletes",
   203  		Usage: "Include accounts for which we don't have the address (missing preimage)",
   204  	}
   205  	ExcludeCodeFlag = &cli.BoolFlag{
   206  		Name:  "nocode",
   207  		Usage: "Exclude contract code (save db lookups)",
   208  	}
   209  	StartKeyFlag = &cli.StringFlag{
   210  		Name:  "start",
   211  		Usage: "Start position. Either a hash or address",
   212  		Value: "0x0000000000000000000000000000000000000000000000000000000000000000",
   213  	}
   214  	DumpLimitFlag = &cli.Uint64Flag{
   215  		Name:  "limit",
   216  		Usage: "Max number of elements (0 = no limit)",
   217  		Value: 0,
   218  	}
   219  
   220  	defaultSyncMode = ethconfig.Defaults.SyncMode
   221  	SyncModeFlag    = &flags.TextMarshalerFlag{
   222  		Name:     "syncmode",
   223  		Usage:    `Blockchain sync mode ("snap", "full" or "light")`,
   224  		Value:    &defaultSyncMode,
   225  		Category: flags.EthCategory,
   226  	}
   227  	GCModeFlag = &cli.StringFlag{
   228  		Name:     "gcmode",
   229  		Usage:    `Blockchain garbage collection mode ("full", "archive")`,
   230  		Value:    "full",
   231  		Category: flags.EthCategory,
   232  	}
   233  	SnapshotFlag = &cli.BoolFlag{
   234  		Name:     "snapshot",
   235  		Usage:    `Enables snapshot-database mode (default = enable)`,
   236  		Value:    true,
   237  		Category: flags.EthCategory,
   238  	}
   239  	TxLookupLimitFlag = &cli.Uint64Flag{
   240  		Name:     "txlookuplimit",
   241  		Usage:    "Number of recent blocks to maintain transactions index for (default = about one year, 0 = entire chain)",
   242  		Value:    ethconfig.Defaults.TxLookupLimit,
   243  		Category: flags.EthCategory,
   244  	}
   245  	LightKDFFlag = &cli.BoolFlag{
   246  		Name:     "lightkdf",
   247  		Usage:    "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   248  		Category: flags.AccountCategory,
   249  	}
   250  	EthRequiredBlocksFlag = &cli.StringFlag{
   251  		Name:     "eth.requiredblocks",
   252  		Usage:    "Comma separated block number-to-hash mappings to require for peering (<number>=<hash>)",
   253  		Category: flags.EthCategory,
   254  	}
   255  	LegacyWhitelistFlag = &cli.StringFlag{
   256  		Name:     "whitelist",
   257  		Usage:    "Comma separated block number-to-hash mappings to enforce (<number>=<hash>) (deprecated in favor of --eth.requiredblocks)",
   258  		Category: flags.DeprecatedCategory,
   259  	}
   260  	BloomFilterSizeFlag = &cli.Uint64Flag{
   261  		Name:     "bloomfilter.size",
   262  		Usage:    "Megabytes of memory allocated to bloom-filter for pruning",
   263  		Value:    2048,
   264  		Category: flags.EthCategory,
   265  	}
   266  	OverrideTerminalTotalDifficulty = &flags.BigFlag{
   267  		Name:     "override.terminaltotaldifficulty",
   268  		Usage:    "Manually specify TerminalTotalDifficulty, overriding the bundled setting",
   269  		Category: flags.EthCategory,
   270  	}
   271  	OverrideTerminalTotalDifficultyPassed = &cli.BoolFlag{
   272  		Name:     "override.terminaltotaldifficultypassed",
   273  		Usage:    "Manually specify TerminalTotalDifficultyPassed, overriding the bundled setting",
   274  		Category: flags.EthCategory,
   275  	}
   276  	// Light server and client settings
   277  	LightServeFlag = &cli.IntFlag{
   278  		Name:     "light.serve",
   279  		Usage:    "Maximum percentage of time allowed for serving LES requests (multi-threaded processing allows values over 100)",
   280  		Value:    ethconfig.Defaults.LightServ,
   281  		Category: flags.LightCategory,
   282  	}
   283  	LightIngressFlag = &cli.IntFlag{
   284  		Name:     "light.ingress",
   285  		Usage:    "Incoming bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)",
   286  		Value:    ethconfig.Defaults.LightIngress,
   287  		Category: flags.LightCategory,
   288  	}
   289  	LightEgressFlag = &cli.IntFlag{
   290  		Name:     "light.egress",
   291  		Usage:    "Outgoing bandwidth limit for serving light clients (kilobytes/sec, 0 = unlimited)",
   292  		Value:    ethconfig.Defaults.LightEgress,
   293  		Category: flags.LightCategory,
   294  	}
   295  	LightMaxPeersFlag = &cli.IntFlag{
   296  		Name:     "light.maxpeers",
   297  		Usage:    "Maximum number of light clients to serve, or light servers to attach to",
   298  		Value:    ethconfig.Defaults.LightPeers,
   299  		Category: flags.LightCategory,
   300  	}
   301  	UltraLightServersFlag = &cli.StringFlag{
   302  		Name:     "ulc.servers",
   303  		Usage:    "List of trusted ultra-light servers",
   304  		Value:    strings.Join(ethconfig.Defaults.UltraLightServers, ","),
   305  		Category: flags.LightCategory,
   306  	}
   307  	UltraLightFractionFlag = &cli.IntFlag{
   308  		Name:     "ulc.fraction",
   309  		Usage:    "Minimum % of trusted ultra-light servers required to announce a new head",
   310  		Value:    ethconfig.Defaults.UltraLightFraction,
   311  		Category: flags.LightCategory,
   312  	}
   313  	UltraLightOnlyAnnounceFlag = &cli.BoolFlag{
   314  		Name:     "ulc.onlyannounce",
   315  		Usage:    "Ultra light server sends announcements only",
   316  		Category: flags.LightCategory,
   317  	}
   318  	LightNoPruneFlag = &cli.BoolFlag{
   319  		Name:     "light.nopruning",
   320  		Usage:    "Disable ancient light chain data pruning",
   321  		Category: flags.LightCategory,
   322  	}
   323  	LightNoSyncServeFlag = &cli.BoolFlag{
   324  		Name:     "light.nosyncserve",
   325  		Usage:    "Enables serving light clients before syncing",
   326  		Category: flags.LightCategory,
   327  	}
   328  
   329  	// Ethash settings
   330  	EthashCacheDirFlag = &flags.DirectoryFlag{
   331  		Name:     "ethash.cachedir",
   332  		Usage:    "Directory to store the ethash verification caches (default = inside the datadir)",
   333  		Category: flags.EthashCategory,
   334  	}
   335  	EthashCachesInMemoryFlag = &cli.IntFlag{
   336  		Name:     "ethash.cachesinmem",
   337  		Usage:    "Number of recent ethash caches to keep in memory (16MB each)",
   338  		Value:    ethconfig.Defaults.Ethash.CachesInMem,
   339  		Category: flags.EthashCategory,
   340  	}
   341  	EthashCachesOnDiskFlag = &cli.IntFlag{
   342  		Name:     "ethash.cachesondisk",
   343  		Usage:    "Number of recent ethash caches to keep on disk (16MB each)",
   344  		Value:    ethconfig.Defaults.Ethash.CachesOnDisk,
   345  		Category: flags.EthashCategory,
   346  	}
   347  	EthashCachesLockMmapFlag = &cli.BoolFlag{
   348  		Name:     "ethash.cacheslockmmap",
   349  		Usage:    "Lock memory maps of recent ethash caches",
   350  		Category: flags.EthashCategory,
   351  	}
   352  	EthashDatasetDirFlag = &flags.DirectoryFlag{
   353  		Name:     "ethash.dagdir",
   354  		Usage:    "Directory to store the ethash mining DAGs",
   355  		Value:    flags.DirectoryString(ethconfig.Defaults.Ethash.DatasetDir),
   356  		Category: flags.EthashCategory,
   357  	}
   358  	EthashDatasetsInMemoryFlag = &cli.IntFlag{
   359  		Name:     "ethash.dagsinmem",
   360  		Usage:    "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
   361  		Value:    ethconfig.Defaults.Ethash.DatasetsInMem,
   362  		Category: flags.EthashCategory,
   363  	}
   364  	EthashDatasetsOnDiskFlag = &cli.IntFlag{
   365  		Name:     "ethash.dagsondisk",
   366  		Usage:    "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
   367  		Value:    ethconfig.Defaults.Ethash.DatasetsOnDisk,
   368  		Category: flags.EthashCategory,
   369  	}
   370  	EthashDatasetsLockMmapFlag = &cli.BoolFlag{
   371  		Name:     "ethash.dagslockmmap",
   372  		Usage:    "Lock memory maps for recent ethash mining DAGs",
   373  		Category: flags.EthashCategory,
   374  	}
   375  
   376  	// Transaction pool settings
   377  	TxPoolLocalsFlag = &cli.StringFlag{
   378  		Name:     "txpool.locals",
   379  		Usage:    "Comma separated accounts to treat as locals (no flush, priority inclusion)",
   380  		Category: flags.TxPoolCategory,
   381  	}
   382  	TxPoolNoLocalsFlag = &cli.BoolFlag{
   383  		Name:     "txpool.nolocals",
   384  		Usage:    "Disables price exemptions for locally submitted transactions",
   385  		Category: flags.TxPoolCategory,
   386  	}
   387  	TxPoolJournalFlag = &cli.StringFlag{
   388  		Name:     "txpool.journal",
   389  		Usage:    "Disk journal for local transaction to survive node restarts",
   390  		Value:    core.DefaultTxPoolConfig.Journal,
   391  		Category: flags.TxPoolCategory,
   392  	}
   393  	TxPoolRejournalFlag = &cli.DurationFlag{
   394  		Name:     "txpool.rejournal",
   395  		Usage:    "Time interval to regenerate the local transaction journal",
   396  		Value:    core.DefaultTxPoolConfig.Rejournal,
   397  		Category: flags.TxPoolCategory,
   398  	}
   399  	TxPoolPriceLimitFlag = &cli.Uint64Flag{
   400  		Name:     "txpool.pricelimit",
   401  		Usage:    "Minimum gas price limit to enforce for acceptance into the pool",
   402  		Value:    ethconfig.Defaults.TxPool.PriceLimit,
   403  		Category: flags.TxPoolCategory,
   404  	}
   405  	TxPoolPriceBumpFlag = &cli.Uint64Flag{
   406  		Name:     "txpool.pricebump",
   407  		Usage:    "Price bump percentage to replace an already existing transaction",
   408  		Value:    ethconfig.Defaults.TxPool.PriceBump,
   409  		Category: flags.TxPoolCategory,
   410  	}
   411  	TxPoolAccountSlotsFlag = &cli.Uint64Flag{
   412  		Name:     "txpool.accountslots",
   413  		Usage:    "Minimum number of executable transaction slots guaranteed per account",
   414  		Value:    ethconfig.Defaults.TxPool.AccountSlots,
   415  		Category: flags.TxPoolCategory,
   416  	}
   417  	TxPoolGlobalSlotsFlag = &cli.Uint64Flag{
   418  		Name:     "txpool.globalslots",
   419  		Usage:    "Maximum number of executable transaction slots for all accounts",
   420  		Value:    ethconfig.Defaults.TxPool.GlobalSlots,
   421  		Category: flags.TxPoolCategory,
   422  	}
   423  	TxPoolAccountQueueFlag = &cli.Uint64Flag{
   424  		Name:     "txpool.accountqueue",
   425  		Usage:    "Maximum number of non-executable transaction slots permitted per account",
   426  		Value:    ethconfig.Defaults.TxPool.AccountQueue,
   427  		Category: flags.TxPoolCategory,
   428  	}
   429  	TxPoolGlobalQueueFlag = &cli.Uint64Flag{
   430  		Name:     "txpool.globalqueue",
   431  		Usage:    "Maximum number of non-executable transaction slots for all accounts",
   432  		Value:    ethconfig.Defaults.TxPool.GlobalQueue,
   433  		Category: flags.TxPoolCategory,
   434  	}
   435  	TxPoolLifetimeFlag = &cli.DurationFlag{
   436  		Name:     "txpool.lifetime",
   437  		Usage:    "Maximum amount of time non-executable transaction are queued",
   438  		Value:    ethconfig.Defaults.TxPool.Lifetime,
   439  		Category: flags.TxPoolCategory,
   440  	}
   441  
   442  	// Performance tuning settings
   443  	CacheFlag = &cli.IntFlag{
   444  		Name:     "cache",
   445  		Usage:    "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node, 128 light mode)",
   446  		Value:    1024,
   447  		Category: flags.PerfCategory,
   448  	}
   449  	CacheDatabaseFlag = &cli.IntFlag{
   450  		Name:     "cache.database",
   451  		Usage:    "Percentage of cache memory allowance to use for database io",
   452  		Value:    50,
   453  		Category: flags.PerfCategory,
   454  	}
   455  	CacheTrieFlag = &cli.IntFlag{
   456  		Name:     "cache.trie",
   457  		Usage:    "Percentage of cache memory allowance to use for trie caching (default = 15% full mode, 30% archive mode)",
   458  		Value:    15,
   459  		Category: flags.PerfCategory,
   460  	}
   461  	CacheTrieJournalFlag = &cli.StringFlag{
   462  		Name:     "cache.trie.journal",
   463  		Usage:    "Disk journal directory for trie cache to survive node restarts",
   464  		Value:    ethconfig.Defaults.TrieCleanCacheJournal,
   465  		Category: flags.PerfCategory,
   466  	}
   467  	CacheTrieRejournalFlag = &cli.DurationFlag{
   468  		Name:     "cache.trie.rejournal",
   469  		Usage:    "Time interval to regenerate the trie cache journal",
   470  		Value:    ethconfig.Defaults.TrieCleanCacheRejournal,
   471  		Category: flags.PerfCategory,
   472  	}
   473  	CacheGCFlag = &cli.IntFlag{
   474  		Name:     "cache.gc",
   475  		Usage:    "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
   476  		Value:    25,
   477  		Category: flags.PerfCategory,
   478  	}
   479  	CacheSnapshotFlag = &cli.IntFlag{
   480  		Name:     "cache.snapshot",
   481  		Usage:    "Percentage of cache memory allowance to use for snapshot caching (default = 10% full mode, 20% archive mode)",
   482  		Value:    10,
   483  		Category: flags.PerfCategory,
   484  	}
   485  	CacheNoPrefetchFlag = &cli.BoolFlag{
   486  		Name:     "cache.noprefetch",
   487  		Usage:    "Disable heuristic state prefetch during block import (less CPU and disk IO, more time waiting for data)",
   488  		Category: flags.PerfCategory,
   489  	}
   490  	CachePreimagesFlag = &cli.BoolFlag{
   491  		Name:     "cache.preimages",
   492  		Usage:    "Enable recording the SHA3/keccak preimages of trie keys",
   493  		Category: flags.PerfCategory,
   494  	}
   495  	CacheLogSizeFlag = &cli.IntFlag{
   496  		Name:     "cache.blocklogs",
   497  		Usage:    "Size (in number of blocks) of the log cache for filtering",
   498  		Category: flags.PerfCategory,
   499  		Value:    ethconfig.Defaults.FilterLogCacheSize,
   500  	}
   501  	FDLimitFlag = &cli.IntFlag{
   502  		Name:     "fdlimit",
   503  		Usage:    "Raise the open file descriptor resource limit (default = system fd limit)",
   504  		Category: flags.PerfCategory,
   505  	}
   506  
   507  	// Miner settings
   508  	MiningEnabledFlag = &cli.BoolFlag{
   509  		Name:     "mine",
   510  		Usage:    "Enable mining",
   511  		Category: flags.MinerCategory,
   512  	}
   513  	MinerThreadsFlag = &cli.IntFlag{
   514  		Name:     "miner.threads",
   515  		Usage:    "Number of CPU threads to use for mining",
   516  		Value:    0,
   517  		Category: flags.MinerCategory,
   518  	}
   519  	MinerNotifyFlag = &cli.StringFlag{
   520  		Name:     "miner.notify",
   521  		Usage:    "Comma separated HTTP URL list to notify of new work packages",
   522  		Category: flags.MinerCategory,
   523  	}
   524  	MinerNotifyFullFlag = &cli.BoolFlag{
   525  		Name:     "miner.notify.full",
   526  		Usage:    "Notify with pending block headers instead of work packages",
   527  		Category: flags.MinerCategory,
   528  	}
   529  	MinerGasLimitFlag = &cli.Uint64Flag{
   530  		Name:     "miner.gaslimit",
   531  		Usage:    "Target gas ceiling for mined blocks",
   532  		Value:    ethconfig.Defaults.Miner.GasCeil,
   533  		Category: flags.MinerCategory,
   534  	}
   535  	MinerGasPriceFlag = &flags.BigFlag{
   536  		Name:     "miner.gasprice",
   537  		Usage:    "Minimum gas price for mining a transaction",
   538  		Value:    ethconfig.Defaults.Miner.GasPrice,
   539  		Category: flags.MinerCategory,
   540  	}
   541  	MinerEtherbaseFlag = &cli.StringFlag{
   542  		Name:     "miner.etherbase",
   543  		Usage:    "Public address for block mining rewards (default = first account)",
   544  		Value:    "0",
   545  		Category: flags.MinerCategory,
   546  	}
   547  	MinerExtraDataFlag = &cli.StringFlag{
   548  		Name:     "miner.extradata",
   549  		Usage:    "Block extra data set by the miner (default = client version)",
   550  		Category: flags.MinerCategory,
   551  	}
   552  	MinerRecommitIntervalFlag = &cli.DurationFlag{
   553  		Name:     "miner.recommit",
   554  		Usage:    "Time interval to recreate the block being mined",
   555  		Value:    ethconfig.Defaults.Miner.Recommit,
   556  		Category: flags.MinerCategory,
   557  	}
   558  	MinerNoVerifyFlag = &cli.BoolFlag{
   559  		Name:     "miner.noverify",
   560  		Usage:    "Disable remote sealing verification",
   561  		Category: flags.MinerCategory,
   562  	}
   563  
   564  	// Account settings
   565  	UnlockedAccountFlag = &cli.StringFlag{
   566  		Name:     "unlock",
   567  		Usage:    "Comma separated list of accounts to unlock",
   568  		Value:    "",
   569  		Category: flags.AccountCategory,
   570  	}
   571  	PasswordFileFlag = &cli.PathFlag{
   572  		Name:      "password",
   573  		Usage:     "Password file to use for non-interactive password input",
   574  		TakesFile: true,
   575  		Category:  flags.AccountCategory,
   576  	}
   577  	ExternalSignerFlag = &cli.StringFlag{
   578  		Name:     "signer",
   579  		Usage:    "External signer (url or path to ipc file)",
   580  		Value:    "",
   581  		Category: flags.AccountCategory,
   582  	}
   583  	InsecureUnlockAllowedFlag = &cli.BoolFlag{
   584  		Name:     "allow-insecure-unlock",
   585  		Usage:    "Allow insecure account unlocking when account-related RPCs are exposed by http",
   586  		Category: flags.AccountCategory,
   587  	}
   588  
   589  	// EVM settings
   590  	VMEnableDebugFlag = &cli.BoolFlag{
   591  		Name:     "vmdebug",
   592  		Usage:    "Record information useful for VM and contract debugging",
   593  		Category: flags.VMCategory,
   594  	}
   595  
   596  	// API options.
   597  	RPCGlobalGasCapFlag = &cli.Uint64Flag{
   598  		Name:     "rpc.gascap",
   599  		Usage:    "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)",
   600  		Value:    ethconfig.Defaults.RPCGasCap,
   601  		Category: flags.APICategory,
   602  	}
   603  	RPCGlobalEVMTimeoutFlag = &cli.DurationFlag{
   604  		Name:     "rpc.evmtimeout",
   605  		Usage:    "Sets a timeout used for eth_call (0=infinite)",
   606  		Value:    ethconfig.Defaults.RPCEVMTimeout,
   607  		Category: flags.APICategory,
   608  	}
   609  	RPCGlobalTxFeeCapFlag = &cli.Float64Flag{
   610  		Name:     "rpc.txfeecap",
   611  		Usage:    "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)",
   612  		Value:    ethconfig.Defaults.RPCTxFeeCap,
   613  		Category: flags.APICategory,
   614  	}
   615  	// Authenticated RPC HTTP settings
   616  	AuthListenFlag = &cli.StringFlag{
   617  		Name:     "authrpc.addr",
   618  		Usage:    "Listening address for authenticated APIs",
   619  		Value:    node.DefaultConfig.AuthAddr,
   620  		Category: flags.APICategory,
   621  	}
   622  	AuthPortFlag = &cli.IntFlag{
   623  		Name:     "authrpc.port",
   624  		Usage:    "Listening port for authenticated APIs",
   625  		Value:    node.DefaultConfig.AuthPort,
   626  		Category: flags.APICategory,
   627  	}
   628  	AuthVirtualHostsFlag = &cli.StringFlag{
   629  		Name:     "authrpc.vhosts",
   630  		Usage:    "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   631  		Value:    strings.Join(node.DefaultConfig.AuthVirtualHosts, ","),
   632  		Category: flags.APICategory,
   633  	}
   634  	JWTSecretFlag = &cli.StringFlag{
   635  		Name:     "authrpc.jwtsecret",
   636  		Usage:    "Path to a JWT secret to use for authenticated RPC endpoints",
   637  		Category: flags.APICategory,
   638  	}
   639  
   640  	// Logging and debug settings
   641  	EthStatsURLFlag = &cli.StringFlag{
   642  		Name:     "ethstats",
   643  		Usage:    "Reporting URL of a ethstats service (nodename:secret@host:port)",
   644  		Category: flags.MetricsCategory,
   645  	}
   646  	FakePoWFlag = &cli.BoolFlag{
   647  		Name:     "fakepow",
   648  		Usage:    "Disables proof-of-work verification",
   649  		Category: flags.LoggingCategory,
   650  	}
   651  	NoCompactionFlag = &cli.BoolFlag{
   652  		Name:     "nocompaction",
   653  		Usage:    "Disables db compaction after import",
   654  		Category: flags.LoggingCategory,
   655  	}
   656  
   657  	IgnoreLegacyReceiptsFlag = &cli.BoolFlag{
   658  		Name:     "ignore-legacy-receipts",
   659  		Usage:    "Geth will start up even if there are legacy receipts in freezer",
   660  		Category: flags.MiscCategory,
   661  	}
   662  
   663  	// RPC settings
   664  	IPCDisabledFlag = &cli.BoolFlag{
   665  		Name:     "ipcdisable",
   666  		Usage:    "Disable the IPC-RPC server",
   667  		Category: flags.APICategory,
   668  	}
   669  	IPCPathFlag = &flags.DirectoryFlag{
   670  		Name:     "ipcpath",
   671  		Usage:    "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   672  		Category: flags.APICategory,
   673  	}
   674  	HTTPEnabledFlag = &cli.BoolFlag{
   675  		Name:     "http",
   676  		Usage:    "Enable the HTTP-RPC server",
   677  		Category: flags.APICategory,
   678  	}
   679  	HTTPListenAddrFlag = &cli.StringFlag{
   680  		Name:     "http.addr",
   681  		Usage:    "HTTP-RPC server listening interface",
   682  		Value:    node.DefaultHTTPHost,
   683  		Category: flags.APICategory,
   684  	}
   685  	HTTPPortFlag = &cli.IntFlag{
   686  		Name:     "http.port",
   687  		Usage:    "HTTP-RPC server listening port",
   688  		Value:    node.DefaultHTTPPort,
   689  		Category: flags.APICategory,
   690  	}
   691  	HTTPCORSDomainFlag = &cli.StringFlag{
   692  		Name:     "http.corsdomain",
   693  		Usage:    "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   694  		Value:    "",
   695  		Category: flags.APICategory,
   696  	}
   697  	HTTPVirtualHostsFlag = &cli.StringFlag{
   698  		Name:     "http.vhosts",
   699  		Usage:    "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   700  		Value:    strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","),
   701  		Category: flags.APICategory,
   702  	}
   703  	HTTPApiFlag = &cli.StringFlag{
   704  		Name:     "http.api",
   705  		Usage:    "API's offered over the HTTP-RPC interface",
   706  		Value:    "",
   707  		Category: flags.APICategory,
   708  	}
   709  	HTTPPathPrefixFlag = &cli.StringFlag{
   710  		Name:     "http.rpcprefix",
   711  		Usage:    "HTTP path path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
   712  		Value:    "",
   713  		Category: flags.APICategory,
   714  	}
   715  	GraphQLEnabledFlag = &cli.BoolFlag{
   716  		Name:     "graphql",
   717  		Usage:    "Enable GraphQL on the HTTP-RPC server. Note that GraphQL can only be started if an HTTP server is started as well.",
   718  		Category: flags.APICategory,
   719  	}
   720  	GraphQLCORSDomainFlag = &cli.StringFlag{
   721  		Name:     "graphql.corsdomain",
   722  		Usage:    "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   723  		Value:    "",
   724  		Category: flags.APICategory,
   725  	}
   726  	GraphQLVirtualHostsFlag = &cli.StringFlag{
   727  		Name:     "graphql.vhosts",
   728  		Usage:    "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   729  		Value:    strings.Join(node.DefaultConfig.GraphQLVirtualHosts, ","),
   730  		Category: flags.APICategory,
   731  	}
   732  	WSEnabledFlag = &cli.BoolFlag{
   733  		Name:     "ws",
   734  		Usage:    "Enable the WS-RPC server",
   735  		Category: flags.APICategory,
   736  	}
   737  	WSListenAddrFlag = &cli.StringFlag{
   738  		Name:     "ws.addr",
   739  		Usage:    "WS-RPC server listening interface",
   740  		Value:    node.DefaultWSHost,
   741  		Category: flags.APICategory,
   742  	}
   743  	WSPortFlag = &cli.IntFlag{
   744  		Name:     "ws.port",
   745  		Usage:    "WS-RPC server listening port",
   746  		Value:    node.DefaultWSPort,
   747  		Category: flags.APICategory,
   748  	}
   749  	WSApiFlag = &cli.StringFlag{
   750  		Name:     "ws.api",
   751  		Usage:    "API's offered over the WS-RPC interface",
   752  		Value:    "",
   753  		Category: flags.APICategory,
   754  	}
   755  	WSAllowedOriginsFlag = &cli.StringFlag{
   756  		Name:     "ws.origins",
   757  		Usage:    "Origins from which to accept websockets requests",
   758  		Value:    "",
   759  		Category: flags.APICategory,
   760  	}
   761  	WSPathPrefixFlag = &cli.StringFlag{
   762  		Name:     "ws.rpcprefix",
   763  		Usage:    "HTTP path prefix on which JSON-RPC is served. Use '/' to serve on all paths.",
   764  		Value:    "",
   765  		Category: flags.APICategory,
   766  	}
   767  	ExecFlag = &cli.StringFlag{
   768  		Name:     "exec",
   769  		Usage:    "Execute JavaScript statement",
   770  		Category: flags.APICategory,
   771  	}
   772  	PreloadJSFlag = &cli.StringFlag{
   773  		Name:     "preload",
   774  		Usage:    "Comma separated list of JavaScript files to preload into the console",
   775  		Category: flags.APICategory,
   776  	}
   777  	AllowUnprotectedTxs = &cli.BoolFlag{
   778  		Name:     "rpc.allow-unprotected-txs",
   779  		Usage:    "Allow for unprotected (non EIP155 signed) transactions to be submitted via RPC",
   780  		Category: flags.APICategory,
   781  	}
   782  
   783  	// Network Settings
   784  	MaxPeersFlag = &cli.IntFlag{
   785  		Name:     "maxpeers",
   786  		Usage:    "Maximum number of network peers (network disabled if set to 0)",
   787  		Value:    node.DefaultConfig.P2P.MaxPeers,
   788  		Category: flags.NetworkingCategory,
   789  	}
   790  	MaxPendingPeersFlag = &cli.IntFlag{
   791  		Name:     "maxpendpeers",
   792  		Usage:    "Maximum number of pending connection attempts (defaults used if set to 0)",
   793  		Value:    node.DefaultConfig.P2P.MaxPendingPeers,
   794  		Category: flags.NetworkingCategory,
   795  	}
   796  	ListenPortFlag = &cli.IntFlag{
   797  		Name:     "port",
   798  		Usage:    "Network listening port",
   799  		Value:    30303,
   800  		Category: flags.NetworkingCategory,
   801  	}
   802  	BootnodesFlag = &cli.StringFlag{
   803  		Name:     "bootnodes",
   804  		Usage:    "Comma separated enode URLs for P2P discovery bootstrap",
   805  		Value:    "",
   806  		Category: flags.NetworkingCategory,
   807  	}
   808  	NodeKeyFileFlag = &cli.StringFlag{
   809  		Name:     "nodekey",
   810  		Usage:    "P2P node key file",
   811  		Category: flags.NetworkingCategory,
   812  	}
   813  	NodeKeyHexFlag = &cli.StringFlag{
   814  		Name:     "nodekeyhex",
   815  		Usage:    "P2P node key as hex (for testing)",
   816  		Category: flags.NetworkingCategory,
   817  	}
   818  	NATFlag = &cli.StringFlag{
   819  		Name:     "nat",
   820  		Usage:    "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   821  		Value:    "any",
   822  		Category: flags.NetworkingCategory,
   823  	}
   824  	NoDiscoverFlag = &cli.BoolFlag{
   825  		Name:     "nodiscover",
   826  		Usage:    "Disables the peer discovery mechanism (manual peer addition)",
   827  		Category: flags.NetworkingCategory,
   828  	}
   829  	DiscoveryV5Flag = &cli.BoolFlag{
   830  		Name:     "v5disc",
   831  		Usage:    "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   832  		Category: flags.NetworkingCategory,
   833  	}
   834  	NetrestrictFlag = &cli.StringFlag{
   835  		Name:     "netrestrict",
   836  		Usage:    "Restricts network communication to the given IP networks (CIDR masks)",
   837  		Category: flags.NetworkingCategory,
   838  	}
   839  	DNSDiscoveryFlag = &cli.StringFlag{
   840  		Name:     "discovery.dns",
   841  		Usage:    "Sets DNS discovery entry points (use \"\" to disable DNS)",
   842  		Category: flags.NetworkingCategory,
   843  	}
   844  	DiscoveryPortFlag = &cli.IntFlag{
   845  		Name:     "discovery.port",
   846  		Usage:    "Use a custom UDP port for P2P discovery",
   847  		Value:    30303,
   848  		Category: flags.NetworkingCategory,
   849  	}
   850  
   851  	// Console
   852  	JSpathFlag = &flags.DirectoryFlag{
   853  		Name:     "jspath",
   854  		Usage:    "JavaScript root path for `loadScript`",
   855  		Value:    flags.DirectoryString("."),
   856  		Category: flags.APICategory,
   857  	}
   858  
   859  	// Gas price oracle settings
   860  	GpoBlocksFlag = &cli.IntFlag{
   861  		Name:     "gpo.blocks",
   862  		Usage:    "Number of recent blocks to check for gas prices",
   863  		Value:    ethconfig.Defaults.GPO.Blocks,
   864  		Category: flags.GasPriceCategory,
   865  	}
   866  	GpoPercentileFlag = &cli.IntFlag{
   867  		Name:     "gpo.percentile",
   868  		Usage:    "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   869  		Value:    ethconfig.Defaults.GPO.Percentile,
   870  		Category: flags.GasPriceCategory,
   871  	}
   872  	GpoMaxGasPriceFlag = &cli.Int64Flag{
   873  		Name:     "gpo.maxprice",
   874  		Usage:    "Maximum transaction priority fee (or gasprice before London fork) to be recommended by gpo",
   875  		Value:    ethconfig.Defaults.GPO.MaxPrice.Int64(),
   876  		Category: flags.GasPriceCategory,
   877  	}
   878  	GpoIgnoreGasPriceFlag = &cli.Int64Flag{
   879  		Name:     "gpo.ignoreprice",
   880  		Usage:    "Gas price below which gpo will ignore transactions",
   881  		Value:    ethconfig.Defaults.GPO.IgnorePrice.Int64(),
   882  		Category: flags.GasPriceCategory,
   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.IsSet(CacheLogSizeFlag.Name) {
  1819  		cfg.FilterLogCacheSize = ctx.Int(CacheLogSizeFlag.Name)
  1820  	}
  1821  	if !ctx.Bool(SnapshotFlag.Name) {
  1822  		// If snap-sync is requested, this flag is also required
  1823  		if cfg.SyncMode == downloader.SnapSync {
  1824  			log.Info("Snap sync requested, enabling --snapshot")
  1825  		} else {
  1826  			cfg.TrieCleanCache += cfg.SnapshotCache
  1827  			cfg.SnapshotCache = 0 // Disabled
  1828  		}
  1829  	}
  1830  	if ctx.IsSet(DocRootFlag.Name) {
  1831  		cfg.DocRoot = ctx.String(DocRootFlag.Name)
  1832  	}
  1833  	if ctx.IsSet(VMEnableDebugFlag.Name) {
  1834  		// TODO(fjl): force-enable this in --dev mode
  1835  		cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
  1836  	}
  1837  
  1838  	if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
  1839  		cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
  1840  	}
  1841  	if cfg.RPCGasCap != 0 {
  1842  		log.Info("Set global gas cap", "cap", cfg.RPCGasCap)
  1843  	} else {
  1844  		log.Info("Global gas cap disabled")
  1845  	}
  1846  	if ctx.IsSet(RPCGlobalEVMTimeoutFlag.Name) {
  1847  		cfg.RPCEVMTimeout = ctx.Duration(RPCGlobalEVMTimeoutFlag.Name)
  1848  	}
  1849  	if ctx.IsSet(RPCGlobalTxFeeCapFlag.Name) {
  1850  		cfg.RPCTxFeeCap = ctx.Float64(RPCGlobalTxFeeCapFlag.Name)
  1851  	}
  1852  	if ctx.IsSet(NoDiscoverFlag.Name) {
  1853  		cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs = []string{}, []string{}
  1854  	} else if ctx.IsSet(DNSDiscoveryFlag.Name) {
  1855  		urls := ctx.String(DNSDiscoveryFlag.Name)
  1856  		if urls == "" {
  1857  			cfg.EthDiscoveryURLs = []string{}
  1858  		} else {
  1859  			cfg.EthDiscoveryURLs = SplitAndTrim(urls)
  1860  		}
  1861  	}
  1862  	// Override any default configs for hard coded networks.
  1863  	switch {
  1864  	case ctx.Bool(MainnetFlag.Name):
  1865  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1866  			cfg.NetworkId = 513100
  1867  		}
  1868  		cfg.Genesis = core.DefaultGenesisBlock()
  1869  		SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
  1870  	case ctx.Bool(RopstenFlag.Name):
  1871  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1872  			cfg.NetworkId = 3
  1873  		}
  1874  		cfg.Genesis = core.DefaultRopstenGenesisBlock()
  1875  		SetDNSDiscoveryDefaults(cfg, params.RopstenGenesisHash)
  1876  	case ctx.Bool(SepoliaFlag.Name):
  1877  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1878  			cfg.NetworkId = 11155111
  1879  		}
  1880  		cfg.Genesis = core.DefaultSepoliaGenesisBlock()
  1881  		SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash)
  1882  	case ctx.Bool(RinkebyFlag.Name):
  1883  		log.Warn("")
  1884  		log.Warn("--------------------------------------------------------------------------------")
  1885  		log.Warn("Please note, Rinkeby has been deprecated. It will still work for the time being,")
  1886  		log.Warn("but there will be no further hard-forks shipped for it. Eventually the network")
  1887  		log.Warn("will be permanently halted after the other networks transition through the merge")
  1888  		log.Warn("and prove stable enough. For the most future proof testnet, choose Sepolia as")
  1889  		log.Warn("your replacement environment (--sepolia instead of --rinkeby).")
  1890  		log.Warn("--------------------------------------------------------------------------------")
  1891  		log.Warn("")
  1892  
  1893  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1894  			cfg.NetworkId = 4
  1895  		}
  1896  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1897  		SetDNSDiscoveryDefaults(cfg, params.RinkebyGenesisHash)
  1898  	case ctx.Bool(GoerliFlag.Name):
  1899  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1900  			cfg.NetworkId = 5
  1901  		}
  1902  		cfg.Genesis = core.DefaultGoerliGenesisBlock()
  1903  		SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash)
  1904  	case ctx.Bool(KilnFlag.Name):
  1905  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1906  			cfg.NetworkId = 1337802
  1907  		}
  1908  		cfg.Genesis = core.DefaultKilnGenesisBlock()
  1909  		SetDNSDiscoveryDefaults(cfg, params.KilnGenesisHash)
  1910  	case ctx.Bool(DeveloperFlag.Name):
  1911  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1912  			cfg.NetworkId = 1337
  1913  		}
  1914  		cfg.SyncMode = downloader.FullSync
  1915  		// Create new developer account or reuse existing one
  1916  		var (
  1917  			developer  accounts.Account
  1918  			passphrase string
  1919  			err        error
  1920  		)
  1921  		if list := MakePasswordList(ctx); len(list) > 0 {
  1922  			// Just take the first value. Although the function returns a possible multiple values and
  1923  			// some usages iterate through them as attempts, that doesn't make sense in this setting,
  1924  			// when we're definitely concerned with only one account.
  1925  			passphrase = list[0]
  1926  		}
  1927  		// setEtherbase has been called above, configuring the miner address from command line flags.
  1928  		if cfg.Miner.Etherbase != (common.Address{}) {
  1929  			developer = accounts.Account{Address: cfg.Miner.Etherbase}
  1930  		} else if accs := ks.Accounts(); len(accs) > 0 {
  1931  			developer = ks.Accounts()[0]
  1932  		} else {
  1933  			developer, err = ks.NewAccount(passphrase)
  1934  			if err != nil {
  1935  				Fatalf("Failed to create developer account: %v", err)
  1936  			}
  1937  		}
  1938  		if err := ks.Unlock(developer, passphrase); err != nil {
  1939  			Fatalf("Failed to unlock developer account: %v", err)
  1940  		}
  1941  		log.Info("Using developer account", "address", developer.Address)
  1942  
  1943  		// Create a new developer genesis block or reuse existing one
  1944  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.Int(DeveloperPeriodFlag.Name)), ctx.Uint64(DeveloperGasLimitFlag.Name), developer.Address)
  1945  		if ctx.IsSet(DataDirFlag.Name) {
  1946  			// If datadir doesn't exist we need to open db in write-mode
  1947  			// so leveldb can create files.
  1948  			readonly := true
  1949  			if !common.FileExist(stack.ResolvePath("chaindata")) {
  1950  				readonly = false
  1951  			}
  1952  			// Check if we have an already initialized chain and fall back to
  1953  			// that if so. Otherwise we need to generate a new genesis spec.
  1954  			chaindb := MakeChainDatabase(ctx, stack, readonly)
  1955  			if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
  1956  				cfg.Genesis = nil // fallback to db content
  1957  			}
  1958  			chaindb.Close()
  1959  		}
  1960  		if !ctx.IsSet(MinerGasPriceFlag.Name) {
  1961  			cfg.Miner.GasPrice = big.NewInt(1)
  1962  		}
  1963  	default:
  1964  		if cfg.NetworkId == 1 {
  1965  			SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
  1966  		}
  1967  	}
  1968  }
  1969  
  1970  // SetDNSDiscoveryDefaults configures DNS discovery with the given URL if
  1971  // no URLs are set.
  1972  func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
  1973  	if cfg.EthDiscoveryURLs != nil {
  1974  		return // already set through flags/config
  1975  	}
  1976  	protocol := "all"
  1977  	if cfg.SyncMode == downloader.LightSync {
  1978  		protocol = "les"
  1979  	}
  1980  	if url := params.KnownDNSNetwork(genesis, protocol); url != "" {
  1981  		cfg.EthDiscoveryURLs = []string{url}
  1982  		cfg.SnapDiscoveryURLs = cfg.EthDiscoveryURLs
  1983  	}
  1984  }
  1985  
  1986  // RegisterEthService adds an Ethereum client to the stack.
  1987  // The second return value is the full node instance, which may be nil if the
  1988  // node is running as a light client.
  1989  func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) {
  1990  	if cfg.SyncMode == downloader.LightSync {
  1991  		backend, err := les.New(stack, cfg)
  1992  		if err != nil {
  1993  			Fatalf("Failed to register the Ethereum service: %v", err)
  1994  		}
  1995  		stack.RegisterAPIs(tracers.APIs(backend.ApiBackend))
  1996  		if err := lescatalyst.Register(stack, backend); err != nil {
  1997  			Fatalf("Failed to register the Engine API service: %v", err)
  1998  		}
  1999  		return backend.ApiBackend, nil
  2000  	}
  2001  	backend, err := eth.New(stack, cfg)
  2002  	if err != nil {
  2003  		Fatalf("Failed to register the Ethereum service: %v", err)
  2004  	}
  2005  	if cfg.LightServ > 0 {
  2006  		_, err := les.NewLesServer(stack, backend, cfg)
  2007  		if err != nil {
  2008  			Fatalf("Failed to create the LES server: %v", err)
  2009  		}
  2010  	}
  2011  	if err := ethcatalyst.Register(stack, backend); err != nil {
  2012  		Fatalf("Failed to register the Engine API service: %v", err)
  2013  	}
  2014  	stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
  2015  	return backend.APIBackend, backend
  2016  }
  2017  
  2018  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to the node.
  2019  func RegisterEthStatsService(stack *node.Node, backend ethapi.Backend, url string) {
  2020  	if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil {
  2021  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  2022  	}
  2023  }
  2024  
  2025  // RegisterGraphQLService adds the GraphQL API to the node.
  2026  func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, filterSystem *filters.FilterSystem, cfg *node.Config) {
  2027  	err := graphql.New(stack, backend, filterSystem, cfg.GraphQLCors, cfg.GraphQLVirtualHosts)
  2028  	if err != nil {
  2029  		Fatalf("Failed to register the GraphQL service: %v", err)
  2030  	}
  2031  }
  2032  
  2033  // RegisterFilterAPI adds the eth log filtering RPC API to the node.
  2034  func RegisterFilterAPI(stack *node.Node, backend ethapi.Backend, ethcfg *ethconfig.Config) *filters.FilterSystem {
  2035  	isLightClient := ethcfg.SyncMode == downloader.LightSync
  2036  	filterSystem := filters.NewFilterSystem(backend, filters.Config{
  2037  		LogCacheSize: ethcfg.FilterLogCacheSize,
  2038  	})
  2039  	stack.RegisterAPIs([]rpc.API{{
  2040  		Namespace: "eth",
  2041  		Service:   filters.NewFilterAPI(filterSystem, isLightClient),
  2042  	}})
  2043  	return filterSystem
  2044  }
  2045  
  2046  func SetupMetrics(ctx *cli.Context) {
  2047  	if metrics.Enabled {
  2048  		log.Info("Enabling metrics collection")
  2049  
  2050  		var (
  2051  			enableExport   = ctx.Bool(MetricsEnableInfluxDBFlag.Name)
  2052  			enableExportV2 = ctx.Bool(MetricsEnableInfluxDBV2Flag.Name)
  2053  		)
  2054  
  2055  		if enableExport || enableExportV2 {
  2056  			CheckExclusive(ctx, MetricsEnableInfluxDBFlag, MetricsEnableInfluxDBV2Flag)
  2057  
  2058  			v1FlagIsSet := ctx.IsSet(MetricsInfluxDBUsernameFlag.Name) ||
  2059  				ctx.IsSet(MetricsInfluxDBPasswordFlag.Name)
  2060  
  2061  			v2FlagIsSet := ctx.IsSet(MetricsInfluxDBTokenFlag.Name) ||
  2062  				ctx.IsSet(MetricsInfluxDBOrganizationFlag.Name) ||
  2063  				ctx.IsSet(MetricsInfluxDBBucketFlag.Name)
  2064  
  2065  			if enableExport && v2FlagIsSet {
  2066  				Fatalf("Flags --influxdb.metrics.organization, --influxdb.metrics.token, --influxdb.metrics.bucket are only available for influxdb-v2")
  2067  			} else if enableExportV2 && v1FlagIsSet {
  2068  				Fatalf("Flags --influxdb.metrics.username, --influxdb.metrics.password are only available for influxdb-v1")
  2069  			}
  2070  		}
  2071  
  2072  		var (
  2073  			endpoint = ctx.String(MetricsInfluxDBEndpointFlag.Name)
  2074  			database = ctx.String(MetricsInfluxDBDatabaseFlag.Name)
  2075  			username = ctx.String(MetricsInfluxDBUsernameFlag.Name)
  2076  			password = ctx.String(MetricsInfluxDBPasswordFlag.Name)
  2077  
  2078  			token        = ctx.String(MetricsInfluxDBTokenFlag.Name)
  2079  			bucket       = ctx.String(MetricsInfluxDBBucketFlag.Name)
  2080  			organization = ctx.String(MetricsInfluxDBOrganizationFlag.Name)
  2081  		)
  2082  
  2083  		if enableExport {
  2084  			tagsMap := SplitTagsFlag(ctx.String(MetricsInfluxDBTagsFlag.Name))
  2085  
  2086  			log.Info("Enabling metrics export to InfluxDB")
  2087  
  2088  			go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap)
  2089  		} else if enableExportV2 {
  2090  			tagsMap := SplitTagsFlag(ctx.String(MetricsInfluxDBTagsFlag.Name))
  2091  
  2092  			log.Info("Enabling metrics export to InfluxDB (v2)")
  2093  
  2094  			go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap)
  2095  		}
  2096  
  2097  		if ctx.IsSet(MetricsHTTPFlag.Name) {
  2098  			address := fmt.Sprintf("%s:%d", ctx.String(MetricsHTTPFlag.Name), ctx.Int(MetricsPortFlag.Name))
  2099  			log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address)
  2100  			exp.Setup(address)
  2101  		}
  2102  	}
  2103  }
  2104  
  2105  func SplitTagsFlag(tagsFlag string) map[string]string {
  2106  	tags := strings.Split(tagsFlag, ",")
  2107  	tagsMap := map[string]string{}
  2108  
  2109  	for _, t := range tags {
  2110  		if t != "" {
  2111  			kv := strings.Split(t, "=")
  2112  
  2113  			if len(kv) == 2 {
  2114  				tagsMap[kv[0]] = kv[1]
  2115  			}
  2116  		}
  2117  	}
  2118  
  2119  	return tagsMap
  2120  }
  2121  
  2122  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  2123  func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.Database {
  2124  	var (
  2125  		cache   = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
  2126  		handles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name))
  2127  
  2128  		err     error
  2129  		chainDb ethdb.Database
  2130  	)
  2131  	switch {
  2132  	case ctx.IsSet(RemoteDBFlag.Name):
  2133  		log.Info("Using remote db", "url", ctx.String(RemoteDBFlag.Name))
  2134  		chainDb, err = remotedb.New(ctx.String(RemoteDBFlag.Name))
  2135  	case ctx.String(SyncModeFlag.Name) == "light":
  2136  		chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly)
  2137  	default:
  2138  		chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly)
  2139  	}
  2140  	if err != nil {
  2141  		Fatalf("Could not open database: %v", err)
  2142  	}
  2143  	return chainDb
  2144  }
  2145  
  2146  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  2147  	var genesis *core.Genesis
  2148  	switch {
  2149  	case ctx.Bool(MainnetFlag.Name):
  2150  		genesis = core.DefaultGenesisBlock()
  2151  	case ctx.Bool(RopstenFlag.Name):
  2152  		genesis = core.DefaultRopstenGenesisBlock()
  2153  	case ctx.Bool(SepoliaFlag.Name):
  2154  		genesis = core.DefaultSepoliaGenesisBlock()
  2155  	case ctx.Bool(RinkebyFlag.Name):
  2156  		genesis = core.DefaultRinkebyGenesisBlock()
  2157  	case ctx.Bool(GoerliFlag.Name):
  2158  		genesis = core.DefaultGoerliGenesisBlock()
  2159  	case ctx.Bool(KilnFlag.Name):
  2160  		genesis = core.DefaultKilnGenesisBlock()
  2161  	case ctx.Bool(DeveloperFlag.Name):
  2162  		Fatalf("Developer chains are ephemeral")
  2163  	}
  2164  	return genesis
  2165  }
  2166  
  2167  // MakeChain creates a chain manager from set command line flags.
  2168  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
  2169  	var err error
  2170  	chainDb = MakeChainDatabase(ctx, stack, false) // TODO(rjl493456442) support read-only database
  2171  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  2172  	if err != nil {
  2173  		Fatalf("%v", err)
  2174  	}
  2175  
  2176  	var engine consensus.Engine
  2177  	ethashConf := ethconfig.Defaults.Ethash
  2178  	if ctx.Bool(FakePoWFlag.Name) {
  2179  		ethashConf.PowMode = ethash.ModeFake
  2180  	}
  2181  	engine = ethconfig.CreateConsensusEngine(stack, config, &ethashConf, nil, false, chainDb)
  2182  	if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  2183  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  2184  	}
  2185  	cache := &core.CacheConfig{
  2186  		TrieCleanLimit:      ethconfig.Defaults.TrieCleanCache,
  2187  		TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name),
  2188  		TrieDirtyLimit:      ethconfig.Defaults.TrieDirtyCache,
  2189  		TrieDirtyDisabled:   ctx.String(GCModeFlag.Name) == "archive",
  2190  		TrieTimeLimit:       ethconfig.Defaults.TrieTimeout,
  2191  		SnapshotLimit:       ethconfig.Defaults.SnapshotCache,
  2192  		Preimages:           ctx.Bool(CachePreimagesFlag.Name),
  2193  	}
  2194  	if cache.TrieDirtyDisabled && !cache.Preimages {
  2195  		cache.Preimages = true
  2196  		log.Info("Enabling recording of key preimages since archive mode is used")
  2197  	}
  2198  	if !ctx.Bool(SnapshotFlag.Name) {
  2199  		cache.SnapshotLimit = 0 // Disabled
  2200  	}
  2201  	if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
  2202  		cache.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
  2203  	}
  2204  	if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
  2205  		cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
  2206  	}
  2207  	vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)}
  2208  
  2209  	// TODO(rjl493456442) disable snapshot generation/wiping if the chain is read only.
  2210  	// Disable transaction indexing/unindexing by default.
  2211  	chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, nil)
  2212  	if err != nil {
  2213  		Fatalf("Can't create BlockChain: %v", err)
  2214  	}
  2215  	return chain, chainDb
  2216  }
  2217  
  2218  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  2219  // scripts to preload before starting.
  2220  func MakeConsolePreloads(ctx *cli.Context) []string {
  2221  	// Skip preloading if there's nothing to preload
  2222  	if ctx.String(PreloadJSFlag.Name) == "" {
  2223  		return nil
  2224  	}
  2225  	// Otherwise resolve absolute paths and return them
  2226  	var preloads []string
  2227  
  2228  	for _, file := range strings.Split(ctx.String(PreloadJSFlag.Name), ",") {
  2229  		preloads = append(preloads, strings.TrimSpace(file))
  2230  	}
  2231  	return preloads
  2232  }