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