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