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