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