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