github.com/bearnetworkchain/go-bearnetwork@v1.10.19-0.20220604150648-d63890c2e42b/cmd/utils/flags.go (about)

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