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