github.com/tmoore22/go-ethereum@v1.10.22-0.20220814113424-76f4d8bc4994/cmd/utils/flags.go (about)

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