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