github.com/aiyaya188/klaytn@v0.0.0-20220629133911-2c66fd5546f4/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/aiyaya188/klaytn/accounts"
    33  	"github.com/aiyaya188/klaytn/accounts/keystore"
    34  	"github.com/aiyaya188/klaytn/common"
    35  	"github.com/aiyaya188/klaytn/common/fdlimit"
    36  	"github.com/aiyaya188/klaytn/consensus"
    37  	"github.com/aiyaya188/klaytn/consensus/ethash"
    38  	"github.com/aiyaya188/klaytn/core"
    39  	"github.com/aiyaya188/klaytn/core/rawdb"
    40  	"github.com/aiyaya188/klaytn/core/vm"
    41  	"github.com/aiyaya188/klaytn/crypto"
    42  	"github.com/aiyaya188/klaytn/eth"
    43  	ethcatalyst "github.com/aiyaya188/klaytn/eth/catalyst"
    44  	"github.com/aiyaya188/klaytn/eth/downloader"
    45  	"github.com/aiyaya188/klaytn/eth/ethconfig"
    46  	"github.com/aiyaya188/klaytn/eth/gasprice"
    47  	"github.com/aiyaya188/klaytn/eth/tracers"
    48  	"github.com/aiyaya188/klaytn/ethdb"
    49  	"github.com/aiyaya188/klaytn/ethdb/remotedb"
    50  	"github.com/aiyaya188/klaytn/ethstats"
    51  	"github.com/aiyaya188/klaytn/graphql"
    52  	"github.com/aiyaya188/klaytn/internal/ethapi"
    53  	"github.com/aiyaya188/klaytn/internal/flags"
    54  	"github.com/aiyaya188/klaytn/les"
    55  	lescatalyst "github.com/aiyaya188/klaytn/les/catalyst"
    56  	"github.com/aiyaya188/klaytn/log"
    57  	"github.com/aiyaya188/klaytn/metrics"
    58  	"github.com/aiyaya188/klaytn/metrics/exp"
    59  	"github.com/aiyaya188/klaytn/metrics/influxdb"
    60  	"github.com/aiyaya188/klaytn/miner"
    61  	"github.com/aiyaya188/klaytn/node"
    62  	"github.com/aiyaya188/klaytn/p2p"
    63  	"github.com/aiyaya188/klaytn/p2p/enode"
    64  	"github.com/aiyaya188/klaytn/p2p/nat"
    65  	"github.com/aiyaya188/klaytn/p2p/netutil"
    66  	"github.com/aiyaya188/klaytn/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  // GroupFlags combines the given flag slices together and returns the merged one.
   998  func GroupFlags(groups ...[]cli.Flag) []cli.Flag {
   999  	var ret []cli.Flag
  1000  	for _, group := range groups {
  1001  		ret = append(ret, group...)
  1002  	}
  1003  	return ret
  1004  }
  1005  
  1006  // MakeDataDir retrieves the currently requested data directory, terminating
  1007  // if none (or the empty string) is specified. If the node is starting a testnet,
  1008  // then a subdirectory of the specified datadir will be used.
  1009  func MakeDataDir(ctx *cli.Context) string {
  1010  	if path := ctx.String(DataDirFlag.Name); path != "" {
  1011  		if ctx.Bool(RopstenFlag.Name) {
  1012  			// Maintain compatibility with older Geth configurations storing the
  1013  			// Ropsten database in `testnet` instead of `ropsten`.
  1014  			return filepath.Join(path, "ropsten")
  1015  		}
  1016  		if ctx.Bool(RinkebyFlag.Name) {
  1017  			return filepath.Join(path, "rinkeby")
  1018  		}
  1019  		if ctx.Bool(GoerliFlag.Name) {
  1020  			return filepath.Join(path, "goerli")
  1021  		}
  1022  		if ctx.Bool(SepoliaFlag.Name) {
  1023  			return filepath.Join(path, "sepolia")
  1024  		}
  1025  		if ctx.Bool(KilnFlag.Name) {
  1026  			return filepath.Join(path, "kiln")
  1027  		}
  1028  		return path
  1029  	}
  1030  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
  1031  	return ""
  1032  }
  1033  
  1034  // setNodeKey creates a node key from set command line flags, either loading it
  1035  // from a file or as a specified hex value. If neither flags were provided, this
  1036  // method returns nil and an emphemeral key is to be generated.
  1037  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
  1038  	var (
  1039  		hex  = ctx.String(NodeKeyHexFlag.Name)
  1040  		file = ctx.String(NodeKeyFileFlag.Name)
  1041  		key  *ecdsa.PrivateKey
  1042  		err  error
  1043  	)
  1044  	switch {
  1045  	case file != "" && hex != "":
  1046  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
  1047  	case file != "":
  1048  		if key, err = crypto.LoadECDSA(file); err != nil {
  1049  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
  1050  		}
  1051  		cfg.PrivateKey = key
  1052  	case hex != "":
  1053  		if key, err = crypto.HexToECDSA(hex); err != nil {
  1054  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
  1055  		}
  1056  		cfg.PrivateKey = key
  1057  	}
  1058  }
  1059  
  1060  // setNodeUserIdent creates the user identifier from CLI flags.
  1061  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
  1062  	if identity := ctx.String(IdentityFlag.Name); len(identity) > 0 {
  1063  		cfg.UserIdent = identity
  1064  	}
  1065  }
  1066  
  1067  // setBootstrapNodes creates a list of bootstrap nodes from the command line
  1068  // flags, reverting to pre-configured ones if none have been specified.
  1069  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
  1070  	urls := params.MainnetBootnodes
  1071  	switch {
  1072  	case ctx.IsSet(BootnodesFlag.Name):
  1073  		urls = SplitAndTrim(ctx.String(BootnodesFlag.Name))
  1074  	case ctx.Bool(RopstenFlag.Name):
  1075  		urls = params.RopstenBootnodes
  1076  	case ctx.Bool(SepoliaFlag.Name):
  1077  		urls = params.SepoliaBootnodes
  1078  	case ctx.Bool(RinkebyFlag.Name):
  1079  		urls = params.RinkebyBootnodes
  1080  	case ctx.Bool(GoerliFlag.Name):
  1081  		urls = params.GoerliBootnodes
  1082  	case ctx.Bool(KilnFlag.Name):
  1083  		urls = params.KilnBootnodes
  1084  	}
  1085  
  1086  	// don't apply defaults if BootstrapNodes is already set
  1087  	if cfg.BootstrapNodes != nil {
  1088  		return
  1089  	}
  1090  
  1091  	cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls))
  1092  	for _, url := range urls {
  1093  		if url != "" {
  1094  			node, err := enode.Parse(enode.ValidSchemes, url)
  1095  			if err != nil {
  1096  				log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
  1097  				continue
  1098  			}
  1099  			cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
  1100  		}
  1101  	}
  1102  }
  1103  
  1104  // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
  1105  // flags, reverting to pre-configured ones if none have been specified.
  1106  func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
  1107  	urls := params.V5Bootnodes
  1108  	switch {
  1109  	case ctx.IsSet(BootnodesFlag.Name):
  1110  		urls = SplitAndTrim(ctx.String(BootnodesFlag.Name))
  1111  	case cfg.BootstrapNodesV5 != nil:
  1112  		return // already set, don't apply defaults.
  1113  	}
  1114  
  1115  	cfg.BootstrapNodesV5 = make([]*enode.Node, 0, len(urls))
  1116  	for _, url := range urls {
  1117  		if url != "" {
  1118  			node, err := enode.Parse(enode.ValidSchemes, url)
  1119  			if err != nil {
  1120  				log.Error("Bootstrap URL invalid", "enode", url, "err", err)
  1121  				continue
  1122  			}
  1123  			cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
  1124  		}
  1125  	}
  1126  }
  1127  
  1128  // setListenAddress creates TCP/UDP listening address strings from set command
  1129  // line flags
  1130  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
  1131  	if ctx.IsSet(ListenPortFlag.Name) {
  1132  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.Int(ListenPortFlag.Name))
  1133  	}
  1134  	if ctx.IsSet(DiscoveryPortFlag.Name) {
  1135  		cfg.DiscAddr = fmt.Sprintf(":%d", ctx.Int(DiscoveryPortFlag.Name))
  1136  	}
  1137  }
  1138  
  1139  // setNAT creates a port mapper from command line flags.
  1140  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
  1141  	if ctx.IsSet(NATFlag.Name) {
  1142  		natif, err := nat.Parse(ctx.String(NATFlag.Name))
  1143  		if err != nil {
  1144  			Fatalf("Option %s: %v", NATFlag.Name, err)
  1145  		}
  1146  		cfg.NAT = natif
  1147  	}
  1148  }
  1149  
  1150  // SplitAndTrim splits input separated by a comma
  1151  // and trims excessive white space from the substrings.
  1152  func SplitAndTrim(input string) (ret []string) {
  1153  	l := strings.Split(input, ",")
  1154  	for _, r := range l {
  1155  		if r = strings.TrimSpace(r); r != "" {
  1156  			ret = append(ret, r)
  1157  		}
  1158  	}
  1159  	return ret
  1160  }
  1161  
  1162  // setHTTP creates the HTTP RPC listener interface string from the set
  1163  // command line flags, returning empty if the HTTP endpoint is disabled.
  1164  func setHTTP(ctx *cli.Context, cfg *node.Config) {
  1165  	if ctx.Bool(HTTPEnabledFlag.Name) && cfg.HTTPHost == "" {
  1166  		cfg.HTTPHost = "127.0.0.1"
  1167  		if ctx.IsSet(HTTPListenAddrFlag.Name) {
  1168  			cfg.HTTPHost = ctx.String(HTTPListenAddrFlag.Name)
  1169  		}
  1170  	}
  1171  
  1172  	if ctx.IsSet(HTTPPortFlag.Name) {
  1173  		cfg.HTTPPort = ctx.Int(HTTPPortFlag.Name)
  1174  	}
  1175  
  1176  	if ctx.IsSet(AuthListenFlag.Name) {
  1177  		cfg.AuthAddr = ctx.String(AuthListenFlag.Name)
  1178  	}
  1179  
  1180  	if ctx.IsSet(AuthPortFlag.Name) {
  1181  		cfg.AuthPort = ctx.Int(AuthPortFlag.Name)
  1182  	}
  1183  
  1184  	if ctx.IsSet(AuthVirtualHostsFlag.Name) {
  1185  		cfg.AuthVirtualHosts = SplitAndTrim(ctx.String(AuthVirtualHostsFlag.Name))
  1186  	}
  1187  
  1188  	if ctx.IsSet(HTTPCORSDomainFlag.Name) {
  1189  		cfg.HTTPCors = SplitAndTrim(ctx.String(HTTPCORSDomainFlag.Name))
  1190  	}
  1191  
  1192  	if ctx.IsSet(HTTPApiFlag.Name) {
  1193  		cfg.HTTPModules = SplitAndTrim(ctx.String(HTTPApiFlag.Name))
  1194  	}
  1195  
  1196  	if ctx.IsSet(HTTPVirtualHostsFlag.Name) {
  1197  		cfg.HTTPVirtualHosts = SplitAndTrim(ctx.String(HTTPVirtualHostsFlag.Name))
  1198  	}
  1199  
  1200  	if ctx.IsSet(HTTPPathPrefixFlag.Name) {
  1201  		cfg.HTTPPathPrefix = ctx.String(HTTPPathPrefixFlag.Name)
  1202  	}
  1203  	if ctx.IsSet(AllowUnprotectedTxs.Name) {
  1204  		cfg.AllowUnprotectedTxs = ctx.Bool(AllowUnprotectedTxs.Name)
  1205  	}
  1206  }
  1207  
  1208  // setGraphQL creates the GraphQL listener interface string from the set
  1209  // command line flags, returning empty if the GraphQL endpoint is disabled.
  1210  func setGraphQL(ctx *cli.Context, cfg *node.Config) {
  1211  	if ctx.IsSet(GraphQLCORSDomainFlag.Name) {
  1212  		cfg.GraphQLCors = SplitAndTrim(ctx.String(GraphQLCORSDomainFlag.Name))
  1213  	}
  1214  	if ctx.IsSet(GraphQLVirtualHostsFlag.Name) {
  1215  		cfg.GraphQLVirtualHosts = SplitAndTrim(ctx.String(GraphQLVirtualHostsFlag.Name))
  1216  	}
  1217  }
  1218  
  1219  // setWS creates the WebSocket RPC listener interface string from the set
  1220  // command line flags, returning empty if the HTTP endpoint is disabled.
  1221  func setWS(ctx *cli.Context, cfg *node.Config) {
  1222  	if ctx.Bool(WSEnabledFlag.Name) && cfg.WSHost == "" {
  1223  		cfg.WSHost = "127.0.0.1"
  1224  		if ctx.IsSet(WSListenAddrFlag.Name) {
  1225  			cfg.WSHost = ctx.String(WSListenAddrFlag.Name)
  1226  		}
  1227  	}
  1228  	if ctx.IsSet(WSPortFlag.Name) {
  1229  		cfg.WSPort = ctx.Int(WSPortFlag.Name)
  1230  	}
  1231  
  1232  	if ctx.IsSet(WSAllowedOriginsFlag.Name) {
  1233  		cfg.WSOrigins = SplitAndTrim(ctx.String(WSAllowedOriginsFlag.Name))
  1234  	}
  1235  
  1236  	if ctx.IsSet(WSApiFlag.Name) {
  1237  		cfg.WSModules = SplitAndTrim(ctx.String(WSApiFlag.Name))
  1238  	}
  1239  
  1240  	if ctx.IsSet(WSPathPrefixFlag.Name) {
  1241  		cfg.WSPathPrefix = ctx.String(WSPathPrefixFlag.Name)
  1242  	}
  1243  }
  1244  
  1245  // setIPC creates an IPC path configuration from the set command line flags,
  1246  // returning an empty string if IPC was explicitly disabled, or the set path.
  1247  func setIPC(ctx *cli.Context, cfg *node.Config) {
  1248  	CheckExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
  1249  	switch {
  1250  	case ctx.Bool(IPCDisabledFlag.Name):
  1251  		cfg.IPCPath = ""
  1252  	case ctx.IsSet(IPCPathFlag.Name):
  1253  		cfg.IPCPath = ctx.String(IPCPathFlag.Name)
  1254  	}
  1255  }
  1256  
  1257  // setLes configures the les server and ultra light client settings from the command line flags.
  1258  func setLes(ctx *cli.Context, cfg *ethconfig.Config) {
  1259  	if ctx.IsSet(LightServeFlag.Name) {
  1260  		cfg.LightServ = ctx.Int(LightServeFlag.Name)
  1261  	}
  1262  	if ctx.IsSet(LightIngressFlag.Name) {
  1263  		cfg.LightIngress = ctx.Int(LightIngressFlag.Name)
  1264  	}
  1265  	if ctx.IsSet(LightEgressFlag.Name) {
  1266  		cfg.LightEgress = ctx.Int(LightEgressFlag.Name)
  1267  	}
  1268  	if ctx.IsSet(LightMaxPeersFlag.Name) {
  1269  		cfg.LightPeers = ctx.Int(LightMaxPeersFlag.Name)
  1270  	}
  1271  	if ctx.IsSet(UltraLightServersFlag.Name) {
  1272  		cfg.UltraLightServers = strings.Split(ctx.String(UltraLightServersFlag.Name), ",")
  1273  	}
  1274  	if ctx.IsSet(UltraLightFractionFlag.Name) {
  1275  		cfg.UltraLightFraction = ctx.Int(UltraLightFractionFlag.Name)
  1276  	}
  1277  	if cfg.UltraLightFraction <= 0 && cfg.UltraLightFraction > 100 {
  1278  		log.Error("Ultra light fraction is invalid", "had", cfg.UltraLightFraction, "updated", ethconfig.Defaults.UltraLightFraction)
  1279  		cfg.UltraLightFraction = ethconfig.Defaults.UltraLightFraction
  1280  	}
  1281  	if ctx.IsSet(UltraLightOnlyAnnounceFlag.Name) {
  1282  		cfg.UltraLightOnlyAnnounce = ctx.Bool(UltraLightOnlyAnnounceFlag.Name)
  1283  	}
  1284  	if ctx.IsSet(LightNoPruneFlag.Name) {
  1285  		cfg.LightNoPrune = ctx.Bool(LightNoPruneFlag.Name)
  1286  	}
  1287  	if ctx.IsSet(LightNoSyncServeFlag.Name) {
  1288  		cfg.LightNoSyncServe = ctx.Bool(LightNoSyncServeFlag.Name)
  1289  	}
  1290  }
  1291  
  1292  // MakeDatabaseHandles raises out the number of allowed file handles per process
  1293  // for Geth and returns half of the allowance to assign to the database.
  1294  func MakeDatabaseHandles(max int) int {
  1295  	limit, err := fdlimit.Maximum()
  1296  	if err != nil {
  1297  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
  1298  	}
  1299  	switch {
  1300  	case max == 0:
  1301  		// User didn't specify a meaningful value, use system limits
  1302  	case max < 128:
  1303  		// User specified something unhealthy, just use system defaults
  1304  		log.Error("File descriptor limit invalid (<128)", "had", max, "updated", limit)
  1305  	case max > limit:
  1306  		// User requested more than the OS allows, notify that we can't allocate it
  1307  		log.Warn("Requested file descriptors denied by OS", "req", max, "limit", limit)
  1308  	default:
  1309  		// User limit is meaningful and within allowed range, use that
  1310  		limit = max
  1311  	}
  1312  	raised, err := fdlimit.Raise(uint64(limit))
  1313  	if err != nil {
  1314  		Fatalf("Failed to raise file descriptor allowance: %v", err)
  1315  	}
  1316  	return int(raised / 2) // Leave half for networking and other stuff
  1317  }
  1318  
  1319  // MakeAddress converts an account specified directly as a hex encoded string or
  1320  // a key index in the key store to an internal account representation.
  1321  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
  1322  	// If the specified account is a valid address, return it
  1323  	if common.IsHexAddress(account) {
  1324  		return accounts.Account{Address: common.HexToAddress(account)}, nil
  1325  	}
  1326  	// Otherwise try to interpret the account as a keystore index
  1327  	index, err := strconv.Atoi(account)
  1328  	if err != nil || index < 0 {
  1329  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
  1330  	}
  1331  	log.Warn("-------------------------------------------------------------------")
  1332  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
  1333  	log.Warn("This functionality is deprecated and will be removed in the future!")
  1334  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
  1335  	log.Warn("-------------------------------------------------------------------")
  1336  
  1337  	accs := ks.Accounts()
  1338  	if len(accs) <= index {
  1339  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
  1340  	}
  1341  	return accs[index], nil
  1342  }
  1343  
  1344  // setEtherbase retrieves the etherbase either from the directly specified
  1345  // command line flags or from the keystore if CLI indexed.
  1346  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *ethconfig.Config) {
  1347  	// Extract the current etherbase
  1348  	var etherbase string
  1349  	if ctx.IsSet(MinerEtherbaseFlag.Name) {
  1350  		etherbase = ctx.String(MinerEtherbaseFlag.Name)
  1351  	}
  1352  	// Convert the etherbase into an address and configure it
  1353  	if etherbase != "" {
  1354  		if ks != nil {
  1355  			account, err := MakeAddress(ks, etherbase)
  1356  			if err != nil {
  1357  				Fatalf("Invalid miner etherbase: %v", err)
  1358  			}
  1359  			cfg.Miner.Etherbase = account.Address
  1360  		} else {
  1361  			Fatalf("No etherbase configured")
  1362  		}
  1363  	}
  1364  }
  1365  
  1366  // MakePasswordList reads password lines from the file specified by the global --password flag.
  1367  func MakePasswordList(ctx *cli.Context) []string {
  1368  	path := ctx.Path(PasswordFileFlag.Name)
  1369  	if path == "" {
  1370  		return nil
  1371  	}
  1372  	text, err := os.ReadFile(path)
  1373  	if err != nil {
  1374  		Fatalf("Failed to read password file: %v", err)
  1375  	}
  1376  	lines := strings.Split(string(text), "\n")
  1377  	// Sanitise DOS line endings.
  1378  	for i := range lines {
  1379  		lines[i] = strings.TrimRight(lines[i], "\r")
  1380  	}
  1381  	return lines
  1382  }
  1383  
  1384  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
  1385  	setNodeKey(ctx, cfg)
  1386  	setNAT(ctx, cfg)
  1387  	setListenAddress(ctx, cfg)
  1388  	setBootstrapNodes(ctx, cfg)
  1389  	setBootstrapNodesV5(ctx, cfg)
  1390  
  1391  	lightClient := ctx.String(SyncModeFlag.Name) == "light"
  1392  	lightServer := (ctx.Int(LightServeFlag.Name) != 0)
  1393  
  1394  	lightPeers := ctx.Int(LightMaxPeersFlag.Name)
  1395  	if lightClient && !ctx.IsSet(LightMaxPeersFlag.Name) {
  1396  		// dynamic default - for clients we use 1/10th of the default for servers
  1397  		lightPeers /= 10
  1398  	}
  1399  
  1400  	if ctx.IsSet(MaxPeersFlag.Name) {
  1401  		cfg.MaxPeers = ctx.Int(MaxPeersFlag.Name)
  1402  		if lightServer && !ctx.IsSet(LightMaxPeersFlag.Name) {
  1403  			cfg.MaxPeers += lightPeers
  1404  		}
  1405  	} else {
  1406  		if lightServer {
  1407  			cfg.MaxPeers += lightPeers
  1408  		}
  1409  		if lightClient && ctx.IsSet(LightMaxPeersFlag.Name) && cfg.MaxPeers < lightPeers {
  1410  			cfg.MaxPeers = lightPeers
  1411  		}
  1412  	}
  1413  	if !(lightClient || lightServer) {
  1414  		lightPeers = 0
  1415  	}
  1416  	ethPeers := cfg.MaxPeers - lightPeers
  1417  	if lightClient {
  1418  		ethPeers = 0
  1419  	}
  1420  	log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
  1421  
  1422  	if ctx.IsSet(MaxPendingPeersFlag.Name) {
  1423  		cfg.MaxPendingPeers = ctx.Int(MaxPendingPeersFlag.Name)
  1424  	}
  1425  	if ctx.IsSet(NoDiscoverFlag.Name) || lightClient {
  1426  		cfg.NoDiscovery = true
  1427  	}
  1428  
  1429  	// if we're running a light client or server, force enable the v5 peer discovery
  1430  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
  1431  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
  1432  	forceV5Discovery := (lightClient || lightServer) && !ctx.Bool(NoDiscoverFlag.Name)
  1433  	if ctx.IsSet(DiscoveryV5Flag.Name) {
  1434  		cfg.DiscoveryV5 = ctx.Bool(DiscoveryV5Flag.Name)
  1435  	} else if forceV5Discovery {
  1436  		cfg.DiscoveryV5 = true
  1437  	}
  1438  
  1439  	if netrestrict := ctx.String(NetrestrictFlag.Name); netrestrict != "" {
  1440  		list, err := netutil.ParseNetlist(netrestrict)
  1441  		if err != nil {
  1442  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
  1443  		}
  1444  		cfg.NetRestrict = list
  1445  	}
  1446  
  1447  	if ctx.Bool(DeveloperFlag.Name) {
  1448  		// --dev mode can't use p2p networking.
  1449  		cfg.MaxPeers = 0
  1450  		cfg.ListenAddr = ""
  1451  		cfg.NoDial = true
  1452  		cfg.NoDiscovery = true
  1453  		cfg.DiscoveryV5 = false
  1454  	}
  1455  }
  1456  
  1457  // SetNodeConfig applies node-related command line flags to the config.
  1458  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
  1459  	SetP2PConfig(ctx, &cfg.P2P)
  1460  	setIPC(ctx, cfg)
  1461  	setHTTP(ctx, cfg)
  1462  	setGraphQL(ctx, cfg)
  1463  	setWS(ctx, cfg)
  1464  	setNodeUserIdent(ctx, cfg)
  1465  	SetDataDir(ctx, cfg)
  1466  	setSmartCard(ctx, cfg)
  1467  
  1468  	if ctx.IsSet(JWTSecretFlag.Name) {
  1469  		cfg.JWTSecret = ctx.String(JWTSecretFlag.Name)
  1470  	}
  1471  
  1472  	if ctx.IsSet(ExternalSignerFlag.Name) {
  1473  		cfg.ExternalSigner = ctx.String(ExternalSignerFlag.Name)
  1474  	}
  1475  
  1476  	if ctx.IsSet(KeyStoreDirFlag.Name) {
  1477  		cfg.KeyStoreDir = ctx.String(KeyStoreDirFlag.Name)
  1478  	}
  1479  	if ctx.IsSet(DeveloperFlag.Name) {
  1480  		cfg.UseLightweightKDF = true
  1481  	}
  1482  	if ctx.IsSet(LightKDFFlag.Name) {
  1483  		cfg.UseLightweightKDF = ctx.Bool(LightKDFFlag.Name)
  1484  	}
  1485  	if ctx.IsSet(NoUSBFlag.Name) || cfg.NoUSB {
  1486  		log.Warn("Option nousb is deprecated and USB is deactivated by default. Use --usb to enable")
  1487  	}
  1488  	if ctx.IsSet(USBFlag.Name) {
  1489  		cfg.USB = ctx.Bool(USBFlag.Name)
  1490  	}
  1491  	if ctx.IsSet(InsecureUnlockAllowedFlag.Name) {
  1492  		cfg.InsecureUnlockAllowed = ctx.Bool(InsecureUnlockAllowedFlag.Name)
  1493  	}
  1494  }
  1495  
  1496  func setSmartCard(ctx *cli.Context, cfg *node.Config) {
  1497  	// Skip enabling smartcards if no path is set
  1498  	path := ctx.String(SmartCardDaemonPathFlag.Name)
  1499  	if path == "" {
  1500  		return
  1501  	}
  1502  	// Sanity check that the smartcard path is valid
  1503  	fi, err := os.Stat(path)
  1504  	if err != nil {
  1505  		log.Info("Smartcard socket not found, disabling", "err", err)
  1506  		return
  1507  	}
  1508  	if fi.Mode()&os.ModeType != os.ModeSocket {
  1509  		log.Error("Invalid smartcard daemon path", "path", path, "type", fi.Mode().String())
  1510  		return
  1511  	}
  1512  	// Smartcard daemon path exists and is a socket, enable it
  1513  	cfg.SmartCardDaemonPath = path
  1514  }
  1515  
  1516  func SetDataDir(ctx *cli.Context, cfg *node.Config) {
  1517  	switch {
  1518  	case ctx.IsSet(DataDirFlag.Name):
  1519  		cfg.DataDir = ctx.String(DataDirFlag.Name)
  1520  	case ctx.Bool(DeveloperFlag.Name):
  1521  		cfg.DataDir = "" // unless explicitly requested, use memory databases
  1522  	case ctx.Bool(RopstenFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1523  		// Maintain compatibility with older Geth configurations storing the
  1524  		// Ropsten database in `testnet` instead of `ropsten`.
  1525  		legacyPath := filepath.Join(node.DefaultDataDir(), "testnet")
  1526  		if common.FileExist(legacyPath) {
  1527  			log.Warn("Using the deprecated `testnet` datadir. Future versions will store the Ropsten chain in `ropsten`.")
  1528  			cfg.DataDir = legacyPath
  1529  		} else {
  1530  			cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten")
  1531  		}
  1532  
  1533  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "ropsten")
  1534  	case ctx.Bool(RinkebyFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1535  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
  1536  	case ctx.Bool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1537  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli")
  1538  	case ctx.Bool(SepoliaFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1539  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "sepolia")
  1540  	case ctx.Bool(KilnFlag.Name) && cfg.DataDir == node.DefaultDataDir():
  1541  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "kiln")
  1542  	}
  1543  }
  1544  
  1545  func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) {
  1546  	// If we are running the light client, apply another group
  1547  	// settings for gas oracle.
  1548  	if light {
  1549  		*cfg = ethconfig.LightClientGPO
  1550  	}
  1551  	if ctx.IsSet(GpoBlocksFlag.Name) {
  1552  		cfg.Blocks = ctx.Int(GpoBlocksFlag.Name)
  1553  	}
  1554  	if ctx.IsSet(GpoPercentileFlag.Name) {
  1555  		cfg.Percentile = ctx.Int(GpoPercentileFlag.Name)
  1556  	}
  1557  	if ctx.IsSet(GpoMaxGasPriceFlag.Name) {
  1558  		cfg.MaxPrice = big.NewInt(ctx.Int64(GpoMaxGasPriceFlag.Name))
  1559  	}
  1560  	if ctx.IsSet(GpoIgnoreGasPriceFlag.Name) {
  1561  		cfg.IgnorePrice = big.NewInt(ctx.Int64(GpoIgnoreGasPriceFlag.Name))
  1562  	}
  1563  }
  1564  
  1565  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
  1566  	if ctx.IsSet(TxPoolLocalsFlag.Name) {
  1567  		locals := strings.Split(ctx.String(TxPoolLocalsFlag.Name), ",")
  1568  		for _, account := range locals {
  1569  			if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
  1570  				Fatalf("Invalid account in --txpool.locals: %s", trimmed)
  1571  			} else {
  1572  				cfg.Locals = append(cfg.Locals, common.HexToAddress(account))
  1573  			}
  1574  		}
  1575  	}
  1576  	if ctx.IsSet(TxPoolNoLocalsFlag.Name) {
  1577  		cfg.NoLocals = ctx.Bool(TxPoolNoLocalsFlag.Name)
  1578  	}
  1579  	if ctx.IsSet(TxPoolJournalFlag.Name) {
  1580  		cfg.Journal = ctx.String(TxPoolJournalFlag.Name)
  1581  	}
  1582  	if ctx.IsSet(TxPoolRejournalFlag.Name) {
  1583  		cfg.Rejournal = ctx.Duration(TxPoolRejournalFlag.Name)
  1584  	}
  1585  	if ctx.IsSet(TxPoolPriceLimitFlag.Name) {
  1586  		cfg.PriceLimit = ctx.Uint64(TxPoolPriceLimitFlag.Name)
  1587  	}
  1588  	if ctx.IsSet(TxPoolPriceBumpFlag.Name) {
  1589  		cfg.PriceBump = ctx.Uint64(TxPoolPriceBumpFlag.Name)
  1590  	}
  1591  	if ctx.IsSet(TxPoolAccountSlotsFlag.Name) {
  1592  		cfg.AccountSlots = ctx.Uint64(TxPoolAccountSlotsFlag.Name)
  1593  	}
  1594  	if ctx.IsSet(TxPoolGlobalSlotsFlag.Name) {
  1595  		cfg.GlobalSlots = ctx.Uint64(TxPoolGlobalSlotsFlag.Name)
  1596  	}
  1597  	if ctx.IsSet(TxPoolAccountQueueFlag.Name) {
  1598  		cfg.AccountQueue = ctx.Uint64(TxPoolAccountQueueFlag.Name)
  1599  	}
  1600  	if ctx.IsSet(TxPoolGlobalQueueFlag.Name) {
  1601  		cfg.GlobalQueue = ctx.Uint64(TxPoolGlobalQueueFlag.Name)
  1602  	}
  1603  	if ctx.IsSet(TxPoolLifetimeFlag.Name) {
  1604  		cfg.Lifetime = ctx.Duration(TxPoolLifetimeFlag.Name)
  1605  	}
  1606  }
  1607  
  1608  func setEthash(ctx *cli.Context, cfg *ethconfig.Config) {
  1609  	if ctx.IsSet(EthashCacheDirFlag.Name) {
  1610  		cfg.Ethash.CacheDir = ctx.String(EthashCacheDirFlag.Name)
  1611  	}
  1612  	if ctx.IsSet(EthashDatasetDirFlag.Name) {
  1613  		cfg.Ethash.DatasetDir = ctx.String(EthashDatasetDirFlag.Name)
  1614  	}
  1615  	if ctx.IsSet(EthashCachesInMemoryFlag.Name) {
  1616  		cfg.Ethash.CachesInMem = ctx.Int(EthashCachesInMemoryFlag.Name)
  1617  	}
  1618  	if ctx.IsSet(EthashCachesOnDiskFlag.Name) {
  1619  		cfg.Ethash.CachesOnDisk = ctx.Int(EthashCachesOnDiskFlag.Name)
  1620  	}
  1621  	if ctx.IsSet(EthashCachesLockMmapFlag.Name) {
  1622  		cfg.Ethash.CachesLockMmap = ctx.Bool(EthashCachesLockMmapFlag.Name)
  1623  	}
  1624  	if ctx.IsSet(EthashDatasetsInMemoryFlag.Name) {
  1625  		cfg.Ethash.DatasetsInMem = ctx.Int(EthashDatasetsInMemoryFlag.Name)
  1626  	}
  1627  	if ctx.IsSet(EthashDatasetsOnDiskFlag.Name) {
  1628  		cfg.Ethash.DatasetsOnDisk = ctx.Int(EthashDatasetsOnDiskFlag.Name)
  1629  	}
  1630  	if ctx.IsSet(EthashDatasetsLockMmapFlag.Name) {
  1631  		cfg.Ethash.DatasetsLockMmap = ctx.Bool(EthashDatasetsLockMmapFlag.Name)
  1632  	}
  1633  }
  1634  
  1635  func setMiner(ctx *cli.Context, cfg *miner.Config) {
  1636  	if ctx.IsSet(MinerNotifyFlag.Name) {
  1637  		cfg.Notify = strings.Split(ctx.String(MinerNotifyFlag.Name), ",")
  1638  	}
  1639  	cfg.NotifyFull = ctx.Bool(MinerNotifyFullFlag.Name)
  1640  	if ctx.IsSet(MinerExtraDataFlag.Name) {
  1641  		cfg.ExtraData = []byte(ctx.String(MinerExtraDataFlag.Name))
  1642  	}
  1643  	if ctx.IsSet(MinerGasLimitFlag.Name) {
  1644  		cfg.GasCeil = ctx.Uint64(MinerGasLimitFlag.Name)
  1645  	}
  1646  	if ctx.IsSet(MinerGasPriceFlag.Name) {
  1647  		cfg.GasPrice = flags.GlobalBig(ctx, MinerGasPriceFlag.Name)
  1648  	}
  1649  	if ctx.IsSet(MinerRecommitIntervalFlag.Name) {
  1650  		cfg.Recommit = ctx.Duration(MinerRecommitIntervalFlag.Name)
  1651  	}
  1652  	if ctx.IsSet(MinerNoVerifyFlag.Name) {
  1653  		cfg.Noverify = ctx.Bool(MinerNoVerifyFlag.Name)
  1654  	}
  1655  	if ctx.IsSet(LegacyMinerGasTargetFlag.Name) {
  1656  		log.Warn("The generic --miner.gastarget flag is deprecated and will be removed in the future!")
  1657  	}
  1658  }
  1659  
  1660  func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
  1661  	requiredBlocks := ctx.String(EthRequiredBlocksFlag.Name)
  1662  	if requiredBlocks == "" {
  1663  		if ctx.IsSet(LegacyWhitelistFlag.Name) {
  1664  			log.Warn("The flag --whitelist is deprecated and will be removed, please use --eth.requiredblocks")
  1665  			requiredBlocks = ctx.String(LegacyWhitelistFlag.Name)
  1666  		} else {
  1667  			return
  1668  		}
  1669  	}
  1670  	cfg.RequiredBlocks = make(map[uint64]common.Hash)
  1671  	for _, entry := range strings.Split(requiredBlocks, ",") {
  1672  		parts := strings.Split(entry, "=")
  1673  		if len(parts) != 2 {
  1674  			Fatalf("Invalid required block entry: %s", entry)
  1675  		}
  1676  		number, err := strconv.ParseUint(parts[0], 0, 64)
  1677  		if err != nil {
  1678  			Fatalf("Invalid required block number %s: %v", parts[0], err)
  1679  		}
  1680  		var hash common.Hash
  1681  		if err = hash.UnmarshalText([]byte(parts[1])); err != nil {
  1682  			Fatalf("Invalid required block hash %s: %v", parts[1], err)
  1683  		}
  1684  		cfg.RequiredBlocks[number] = hash
  1685  	}
  1686  }
  1687  
  1688  // CheckExclusive verifies that only a single instance of the provided flags was
  1689  // set by the user. Each flag might optionally be followed by a string type to
  1690  // specialize it further.
  1691  func CheckExclusive(ctx *cli.Context, args ...interface{}) {
  1692  	set := make([]string, 0, 1)
  1693  	for i := 0; i < len(args); i++ {
  1694  		// Make sure the next argument is a flag and skip if not set
  1695  		flag, ok := args[i].(cli.Flag)
  1696  		if !ok {
  1697  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
  1698  		}
  1699  		// Check if next arg extends current and expand its name if so
  1700  		name := flag.Names()[0]
  1701  
  1702  		if i+1 < len(args) {
  1703  			switch option := args[i+1].(type) {
  1704  			case string:
  1705  				// Extended flag check, make sure value set doesn't conflict with passed in option
  1706  				if ctx.String(flag.Names()[0]) == option {
  1707  					name += "=" + option
  1708  					set = append(set, "--"+name)
  1709  				}
  1710  				// shift arguments and continue
  1711  				i++
  1712  				continue
  1713  
  1714  			case cli.Flag:
  1715  			default:
  1716  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
  1717  			}
  1718  		}
  1719  		// Mark the flag if it's set
  1720  		if ctx.IsSet(flag.Names()[0]) {
  1721  			set = append(set, "--"+name)
  1722  		}
  1723  	}
  1724  	if len(set) > 1 {
  1725  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
  1726  	}
  1727  }
  1728  
  1729  // SetEthConfig applies eth-related command line flags to the config.
  1730  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
  1731  	// Avoid conflicting network flags
  1732  	CheckExclusive(ctx, MainnetFlag, DeveloperFlag, RopstenFlag, RinkebyFlag, GoerliFlag, SepoliaFlag, KilnFlag)
  1733  	CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light")
  1734  	CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
  1735  	if ctx.String(GCModeFlag.Name) == "archive" && ctx.Uint64(TxLookupLimitFlag.Name) != 0 {
  1736  		ctx.Set(TxLookupLimitFlag.Name, "0")
  1737  		log.Warn("Disable transaction unindexing for archive node")
  1738  	}
  1739  	if ctx.IsSet(LightServeFlag.Name) && ctx.Uint64(TxLookupLimitFlag.Name) != 0 {
  1740  		log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited")
  1741  	}
  1742  	var ks *keystore.KeyStore
  1743  	if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
  1744  		ks = keystores[0].(*keystore.KeyStore)
  1745  	}
  1746  	setEtherbase(ctx, ks, cfg)
  1747  	setGPO(ctx, &cfg.GPO, ctx.String(SyncModeFlag.Name) == "light")
  1748  	setTxPool(ctx, &cfg.TxPool)
  1749  	setEthash(ctx, cfg)
  1750  	setMiner(ctx, &cfg.Miner)
  1751  	setRequiredBlocks(ctx, cfg)
  1752  	setLes(ctx, cfg)
  1753  
  1754  	// Cap the cache allowance and tune the garbage collector
  1755  	mem, err := gopsutil.VirtualMemory()
  1756  	if err == nil {
  1757  		if 32<<(^uintptr(0)>>63) == 32 && mem.Total > 2*1024*1024*1024 {
  1758  			log.Warn("Lowering memory allowance on 32bit arch", "available", mem.Total/1024/1024, "addressable", 2*1024)
  1759  			mem.Total = 2 * 1024 * 1024 * 1024
  1760  		}
  1761  		allowance := int(mem.Total / 1024 / 1024 / 3)
  1762  		if cache := ctx.Int(CacheFlag.Name); cache > allowance {
  1763  			log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance)
  1764  			ctx.Set(CacheFlag.Name, strconv.Itoa(allowance))
  1765  		}
  1766  	}
  1767  	// Ensure Go's GC ignores the database cache for trigger percentage
  1768  	cache := ctx.Int(CacheFlag.Name)
  1769  	gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024)))
  1770  
  1771  	log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
  1772  	godebug.SetGCPercent(int(gogc))
  1773  
  1774  	if ctx.IsSet(SyncModeFlag.Name) {
  1775  		cfg.SyncMode = *flags.GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
  1776  	}
  1777  	if ctx.IsSet(NetworkIdFlag.Name) {
  1778  		cfg.NetworkId = ctx.Uint64(NetworkIdFlag.Name)
  1779  	}
  1780  	if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheDatabaseFlag.Name) {
  1781  		cfg.DatabaseCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
  1782  	}
  1783  	cfg.DatabaseHandles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name))
  1784  	if ctx.IsSet(AncientFlag.Name) {
  1785  		cfg.DatabaseFreezer = ctx.String(AncientFlag.Name)
  1786  	}
  1787  
  1788  	if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1789  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1790  	}
  1791  	if ctx.IsSet(GCModeFlag.Name) {
  1792  		cfg.NoPruning = ctx.String(GCModeFlag.Name) == "archive"
  1793  	}
  1794  	if ctx.IsSet(CacheNoPrefetchFlag.Name) {
  1795  		cfg.NoPrefetch = ctx.Bool(CacheNoPrefetchFlag.Name)
  1796  	}
  1797  	// Read the value from the flag no matter if it's set or not.
  1798  	cfg.Preimages = ctx.Bool(CachePreimagesFlag.Name)
  1799  	if cfg.NoPruning && !cfg.Preimages {
  1800  		cfg.Preimages = true
  1801  		log.Info("Enabling recording of key preimages since archive mode is used")
  1802  	}
  1803  	if ctx.IsSet(TxLookupLimitFlag.Name) {
  1804  		cfg.TxLookupLimit = ctx.Uint64(TxLookupLimitFlag.Name)
  1805  	}
  1806  	if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
  1807  		cfg.TrieCleanCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
  1808  	}
  1809  	if ctx.IsSet(CacheTrieJournalFlag.Name) {
  1810  		cfg.TrieCleanCacheJournal = ctx.String(CacheTrieJournalFlag.Name)
  1811  	}
  1812  	if ctx.IsSet(CacheTrieRejournalFlag.Name) {
  1813  		cfg.TrieCleanCacheRejournal = ctx.Duration(CacheTrieRejournalFlag.Name)
  1814  	}
  1815  	if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
  1816  		cfg.TrieDirtyCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
  1817  	}
  1818  	if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) {
  1819  		cfg.SnapshotCache = ctx.Int(CacheFlag.Name) * ctx.Int(CacheSnapshotFlag.Name) / 100
  1820  	}
  1821  	if !ctx.Bool(SnapshotFlag.Name) {
  1822  		// If snap-sync is requested, this flag is also required
  1823  		if cfg.SyncMode == downloader.SnapSync {
  1824  			log.Info("Snap sync requested, enabling --snapshot")
  1825  		} else {
  1826  			cfg.TrieCleanCache += cfg.SnapshotCache
  1827  			cfg.SnapshotCache = 0 // Disabled
  1828  		}
  1829  	}
  1830  	if ctx.IsSet(DocRootFlag.Name) {
  1831  		cfg.DocRoot = ctx.String(DocRootFlag.Name)
  1832  	}
  1833  	if ctx.IsSet(VMEnableDebugFlag.Name) {
  1834  		// TODO(fjl): force-enable this in --dev mode
  1835  		cfg.EnablePreimageRecording = ctx.Bool(VMEnableDebugFlag.Name)
  1836  	}
  1837  
  1838  	if ctx.IsSet(RPCGlobalGasCapFlag.Name) {
  1839  		cfg.RPCGasCap = ctx.Uint64(RPCGlobalGasCapFlag.Name)
  1840  	}
  1841  	if cfg.RPCGasCap != 0 {
  1842  		log.Info("Set global gas cap", "cap", cfg.RPCGasCap)
  1843  	} else {
  1844  		log.Info("Global gas cap disabled")
  1845  	}
  1846  	if ctx.IsSet(RPCGlobalEVMTimeoutFlag.Name) {
  1847  		cfg.RPCEVMTimeout = ctx.Duration(RPCGlobalEVMTimeoutFlag.Name)
  1848  	}
  1849  	if ctx.IsSet(RPCGlobalTxFeeCapFlag.Name) {
  1850  		cfg.RPCTxFeeCap = ctx.Float64(RPCGlobalTxFeeCapFlag.Name)
  1851  	}
  1852  	if ctx.IsSet(NoDiscoverFlag.Name) {
  1853  		cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs = []string{}, []string{}
  1854  	} else if ctx.IsSet(DNSDiscoveryFlag.Name) {
  1855  		urls := ctx.String(DNSDiscoveryFlag.Name)
  1856  		if urls == "" {
  1857  			cfg.EthDiscoveryURLs = []string{}
  1858  		} else {
  1859  			cfg.EthDiscoveryURLs = SplitAndTrim(urls)
  1860  		}
  1861  	}
  1862  	// Override any default configs for hard coded networks.
  1863  	switch {
  1864  	case ctx.Bool(MainnetFlag.Name):
  1865  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1866  			cfg.NetworkId = 1
  1867  		}
  1868  		cfg.Genesis = core.DefaultGenesisBlock()
  1869  		SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
  1870  	case ctx.Bool(RopstenFlag.Name):
  1871  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1872  			cfg.NetworkId = 3
  1873  		}
  1874  		cfg.Genesis = core.DefaultRopstenGenesisBlock()
  1875  		SetDNSDiscoveryDefaults(cfg, params.RopstenGenesisHash)
  1876  	case ctx.Bool(SepoliaFlag.Name):
  1877  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1878  			cfg.NetworkId = 11155111
  1879  		}
  1880  		cfg.Genesis = core.DefaultSepoliaGenesisBlock()
  1881  		SetDNSDiscoveryDefaults(cfg, params.SepoliaGenesisHash)
  1882  	case ctx.Bool(RinkebyFlag.Name):
  1883  		log.Warn("")
  1884  		log.Warn("--------------------------------------------------------------------------------")
  1885  		log.Warn("Please note, Rinkeby has been deprecated. It will still work for the time being,")
  1886  		log.Warn("but there will be no further hard-forks shipped for it. Eventually the network")
  1887  		log.Warn("will be permanently halted after the other networks transition through the merge")
  1888  		log.Warn("and prove stable enough. For the most future proof testnet, choose Sepolia as")
  1889  		log.Warn("your replacement environment (--sepolia instead of --rinkeby).")
  1890  		log.Warn("--------------------------------------------------------------------------------")
  1891  		log.Warn("")
  1892  
  1893  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1894  			cfg.NetworkId = 4
  1895  		}
  1896  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1897  		SetDNSDiscoveryDefaults(cfg, params.RinkebyGenesisHash)
  1898  	case ctx.Bool(GoerliFlag.Name):
  1899  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1900  			cfg.NetworkId = 5
  1901  		}
  1902  		cfg.Genesis = core.DefaultGoerliGenesisBlock()
  1903  		SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash)
  1904  	case ctx.Bool(KilnFlag.Name):
  1905  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1906  			cfg.NetworkId = 1337802
  1907  		}
  1908  		cfg.Genesis = core.DefaultKilnGenesisBlock()
  1909  		SetDNSDiscoveryDefaults(cfg, params.KilnGenesisHash)
  1910  	case ctx.Bool(DeveloperFlag.Name):
  1911  		if !ctx.IsSet(NetworkIdFlag.Name) {
  1912  			cfg.NetworkId = 1337
  1913  		}
  1914  		cfg.SyncMode = downloader.FullSync
  1915  		// Create new developer account or reuse existing one
  1916  		var (
  1917  			developer  accounts.Account
  1918  			passphrase string
  1919  			err        error
  1920  		)
  1921  		if list := MakePasswordList(ctx); len(list) > 0 {
  1922  			// Just take the first value. Although the function returns a possible multiple values and
  1923  			// some usages iterate through them as attempts, that doesn't make sense in this setting,
  1924  			// when we're definitely concerned with only one account.
  1925  			passphrase = list[0]
  1926  		}
  1927  		// setEtherbase has been called above, configuring the miner address from command line flags.
  1928  		if cfg.Miner.Etherbase != (common.Address{}) {
  1929  			developer = accounts.Account{Address: cfg.Miner.Etherbase}
  1930  		} else if accs := ks.Accounts(); len(accs) > 0 {
  1931  			developer = ks.Accounts()[0]
  1932  		} else {
  1933  			developer, err = ks.NewAccount(passphrase)
  1934  			if err != nil {
  1935  				Fatalf("Failed to create developer account: %v", err)
  1936  			}
  1937  		}
  1938  		if err := ks.Unlock(developer, passphrase); err != nil {
  1939  			Fatalf("Failed to unlock developer account: %v", err)
  1940  		}
  1941  		log.Info("Using developer account", "address", developer.Address)
  1942  
  1943  		// Create a new developer genesis block or reuse existing one
  1944  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.Int(DeveloperPeriodFlag.Name)), ctx.Uint64(DeveloperGasLimitFlag.Name), developer.Address)
  1945  		if ctx.IsSet(DataDirFlag.Name) {
  1946  			// If datadir doesn't exist we need to open db in write-mode
  1947  			// so leveldb can create files.
  1948  			readonly := true
  1949  			if !common.FileExist(stack.ResolvePath("chaindata")) {
  1950  				readonly = false
  1951  			}
  1952  			// Check if we have an already initialized chain and fall back to
  1953  			// that if so. Otherwise we need to generate a new genesis spec.
  1954  			chaindb := MakeChainDatabase(ctx, stack, readonly)
  1955  			if rawdb.ReadCanonicalHash(chaindb, 0) != (common.Hash{}) {
  1956  				cfg.Genesis = nil // fallback to db content
  1957  			}
  1958  			chaindb.Close()
  1959  		}
  1960  		if !ctx.IsSet(MinerGasPriceFlag.Name) {
  1961  			cfg.Miner.GasPrice = big.NewInt(1)
  1962  		}
  1963  	default:
  1964  		if cfg.NetworkId == 1 {
  1965  			SetDNSDiscoveryDefaults(cfg, params.MainnetGenesisHash)
  1966  		}
  1967  	}
  1968  }
  1969  
  1970  // SetDNSDiscoveryDefaults configures DNS discovery with the given URL if
  1971  // no URLs are set.
  1972  func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
  1973  	if cfg.EthDiscoveryURLs != nil {
  1974  		return // already set through flags/config
  1975  	}
  1976  	protocol := "all"
  1977  	if cfg.SyncMode == downloader.LightSync {
  1978  		protocol = "les"
  1979  	}
  1980  	if url := params.KnownDNSNetwork(genesis, protocol); url != "" {
  1981  		cfg.EthDiscoveryURLs = []string{url}
  1982  		cfg.SnapDiscoveryURLs = cfg.EthDiscoveryURLs
  1983  	}
  1984  }
  1985  
  1986  // RegisterEthService adds an Ethereum client to the stack.
  1987  // The second return value is the full node instance, which may be nil if the
  1988  // node is running as a light client.
  1989  func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend, *eth.Ethereum) {
  1990  	if cfg.SyncMode == downloader.LightSync {
  1991  		backend, err := les.New(stack, cfg)
  1992  		if err != nil {
  1993  			Fatalf("Failed to register the Ethereum service: %v", err)
  1994  		}
  1995  		stack.RegisterAPIs(tracers.APIs(backend.ApiBackend))
  1996  		if backend.BlockChain().Config().TerminalTotalDifficulty != nil {
  1997  			if err := lescatalyst.Register(stack, backend); err != nil {
  1998  				Fatalf("Failed to register the catalyst service: %v", err)
  1999  			}
  2000  		}
  2001  		return backend.ApiBackend, nil
  2002  	}
  2003  	backend, err := eth.New(stack, cfg)
  2004  	if err != nil {
  2005  		Fatalf("Failed to register the Ethereum service: %v", err)
  2006  	}
  2007  	if cfg.LightServ > 0 {
  2008  		_, err := les.NewLesServer(stack, backend, cfg)
  2009  		if err != nil {
  2010  			Fatalf("Failed to create the LES server: %v", err)
  2011  		}
  2012  	}
  2013  	if backend.BlockChain().Config().TerminalTotalDifficulty != nil {
  2014  		if err := ethcatalyst.Register(stack, backend); err != nil {
  2015  			Fatalf("Failed to register the catalyst service: %v", err)
  2016  		}
  2017  	}
  2018  	stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
  2019  	return backend.APIBackend, backend
  2020  }
  2021  
  2022  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  2023  // the given node.
  2024  func RegisterEthStatsService(stack *node.Node, backend ethapi.Backend, url string) {
  2025  	if err := ethstats.New(stack, backend, backend.Engine(), url); err != nil {
  2026  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  2027  	}
  2028  }
  2029  
  2030  // RegisterGraphQLService is a utility function to construct a new service and register it against a node.
  2031  func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, cfg node.Config) {
  2032  	if err := graphql.New(stack, backend, cfg.GraphQLCors, cfg.GraphQLVirtualHosts); err != nil {
  2033  		Fatalf("Failed to register the GraphQL service: %v", err)
  2034  	}
  2035  }
  2036  
  2037  func SetupMetrics(ctx *cli.Context) {
  2038  	if metrics.Enabled {
  2039  		log.Info("Enabling metrics collection")
  2040  
  2041  		var (
  2042  			enableExport   = ctx.Bool(MetricsEnableInfluxDBFlag.Name)
  2043  			enableExportV2 = ctx.Bool(MetricsEnableInfluxDBV2Flag.Name)
  2044  		)
  2045  
  2046  		if enableExport || enableExportV2 {
  2047  			CheckExclusive(ctx, MetricsEnableInfluxDBFlag, MetricsEnableInfluxDBV2Flag)
  2048  
  2049  			v1FlagIsSet := ctx.IsSet(MetricsInfluxDBUsernameFlag.Name) ||
  2050  				ctx.IsSet(MetricsInfluxDBPasswordFlag.Name)
  2051  
  2052  			v2FlagIsSet := ctx.IsSet(MetricsInfluxDBTokenFlag.Name) ||
  2053  				ctx.IsSet(MetricsInfluxDBOrganizationFlag.Name) ||
  2054  				ctx.IsSet(MetricsInfluxDBBucketFlag.Name)
  2055  
  2056  			if enableExport && v2FlagIsSet {
  2057  				Fatalf("Flags --influxdb.metrics.organization, --influxdb.metrics.token, --influxdb.metrics.bucket are only available for influxdb-v2")
  2058  			} else if enableExportV2 && v1FlagIsSet {
  2059  				Fatalf("Flags --influxdb.metrics.username, --influxdb.metrics.password are only available for influxdb-v1")
  2060  			}
  2061  		}
  2062  
  2063  		var (
  2064  			endpoint = ctx.String(MetricsInfluxDBEndpointFlag.Name)
  2065  			database = ctx.String(MetricsInfluxDBDatabaseFlag.Name)
  2066  			username = ctx.String(MetricsInfluxDBUsernameFlag.Name)
  2067  			password = ctx.String(MetricsInfluxDBPasswordFlag.Name)
  2068  
  2069  			token        = ctx.String(MetricsInfluxDBTokenFlag.Name)
  2070  			bucket       = ctx.String(MetricsInfluxDBBucketFlag.Name)
  2071  			organization = ctx.String(MetricsInfluxDBOrganizationFlag.Name)
  2072  		)
  2073  
  2074  		if enableExport {
  2075  			tagsMap := SplitTagsFlag(ctx.String(MetricsInfluxDBTagsFlag.Name))
  2076  
  2077  			log.Info("Enabling metrics export to InfluxDB")
  2078  
  2079  			go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap)
  2080  		} else if enableExportV2 {
  2081  			tagsMap := SplitTagsFlag(ctx.String(MetricsInfluxDBTagsFlag.Name))
  2082  
  2083  			log.Info("Enabling metrics export to InfluxDB (v2)")
  2084  
  2085  			go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap)
  2086  		}
  2087  
  2088  		if ctx.IsSet(MetricsHTTPFlag.Name) {
  2089  			address := fmt.Sprintf("%s:%d", ctx.String(MetricsHTTPFlag.Name), ctx.Int(MetricsPortFlag.Name))
  2090  			log.Info("Enabling stand-alone metrics HTTP endpoint", "address", address)
  2091  			exp.Setup(address)
  2092  		}
  2093  	}
  2094  }
  2095  
  2096  func SplitTagsFlag(tagsFlag string) map[string]string {
  2097  	tags := strings.Split(tagsFlag, ",")
  2098  	tagsMap := map[string]string{}
  2099  
  2100  	for _, t := range tags {
  2101  		if t != "" {
  2102  			kv := strings.Split(t, "=")
  2103  
  2104  			if len(kv) == 2 {
  2105  				tagsMap[kv[0]] = kv[1]
  2106  			}
  2107  		}
  2108  	}
  2109  
  2110  	return tagsMap
  2111  }
  2112  
  2113  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  2114  func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.Database {
  2115  	var (
  2116  		cache   = ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100
  2117  		handles = MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name))
  2118  
  2119  		err     error
  2120  		chainDb ethdb.Database
  2121  	)
  2122  	switch {
  2123  	case ctx.IsSet(RemoteDBFlag.Name):
  2124  		log.Info("Using remote db", "url", ctx.String(RemoteDBFlag.Name))
  2125  		chainDb, err = remotedb.New(ctx.String(RemoteDBFlag.Name))
  2126  	case ctx.String(SyncModeFlag.Name) == "light":
  2127  		chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly)
  2128  	default:
  2129  		chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.String(AncientFlag.Name), "", readonly)
  2130  	}
  2131  	if err != nil {
  2132  		Fatalf("Could not open database: %v", err)
  2133  	}
  2134  	return chainDb
  2135  }
  2136  
  2137  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  2138  	var genesis *core.Genesis
  2139  	switch {
  2140  	case ctx.Bool(MainnetFlag.Name):
  2141  		genesis = core.DefaultGenesisBlock()
  2142  	case ctx.Bool(RopstenFlag.Name):
  2143  		genesis = core.DefaultRopstenGenesisBlock()
  2144  	case ctx.Bool(SepoliaFlag.Name):
  2145  		genesis = core.DefaultSepoliaGenesisBlock()
  2146  	case ctx.Bool(RinkebyFlag.Name):
  2147  		genesis = core.DefaultRinkebyGenesisBlock()
  2148  	case ctx.Bool(GoerliFlag.Name):
  2149  		genesis = core.DefaultGoerliGenesisBlock()
  2150  	case ctx.Bool(KilnFlag.Name):
  2151  		genesis = core.DefaultKilnGenesisBlock()
  2152  	case ctx.Bool(DeveloperFlag.Name):
  2153  		Fatalf("Developer chains are ephemeral")
  2154  	}
  2155  	return genesis
  2156  }
  2157  
  2158  // MakeChain creates a chain manager from set command line flags.
  2159  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) {
  2160  	var err error
  2161  	chainDb = MakeChainDatabase(ctx, stack, false) // TODO(rjl493456442) support read-only database
  2162  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
  2163  	if err != nil {
  2164  		Fatalf("%v", err)
  2165  	}
  2166  
  2167  	var engine consensus.Engine
  2168  	ethashConf := ethconfig.Defaults.Ethash
  2169  	if ctx.Bool(FakePoWFlag.Name) {
  2170  		ethashConf.PowMode = ethash.ModeFake
  2171  	}
  2172  	engine = ethconfig.CreateConsensusEngine(stack, config, &ethashConf, nil, false, chainDb)
  2173  	if gcmode := ctx.String(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  2174  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  2175  	}
  2176  	cache := &core.CacheConfig{
  2177  		TrieCleanLimit:      ethconfig.Defaults.TrieCleanCache,
  2178  		TrieCleanNoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name),
  2179  		TrieDirtyLimit:      ethconfig.Defaults.TrieDirtyCache,
  2180  		TrieDirtyDisabled:   ctx.String(GCModeFlag.Name) == "archive",
  2181  		TrieTimeLimit:       ethconfig.Defaults.TrieTimeout,
  2182  		SnapshotLimit:       ethconfig.Defaults.SnapshotCache,
  2183  		Preimages:           ctx.Bool(CachePreimagesFlag.Name),
  2184  	}
  2185  	if cache.TrieDirtyDisabled && !cache.Preimages {
  2186  		cache.Preimages = true
  2187  		log.Info("Enabling recording of key preimages since archive mode is used")
  2188  	}
  2189  	if !ctx.Bool(SnapshotFlag.Name) {
  2190  		cache.SnapshotLimit = 0 // Disabled
  2191  	}
  2192  	if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheTrieFlag.Name) {
  2193  		cache.TrieCleanLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheTrieFlag.Name) / 100
  2194  	}
  2195  	if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheGCFlag.Name) {
  2196  		cache.TrieDirtyLimit = ctx.Int(CacheFlag.Name) * ctx.Int(CacheGCFlag.Name) / 100
  2197  	}
  2198  	vmcfg := vm.Config{EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name)}
  2199  
  2200  	// TODO(rjl493456442) disable snapshot generation/wiping if the chain is read only.
  2201  	// Disable transaction indexing/unindexing by default.
  2202  	chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil, nil)
  2203  	if err != nil {
  2204  		Fatalf("Can't create BlockChain: %v", err)
  2205  	}
  2206  	return chain, chainDb
  2207  }
  2208  
  2209  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  2210  // scripts to preload before starting.
  2211  func MakeConsolePreloads(ctx *cli.Context) []string {
  2212  	// Skip preloading if there's nothing to preload
  2213  	if ctx.String(PreloadJSFlag.Name) == "" {
  2214  		return nil
  2215  	}
  2216  	// Otherwise resolve absolute paths and return them
  2217  	var preloads []string
  2218  
  2219  	for _, file := range strings.Split(ctx.String(PreloadJSFlag.Name), ",") {
  2220  		preloads = append(preloads, strings.TrimSpace(file))
  2221  	}
  2222  	return preloads
  2223  }