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