github.com/theQRL/go-zond@v0.1.1/cmd/utils/flags.go (about)

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