github.com/shyftnetwork/go-empyrean@v1.8.3-0.20191127201940-fbfca9338f04/cmd/utils/flags.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of go-ethereum.
     3  //
     4  // go-ethereum is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // go-ethereum is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU General Public License
    15  // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package utils contains internal helper functions for go-ethereum commands.
    18  package utils
    19  
    20  import (
    21  	"crypto/ecdsa"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"os"
    26  	"path/filepath"
    27  	"strconv"
    28  	"strings"
    29  	"time"
    30  
    31  	"github.com/ShyftNetwork/go-empyrean/accounts"
    32  	"github.com/ShyftNetwork/go-empyrean/accounts/keystore"
    33  	"github.com/ShyftNetwork/go-empyrean/common"
    34  	"github.com/ShyftNetwork/go-empyrean/common/fdlimit"
    35  	"github.com/ShyftNetwork/go-empyrean/consensus"
    36  	"github.com/ShyftNetwork/go-empyrean/consensus/clique"
    37  	"github.com/ShyftNetwork/go-empyrean/consensus/ethash"
    38  	"github.com/ShyftNetwork/go-empyrean/core"
    39  	"github.com/ShyftNetwork/go-empyrean/core/state"
    40  	"github.com/ShyftNetwork/go-empyrean/core/vm"
    41  	"github.com/ShyftNetwork/go-empyrean/crypto"
    42  	"github.com/ShyftNetwork/go-empyrean/dashboard"
    43  	"github.com/ShyftNetwork/go-empyrean/eth"
    44  	"github.com/ShyftNetwork/go-empyrean/eth/downloader"
    45  	"github.com/ShyftNetwork/go-empyrean/eth/gasprice"
    46  	"github.com/ShyftNetwork/go-empyrean/ethdb"
    47  	"github.com/ShyftNetwork/go-empyrean/ethstats"
    48  	"github.com/ShyftNetwork/go-empyrean/les"
    49  	"github.com/ShyftNetwork/go-empyrean/log"
    50  	"github.com/ShyftNetwork/go-empyrean/metrics"
    51  	"github.com/ShyftNetwork/go-empyrean/metrics/influxdb"
    52  	"github.com/ShyftNetwork/go-empyrean/node"
    53  	"github.com/ShyftNetwork/go-empyrean/p2p"
    54  	"github.com/ShyftNetwork/go-empyrean/p2p/discv5"
    55  	"github.com/ShyftNetwork/go-empyrean/p2p/enode"
    56  	"github.com/ShyftNetwork/go-empyrean/p2p/nat"
    57  	"github.com/ShyftNetwork/go-empyrean/p2p/netutil"
    58  	"github.com/ShyftNetwork/go-empyrean/params"
    59  	whisper "github.com/ShyftNetwork/go-empyrean/whisper/whisperv6"
    60  	"gopkg.in/urfave/cli.v1"
    61  )
    62  
    63  var (
    64  	CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...]
    65  {{if .cmd.Description}}{{.cmd.Description}}
    66  {{end}}{{if .cmd.Subcommands}}
    67  SUBCOMMANDS:
    68  	{{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    69  	{{end}}{{end}}{{if .categorizedFlags}}
    70  {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS:
    71  {{range $categorized.Flags}}{{"\t"}}{{.}}
    72  {{end}}
    73  {{end}}{{end}}`
    74  )
    75  
    76  func init() {
    77  	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
    78  
    79  VERSION:
    80     {{.Version}}
    81  
    82  COMMANDS:
    83     {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    84     {{end}}{{if .Flags}}
    85  GLOBAL OPTIONS:
    86     {{range .Flags}}{{.}}
    87     {{end}}{{end}}
    88  `
    89  
    90  	cli.CommandHelpTemplate = CommandHelpTemplate
    91  }
    92  
    93  // NewApp creates an app with sane defaults.
    94  func NewApp(gitCommit, usage string) *cli.App {
    95  	app := cli.NewApp()
    96  	app.Name = filepath.Base(os.Args[0])
    97  	app.Author = ""
    98  	//app.Authors = nil
    99  	app.Email = ""
   100  	app.Version = params.VersionWithMeta
   101  	if len(gitCommit) >= 8 {
   102  		app.Version += "-" + gitCommit[:8]
   103  	}
   104  	app.Usage = usage
   105  	return app
   106  }
   107  
   108  // These are all the command line flags we support.
   109  // If you add to this list, please remember to include the
   110  // flag in the appropriate command definition.
   111  //
   112  // The flags are defined here so their names and help texts
   113  // are the same for all commands.
   114  
   115  var (
   116  	// General settings
   117  	DataDirFlag = DirectoryFlag{
   118  		Name:  "datadir",
   119  		Usage: "Data directory for the databases and keystore",
   120  		Value: DirectoryString{node.DefaultDataDir()},
   121  	}
   122  	PostgresFlag = cli.BoolFlag{
   123  		Name:  "disablepg",
   124  		Usage: "Disconnects the postgres instance used for Shyft Shakedown",
   125  	}
   126  	KeyStoreDirFlag = DirectoryFlag{
   127  		Name:  "keystore",
   128  		Usage: "Directory for the keystore (default = inside the datadir)",
   129  	}
   130  	NoUSBFlag = cli.BoolFlag{
   131  		Name:  "nousb",
   132  		Usage: "Disables monitoring for and managing USB hardware wallets",
   133  	}
   134  	NetworkIdFlag = cli.Uint64Flag{
   135  		Name:  "networkid",
   136  		Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)",
   137  		Value: eth.DefaultConfig.NetworkId,
   138  	}
   139  	TestnetFlag = cli.BoolFlag{
   140  		Name:  "testnet",
   141  		Usage: "Ropsten network: pre-configured proof-of-work test network",
   142  	}
   143  	RinkebyFlag = cli.BoolFlag{
   144  		Name:  "rinkeby",
   145  		Usage: "Rinkeby network: pre-configured proof-of-authority test network",
   146  	}
   147  	ConstantinopleOverrideFlag = cli.Uint64Flag{
   148  		Name:  "override.constantinople",
   149  		Usage: "Manually specify constantinople fork-block, overriding the bundled setting",
   150  	}
   151  	DeveloperFlag = cli.BoolFlag{
   152  		Name:  "dev",
   153  		Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
   154  	}
   155  	DeveloperPeriodFlag = cli.IntFlag{
   156  		Name:  "dev.period",
   157  		Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
   158  	}
   159  	IdentityFlag = cli.StringFlag{
   160  		Name:  "identity",
   161  		Usage: "Custom node name",
   162  	}
   163  	DocRootFlag = DirectoryFlag{
   164  		Name:  "docroot",
   165  		Usage: "Document Root for HTTPClient file scheme",
   166  		Value: DirectoryString{homeDir()},
   167  	}
   168  	defaultSyncMode = eth.DefaultConfig.SyncMode
   169  	SyncModeFlag    = TextMarshalerFlag{
   170  		Name:  "syncmode",
   171  		Usage: `Blockchain sync mode ("fast", "full", or "light")`,
   172  		Value: &defaultSyncMode,
   173  	}
   174  	GCModeFlag = cli.StringFlag{
   175  		Name:  "gcmode",
   176  		Usage: `Blockchain garbage collection mode ("full", "archive")`,
   177  		Value: "full",
   178  	}
   179  	LightServFlag = cli.IntFlag{
   180  		Name:  "lightserv",
   181  		Usage: "Maximum percentage of time allowed for serving LES requests (0-90)",
   182  		Value: 0,
   183  	}
   184  	LightPeersFlag = cli.IntFlag{
   185  		Name:  "lightpeers",
   186  		Usage: "Maximum number of LES client peers",
   187  		Value: eth.DefaultConfig.LightPeers,
   188  	}
   189  	LightKDFFlag = cli.BoolFlag{
   190  		Name:  "lightkdf",
   191  		Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
   192  	}
   193  	WhitelistFlag = cli.StringFlag{
   194  		Name:  "whitelist",
   195  		Usage: "Comma separated block number-to-hash mappings to enforce (<number>=<hash>)",
   196  	}
   197  	// Dashboard settings
   198  	DashboardEnabledFlag = cli.BoolFlag{
   199  		Name:  metrics.DashboardEnabledFlag,
   200  		Usage: "Enable the dashboard",
   201  	}
   202  	DashboardAddrFlag = cli.StringFlag{
   203  		Name:  "dashboard.addr",
   204  		Usage: "Dashboard listening interface",
   205  		Value: dashboard.DefaultConfig.Host,
   206  	}
   207  	DashboardPortFlag = cli.IntFlag{
   208  		Name:  "dashboard.host",
   209  		Usage: "Dashboard listening port",
   210  		Value: dashboard.DefaultConfig.Port,
   211  	}
   212  	DashboardRefreshFlag = cli.DurationFlag{
   213  		Name:  "dashboard.refresh",
   214  		Usage: "Dashboard metrics collection refresh rate",
   215  		Value: dashboard.DefaultConfig.Refresh,
   216  	}
   217  	// Ethash settings
   218  	EthashCacheDirFlag = DirectoryFlag{
   219  		Name:  "ethash.cachedir",
   220  		Usage: "Directory to store the ethash verification caches (default = inside the datadir)",
   221  	}
   222  	EthashCachesInMemoryFlag = cli.IntFlag{
   223  		Name:  "ethash.cachesinmem",
   224  		Usage: "Number of recent ethash caches to keep in memory (16MB each)",
   225  		Value: eth.DefaultConfig.Ethash.CachesInMem,
   226  	}
   227  	EthashCachesOnDiskFlag = cli.IntFlag{
   228  		Name:  "ethash.cachesondisk",
   229  		Usage: "Number of recent ethash caches to keep on disk (16MB each)",
   230  		Value: eth.DefaultConfig.Ethash.CachesOnDisk,
   231  	}
   232  	EthashDatasetDirFlag = DirectoryFlag{
   233  		Name:  "ethash.dagdir",
   234  		Usage: "Directory to store the ethash mining DAGs (default = inside home folder)",
   235  		Value: DirectoryString{eth.DefaultConfig.Ethash.DatasetDir},
   236  	}
   237  	EthashDatasetsInMemoryFlag = cli.IntFlag{
   238  		Name:  "ethash.dagsinmem",
   239  		Usage: "Number of recent ethash mining DAGs to keep in memory (1+GB each)",
   240  		Value: eth.DefaultConfig.Ethash.DatasetsInMem,
   241  	}
   242  	EthashDatasetsOnDiskFlag = cli.IntFlag{
   243  		Name:  "ethash.dagsondisk",
   244  		Usage: "Number of recent ethash mining DAGs to keep on disk (1+GB each)",
   245  		Value: eth.DefaultConfig.Ethash.DatasetsOnDisk,
   246  	}
   247  	// Transaction pool settings
   248  	TxPoolLocalsFlag = cli.StringFlag{
   249  		Name:  "txpool.locals",
   250  		Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)",
   251  	}
   252  	TxPoolNoLocalsFlag = cli.BoolFlag{
   253  		Name:  "txpool.nolocals",
   254  		Usage: "Disables price exemptions for locally submitted transactions",
   255  	}
   256  	TxPoolJournalFlag = cli.StringFlag{
   257  		Name:  "txpool.journal",
   258  		Usage: "Disk journal for local transaction to survive node restarts",
   259  		Value: core.DefaultTxPoolConfig.Journal,
   260  	}
   261  	TxPoolRejournalFlag = cli.DurationFlag{
   262  		Name:  "txpool.rejournal",
   263  		Usage: "Time interval to regenerate the local transaction journal",
   264  		Value: core.DefaultTxPoolConfig.Rejournal,
   265  	}
   266  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   267  		Name:  "txpool.pricelimit",
   268  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   269  		Value: eth.DefaultConfig.TxPool.PriceLimit,
   270  	}
   271  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   272  		Name:  "txpool.pricebump",
   273  		Usage: "Price bump percentage to replace an already existing transaction",
   274  		Value: eth.DefaultConfig.TxPool.PriceBump,
   275  	}
   276  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   277  		Name:  "txpool.accountslots",
   278  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   279  		Value: eth.DefaultConfig.TxPool.AccountSlots,
   280  	}
   281  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   282  		Name:  "txpool.globalslots",
   283  		Usage: "Maximum number of executable transaction slots for all accounts",
   284  		Value: eth.DefaultConfig.TxPool.GlobalSlots,
   285  	}
   286  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   287  		Name:  "txpool.accountqueue",
   288  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   289  		Value: eth.DefaultConfig.TxPool.AccountQueue,
   290  	}
   291  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   292  		Name:  "txpool.globalqueue",
   293  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   294  		Value: eth.DefaultConfig.TxPool.GlobalQueue,
   295  	}
   296  	TxPoolLifetimeFlag = cli.DurationFlag{
   297  		Name:  "txpool.lifetime",
   298  		Usage: "Maximum amount of time non-executable transaction are queued",
   299  		Value: eth.DefaultConfig.TxPool.Lifetime,
   300  	}
   301  	// Performance tuning settings
   302  	CacheFlag = cli.IntFlag{
   303  		Name:  "cache",
   304  		Usage: "Megabytes of memory allocated to internal caching",
   305  		Value: 1024,
   306  	}
   307  	CacheDatabaseFlag = cli.IntFlag{
   308  		Name:  "cache.database",
   309  		Usage: "Percentage of cache memory allowance to use for database io",
   310  		Value: 50,
   311  	}
   312  	CacheTrieFlag = cli.IntFlag{
   313  		Name:  "cache.trie",
   314  		Usage: "Percentage of cache memory allowance to use for trie caching",
   315  		Value: 25,
   316  	}
   317  	CacheGCFlag = cli.IntFlag{
   318  		Name:  "cache.gc",
   319  		Usage: "Percentage of cache memory allowance to use for trie pruning",
   320  		Value: 25,
   321  	}
   322  	TrieCacheGenFlag = cli.IntFlag{
   323  		Name:  "trie-cache-gens",
   324  		Usage: "Number of trie node generations to keep in memory",
   325  		Value: int(state.MaxTrieCacheGen),
   326  	}
   327  	// Miner settings
   328  	MiningEnabledFlag = cli.BoolFlag{
   329  		Name:  "mine",
   330  		Usage: "Enable mining",
   331  	}
   332  	MinerThreadsFlag = cli.IntFlag{
   333  		Name:  "miner.threads",
   334  		Usage: "Number of CPU threads to use for mining",
   335  		Value: 0,
   336  	}
   337  	MinerLegacyThreadsFlag = cli.IntFlag{
   338  		Name:  "minerthreads",
   339  		Usage: "Number of CPU threads to use for mining (deprecated, use --miner.threads)",
   340  		Value: 0,
   341  	}
   342  	MinerNotifyFlag = cli.StringFlag{
   343  		Name:  "miner.notify",
   344  		Usage: "Comma separated HTTP URL list to notify of new work packages",
   345  	}
   346  	MinerGasTargetFlag = cli.Uint64Flag{
   347  		Name:  "miner.gastarget",
   348  		Usage: "Target gas floor for mined blocks",
   349  		Value: eth.DefaultConfig.MinerGasFloor,
   350  	}
   351  	MinerLegacyGasTargetFlag = cli.Uint64Flag{
   352  		Name:  "targetgaslimit",
   353  		Usage: "Target gas floor for mined blocks (deprecated, use --miner.gastarget)",
   354  		Value: eth.DefaultConfig.MinerGasFloor,
   355  	}
   356  	MinerGasLimitFlag = cli.Uint64Flag{
   357  		Name:  "miner.gaslimit",
   358  		Usage: "Target gas ceiling for mined blocks",
   359  		Value: eth.DefaultConfig.MinerGasCeil,
   360  	}
   361  	MinerGasPriceFlag = BigFlag{
   362  		Name:  "miner.gasprice",
   363  		Usage: "Minimum gas price for mining a transaction",
   364  		Value: eth.DefaultConfig.MinerGasPrice,
   365  	}
   366  	MinerLegacyGasPriceFlag = BigFlag{
   367  		Name:  "gasprice",
   368  		Usage: "Minimum gas price for mining a transaction (deprecated, use --miner.gasprice)",
   369  		Value: eth.DefaultConfig.MinerGasPrice,
   370  	}
   371  	MinerEtherbaseFlag = cli.StringFlag{
   372  		Name:  "miner.etherbase",
   373  		Usage: "Public address for block mining rewards (default = first account)",
   374  		Value: "0",
   375  	}
   376  	MinerLegacyEtherbaseFlag = cli.StringFlag{
   377  		Name:  "etherbase",
   378  		Usage: "Public address for block mining rewards (default = first account, deprecated, use --miner.etherbase)",
   379  		Value: "0",
   380  	}
   381  	MinerExtraDataFlag = cli.StringFlag{
   382  		Name:  "miner.extradata",
   383  		Usage: "Block extra data set by the miner (default = client version)",
   384  	}
   385  	MinerLegacyExtraDataFlag = cli.StringFlag{
   386  		Name:  "extradata",
   387  		Usage: "Block extra data set by the miner (default = client version, deprecated, use --miner.extradata)",
   388  	}
   389  	MinerRecommitIntervalFlag = cli.DurationFlag{
   390  		Name:  "miner.recommit",
   391  		Usage: "Time interval to recreate the block being mined",
   392  		Value: eth.DefaultConfig.MinerRecommit,
   393  	}
   394  	MinerNoVerfiyFlag = cli.BoolFlag{
   395  		Name:  "miner.noverify",
   396  		Usage: "Disable remote sealing verification",
   397  	}
   398  	// Account settings
   399  	UnlockedAccountFlag = cli.StringFlag{
   400  		Name:  "unlock",
   401  		Usage: "Comma separated list of accounts to unlock",
   402  		Value: "",
   403  	}
   404  	PasswordFileFlag = cli.StringFlag{
   405  		Name:  "password",
   406  		Usage: "Password file to use for non-interactive password input",
   407  		Value: "",
   408  	}
   409  
   410  	VMEnableDebugFlag = cli.BoolFlag{
   411  		Name:  "vmdebug",
   412  		Usage: "Record information useful for VM and contract debugging",
   413  	}
   414  	// Logging and debug settings
   415  	EthStatsURLFlag = cli.StringFlag{
   416  		Name:  "ethstats",
   417  		Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)",
   418  	}
   419  	FakePoWFlag = cli.BoolFlag{
   420  		Name:  "fakepow",
   421  		Usage: "Disables proof-of-work verification",
   422  	}
   423  	NoCompactionFlag = cli.BoolFlag{
   424  		Name:  "nocompaction",
   425  		Usage: "Disables db compaction after import",
   426  	}
   427  	// RPC settings
   428  	RPCEnabledFlag = cli.BoolFlag{
   429  		Name:  "rpc",
   430  		Usage: "Enable the HTTP-RPC server",
   431  	}
   432  	RPCListenAddrFlag = cli.StringFlag{
   433  		Name:  "rpcaddr",
   434  		Usage: "HTTP-RPC server listening interface",
   435  		Value: node.DefaultHTTPHost,
   436  	}
   437  	RPCPortFlag = cli.IntFlag{
   438  		Name:  "rpcport",
   439  		Usage: "HTTP-RPC server listening port",
   440  		Value: node.DefaultHTTPPort,
   441  	}
   442  	RPCCORSDomainFlag = cli.StringFlag{
   443  		Name:  "rpccorsdomain",
   444  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   445  		Value: "",
   446  	}
   447  	RPCVirtualHostsFlag = cli.StringFlag{
   448  		Name:  "rpcvhosts",
   449  		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   450  		Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","),
   451  	}
   452  	RPCApiFlag = cli.StringFlag{
   453  		Name:  "rpcapi",
   454  		Usage: "API's offered over the HTTP-RPC interface",
   455  		Value: "",
   456  	}
   457  	IPCDisabledFlag = cli.BoolFlag{
   458  		Name:  "ipcdisable",
   459  		Usage: "Disable the IPC-RPC server",
   460  	}
   461  	IPCPathFlag = DirectoryFlag{
   462  		Name:  "ipcpath",
   463  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   464  	}
   465  	WSEnabledFlag = cli.BoolFlag{
   466  		Name:  "ws",
   467  		Usage: "Enable the WS-RPC server",
   468  	}
   469  	WSListenAddrFlag = cli.StringFlag{
   470  		Name:  "wsaddr",
   471  		Usage: "WS-RPC server listening interface",
   472  		Value: node.DefaultWSHost,
   473  	}
   474  	WSPortFlag = cli.IntFlag{
   475  		Name:  "wsport",
   476  		Usage: "WS-RPC server listening port",
   477  		Value: node.DefaultWSPort,
   478  	}
   479  	WSApiFlag = cli.StringFlag{
   480  		Name:  "wsapi",
   481  		Usage: "API's offered over the WS-RPC interface",
   482  		Value: "",
   483  	}
   484  	WSAllowedOriginsFlag = cli.StringFlag{
   485  		Name:  "wsorigins",
   486  		Usage: "Origins from which to accept websockets requests",
   487  		Value: "",
   488  	}
   489  	ExecFlag = cli.StringFlag{
   490  		Name:  "exec",
   491  		Usage: "Execute JavaScript statement",
   492  	}
   493  	PreloadJSFlag = cli.StringFlag{
   494  		Name:  "preload",
   495  		Usage: "Comma separated list of JavaScript files to preload into the console",
   496  	}
   497  
   498  	// Network Settings
   499  	MaxPeersFlag = cli.IntFlag{
   500  		Name:  "maxpeers",
   501  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   502  		Value: 25,
   503  	}
   504  	MaxPendingPeersFlag = cli.IntFlag{
   505  		Name:  "maxpendpeers",
   506  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   507  		Value: 0,
   508  	}
   509  	ListenPortFlag = cli.IntFlag{
   510  		Name:  "port",
   511  		Usage: "Network listening port",
   512  		Value: 30303,
   513  	}
   514  	BootnodesFlag = cli.StringFlag{
   515  		Name:  "bootnodes",
   516  		Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)",
   517  		Value: "",
   518  	}
   519  	BootnodesV4Flag = cli.StringFlag{
   520  		Name:  "bootnodesv4",
   521  		Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)",
   522  		Value: "",
   523  	}
   524  	BootnodesV5Flag = cli.StringFlag{
   525  		Name:  "bootnodesv5",
   526  		Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)",
   527  		Value: "",
   528  	}
   529  	NodeKeyFileFlag = cli.StringFlag{
   530  		Name:  "nodekey",
   531  		Usage: "P2P node key file",
   532  	}
   533  	NodeKeyHexFlag = cli.StringFlag{
   534  		Name:  "nodekeyhex",
   535  		Usage: "P2P node key as hex (for testing)",
   536  	}
   537  	NATFlag = cli.StringFlag{
   538  		Name:  "nat",
   539  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   540  		Value: "any",
   541  	}
   542  	NoDiscoverFlag = cli.BoolFlag{
   543  		Name:  "nodiscover",
   544  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   545  	}
   546  	DiscoveryV5Flag = cli.BoolFlag{
   547  		Name:  "v5disc",
   548  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   549  	}
   550  	NetrestrictFlag = cli.StringFlag{
   551  		Name:  "netrestrict",
   552  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   553  	}
   554  
   555  	// ATM the url is left to the user and deployment to
   556  	JSpathFlag = cli.StringFlag{
   557  		Name:  "jspath",
   558  		Usage: "JavaScript root path for `loadScript`",
   559  		Value: ".",
   560  	}
   561  
   562  	// Gas price oracle settings
   563  	GpoBlocksFlag = cli.IntFlag{
   564  		Name:  "gpoblocks",
   565  		Usage: "Number of recent blocks to check for gas prices",
   566  		Value: eth.DefaultConfig.GPO.Blocks,
   567  	}
   568  	GpoPercentileFlag = cli.IntFlag{
   569  		Name:  "gpopercentile",
   570  		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   571  		Value: eth.DefaultConfig.GPO.Percentile,
   572  	}
   573  	WhisperOffFlag = cli.BoolFlag{
   574  		Name:  "disablewhisper",
   575  		Usage: "Disables the whisper server which is turned on by default",
   576  	}
   577  	WhisperEnabledFlag = cli.BoolFlag{
   578  		Name:  "shh",
   579  		Usage: "Enable Whisper",
   580  	}
   581  	WhisperMaxMessageSizeFlag = cli.IntFlag{
   582  		Name:  "shh.maxmessagesize",
   583  		Usage: "Max message size accepted",
   584  		Value: int(whisper.DefaultMaxMessageSize),
   585  	}
   586  	WhisperMinPOWFlag = cli.Float64Flag{
   587  		Name:  "shh.pow",
   588  		Usage: "Minimum POW accepted",
   589  		Value: whisper.DefaultMinimumPoW,
   590  	}
   591  	WhisperRestrictConnectionBetweenLightClientsFlag = cli.BoolFlag{
   592  		Name:  "shh.restrict-light",
   593  		Usage: "Restrict connection between two whisper light clients",
   594  	}
   595  	// WhisperPublic Key Flags - used to pass in to geth command public whisper broadcast keys
   596  	WhisperKeys = cli.StringFlag{
   597  		Name:  "whisperkeys",
   598  		Usage: "Comma separated list of public keys authorized to broadcast whisper messages",
   599  		Value: "",
   600  	}
   601  
   602  	// Metrics flags
   603  	MetricsEnabledFlag = cli.BoolFlag{
   604  		Name:  metrics.MetricsEnabledFlag,
   605  		Usage: "Enable metrics collection and reporting",
   606  	}
   607  	MetricsEnableInfluxDBFlag = cli.BoolFlag{
   608  		Name:  "metrics.influxdb",
   609  		Usage: "Enable metrics export/push to an external InfluxDB database",
   610  	}
   611  	MetricsInfluxDBEndpointFlag = cli.StringFlag{
   612  		Name:  "metrics.influxdb.endpoint",
   613  		Usage: "InfluxDB API endpoint to report metrics to",
   614  		Value: "http://localhost:8086",
   615  	}
   616  	MetricsInfluxDBDatabaseFlag = cli.StringFlag{
   617  		Name:  "metrics.influxdb.database",
   618  		Usage: "InfluxDB database name to push reported metrics to",
   619  		Value: "geth",
   620  	}
   621  	MetricsInfluxDBUsernameFlag = cli.StringFlag{
   622  		Name:  "metrics.influxdb.username",
   623  		Usage: "Username to authorize access to the database",
   624  		Value: "test",
   625  	}
   626  	MetricsInfluxDBPasswordFlag = cli.StringFlag{
   627  		Name:  "metrics.influxdb.password",
   628  		Usage: "Password to authorize access to the database",
   629  		Value: "test",
   630  	}
   631  	// The `host` tag is part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB.
   632  	// It is used so that we can group all nodes and average a measurement across all of them, but also so
   633  	// that we can select a specific node and inspect its measurements.
   634  	// https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key
   635  	MetricsInfluxDBHostTagFlag = cli.StringFlag{
   636  		Name:  "metrics.influxdb.host.tag",
   637  		Usage: "InfluxDB `host` tag attached to all measurements",
   638  		Value: "localhost",
   639  	}
   640  
   641  	EWASMInterpreterFlag = cli.StringFlag{
   642  		Name:  "vm.ewasm",
   643  		Usage: "External ewasm configuration (default = built-in interpreter)",
   644  		Value: "",
   645  	}
   646  	EVMInterpreterFlag = cli.StringFlag{
   647  		Name:  "vm.evm",
   648  		Usage: "External EVM configuration (default = built-in interpreter)",
   649  		Value: "",
   650  	}
   651  )
   652  
   653  // MakeDataDir retrieves the currently requested data directory, terminating
   654  // if none (or the empty string) is specified. If the node is starting a testnet,
   655  // the a subdirectory of the specified datadir will be used.
   656  func MakeDataDir(ctx *cli.Context) string {
   657  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   658  		if ctx.GlobalBool(TestnetFlag.Name) {
   659  			return filepath.Join(path, "testnet")
   660  		}
   661  		if ctx.GlobalBool(RinkebyFlag.Name) {
   662  			return filepath.Join(path, "rinkeby")
   663  		}
   664  		return path
   665  	}
   666  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   667  	return ""
   668  }
   669  
   670  // setNodeKey creates a node key from set command line flags, either loading it
   671  // from a file or as a specified hex value. If neither flags were provided, this
   672  // method returns nil and an emphemeral key is to be generated.
   673  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   674  	var (
   675  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   676  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   677  		key  *ecdsa.PrivateKey
   678  		err  error
   679  	)
   680  	switch {
   681  	case file != "" && hex != "":
   682  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   683  	case file != "":
   684  		if key, err = crypto.LoadECDSA(file); err != nil {
   685  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   686  		}
   687  		cfg.PrivateKey = key
   688  	case hex != "":
   689  		if key, err = crypto.HexToECDSA(hex); err != nil {
   690  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   691  		}
   692  		cfg.PrivateKey = key
   693  	}
   694  }
   695  
   696  // setNodeUserIdent creates the user identifier from CLI flags.
   697  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   698  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   699  		cfg.UserIdent = identity
   700  	}
   701  }
   702  
   703  // setBootstrapNodes creates a list of bootstrap nodes from the command line
   704  // flags, reverting to pre-configured ones if none have been specified.
   705  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   706  	urls := params.MainnetBootnodes
   707  	switch {
   708  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name):
   709  		if ctx.GlobalIsSet(BootnodesV4Flag.Name) {
   710  			urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",")
   711  		} else {
   712  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   713  		}
   714  	case ctx.GlobalBool(TestnetFlag.Name):
   715  		urls = params.TestnetBootnodes
   716  	case ctx.GlobalBool(RinkebyFlag.Name):
   717  		urls = params.RinkebyBootnodes
   718  	case cfg.BootstrapNodes != nil:
   719  		return // already set, don't apply defaults.
   720  	}
   721  
   722  	cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls))
   723  	for _, url := range urls {
   724  		node, err := enode.ParseV4(url)
   725  		if err != nil {
   726  			log.Crit("Bootstrap URL invalid", "enode", url, "err", err)
   727  		}
   728  		cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   729  	}
   730  }
   731  
   732  // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line
   733  // flags, reverting to pre-configured ones if none have been specified.
   734  func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) {
   735  	urls := params.DiscoveryV5Bootnodes
   736  	switch {
   737  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name):
   738  		if ctx.GlobalIsSet(BootnodesV5Flag.Name) {
   739  			urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",")
   740  		} else {
   741  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   742  		}
   743  	case ctx.GlobalBool(RinkebyFlag.Name):
   744  		urls = params.RinkebyBootnodes
   745  	case cfg.BootstrapNodesV5 != nil:
   746  		return // already set, don't apply defaults.
   747  	}
   748  
   749  	cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls))
   750  	for _, url := range urls {
   751  		node, err := discv5.ParseNode(url)
   752  		if err != nil {
   753  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   754  			continue
   755  		}
   756  		cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node)
   757  	}
   758  }
   759  
   760  // setListenAddress creates a TCP listening address string from set command
   761  // line flags.
   762  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   763  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   764  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   765  	}
   766  }
   767  
   768  // setNAT creates a port mapper from command line flags.
   769  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   770  	if ctx.GlobalIsSet(NATFlag.Name) {
   771  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   772  		if err != nil {
   773  			Fatalf("Option %s: %v", NATFlag.Name, err)
   774  		}
   775  		cfg.NAT = natif
   776  	}
   777  }
   778  
   779  // splitAndTrim splits input separated by a comma
   780  // and trims excessive white space from the substrings.
   781  func splitAndTrim(input string) []string {
   782  	result := strings.Split(input, ",")
   783  	for i, r := range result {
   784  		result[i] = strings.TrimSpace(r)
   785  	}
   786  	return result
   787  }
   788  
   789  // setHTTP creates the HTTP RPC listener interface string from the set
   790  // command line flags, returning empty if the HTTP endpoint is disabled.
   791  func setHTTP(ctx *cli.Context, cfg *node.Config) {
   792  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   793  		cfg.HTTPHost = "127.0.0.1"
   794  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   795  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   796  		}
   797  	}
   798  
   799  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   800  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   801  	}
   802  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   803  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   804  	}
   805  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   806  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   807  	}
   808  	if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) {
   809  		cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name))
   810  	}
   811  }
   812  
   813  // setWS creates the WebSocket RPC listener interface string from the set
   814  // command line flags, returning empty if the HTTP endpoint is disabled.
   815  func setWS(ctx *cli.Context, cfg *node.Config) {
   816  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   817  		cfg.WSHost = "127.0.0.1"
   818  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   819  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   820  		}
   821  	}
   822  
   823  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   824  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   825  	}
   826  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   827  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   828  	}
   829  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   830  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   831  	}
   832  }
   833  
   834  func setWhisperBroadcastKeys(ctx *cli.Context, cfg *node.Config) {
   835  	if ctx.GlobalIsSet(WhisperKeys.Name) {
   836  		cfg.WhisperKeys = splitAndTrim(ctx.GlobalString(WhisperKeys.Name))
   837  	}
   838  }
   839  
   840  // setIPC creates an IPC path configuration from the set command line flags,
   841  // returning an empty string if IPC was explicitly disabled, or the set path.
   842  func setIPC(ctx *cli.Context, cfg *node.Config) {
   843  	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   844  	switch {
   845  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   846  		cfg.IPCPath = ""
   847  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   848  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   849  	}
   850  }
   851  
   852  // makeDatabaseHandles raises out the number of allowed file handles per process
   853  // for Geth and returns half of the allowance to assign to the database.
   854  func makeDatabaseHandles() int {
   855  	limit, err := fdlimit.Maximum()
   856  	if err != nil {
   857  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   858  	}
   859  	if err := fdlimit.Raise(uint64(limit)); err != nil {
   860  		Fatalf("Failed to raise file descriptor allowance: %v", err)
   861  	}
   862  	return limit / 2 // Leave half for networking and other stuff
   863  }
   864  
   865  // MakeAddress converts an account specified directly as a hex encoded string or
   866  // a key index in the key store to an internal account representation.
   867  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   868  	// If the specified account is a valid address, return it
   869  	if common.IsHexAddress(account) {
   870  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   871  	}
   872  	// Otherwise try to interpret the account as a keystore index
   873  	index, err := strconv.Atoi(account)
   874  	if err != nil || index < 0 {
   875  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   876  	}
   877  	log.Warn("-------------------------------------------------------------------")
   878  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
   879  	log.Warn("This functionality is deprecated and will be removed in the future!")
   880  	log.Warn("Please use explicit addresses! (can search via `geth account list`)")
   881  	log.Warn("-------------------------------------------------------------------")
   882  
   883  	accs := ks.Accounts()
   884  	if len(accs) <= index {
   885  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   886  	}
   887  	return accs[index], nil
   888  }
   889  
   890  // setEtherbase retrieves the etherbase either from the directly specified
   891  // command line flags or from the keystore if CLI indexed.
   892  func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) {
   893  	// Extract the current etherbase, new flag overriding legacy one
   894  	var etherbase string
   895  	if ctx.GlobalIsSet(MinerLegacyEtherbaseFlag.Name) {
   896  		etherbase = ctx.GlobalString(MinerLegacyEtherbaseFlag.Name)
   897  	}
   898  	if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) {
   899  		etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name)
   900  	}
   901  	// Convert the etherbase into an address and configure it
   902  	if etherbase != "" {
   903  		account, err := MakeAddress(ks, etherbase)
   904  		if err != nil {
   905  			Fatalf("Invalid miner etherbase: %v", err)
   906  		}
   907  		cfg.Etherbase = account.Address
   908  	}
   909  }
   910  
   911  // MakePasswordList reads password lines from the file specified by the global --password flag.
   912  func MakePasswordList(ctx *cli.Context) []string {
   913  	path := ctx.GlobalString(PasswordFileFlag.Name)
   914  	if path == "" {
   915  		return nil
   916  	}
   917  	text, err := ioutil.ReadFile(path)
   918  	if err != nil {
   919  		Fatalf("Failed to read password file: %v", err)
   920  	}
   921  	lines := strings.Split(string(text), "\n")
   922  	// Sanitise DOS line endings.
   923  	for i := range lines {
   924  		lines[i] = strings.TrimRight(lines[i], "\r")
   925  	}
   926  	return lines
   927  }
   928  
   929  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
   930  	setNodeKey(ctx, cfg)
   931  	setNAT(ctx, cfg)
   932  	setListenAddress(ctx, cfg)
   933  	setBootstrapNodes(ctx, cfg)
   934  	setBootstrapNodesV5(ctx, cfg)
   935  
   936  	lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light"
   937  	lightServer := ctx.GlobalInt(LightServFlag.Name) != 0
   938  	lightPeers := ctx.GlobalInt(LightPeersFlag.Name)
   939  
   940  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   941  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   942  		if lightServer && !ctx.GlobalIsSet(LightPeersFlag.Name) {
   943  			cfg.MaxPeers += lightPeers
   944  		}
   945  	} else {
   946  		if lightServer {
   947  			cfg.MaxPeers += lightPeers
   948  		}
   949  		if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers {
   950  			cfg.MaxPeers = lightPeers
   951  		}
   952  	}
   953  	if !(lightClient || lightServer) {
   954  		lightPeers = 0
   955  	}
   956  	ethPeers := cfg.MaxPeers - lightPeers
   957  	if lightClient {
   958  		ethPeers = 0
   959  	}
   960  	log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers)
   961  
   962  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   963  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   964  	}
   965  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient {
   966  		cfg.NoDiscovery = true
   967  	}
   968  
   969  	// if we're running a light client or server, force enable the v5 peer discovery
   970  	// unless it is explicitly disabled with --nodiscover note that explicitly specifying
   971  	// --v5disc overrides --nodiscover, in which case the later only disables v4 discovery
   972  	forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name)
   973  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   974  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   975  	} else if forceV5Discovery {
   976  		cfg.DiscoveryV5 = true
   977  	}
   978  
   979  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   980  		list, err := netutil.ParseNetlist(netrestrict)
   981  		if err != nil {
   982  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   983  		}
   984  		cfg.NetRestrict = list
   985  	}
   986  
   987  	if ctx.GlobalBool(DeveloperFlag.Name) {
   988  		// --dev mode can't use p2p networking.
   989  		cfg.MaxPeers = 0
   990  		cfg.ListenAddr = ":0"
   991  		cfg.NoDiscovery = true
   992  		cfg.DiscoveryV5 = false
   993  	}
   994  }
   995  
   996  // SetNodeConfig applies node-related command line flags to the config.
   997  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
   998  	SetP2PConfig(ctx, &cfg.P2P)
   999  	setIPC(ctx, cfg)
  1000  	setHTTP(ctx, cfg)
  1001  	setWS(ctx, cfg)
  1002  	setNodeUserIdent(ctx, cfg)
  1003  	setWhisperBroadcastKeys(ctx, cfg)
  1004  
  1005  	setDataDir(ctx, cfg)
  1006  
  1007  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
  1008  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
  1009  	}
  1010  	if ctx.GlobalIsSet(LightKDFFlag.Name) {
  1011  		cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name)
  1012  	}
  1013  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
  1014  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
  1015  	}
  1016  }
  1017  
  1018  func setDataDir(ctx *cli.Context, cfg *node.Config) {
  1019  	switch {
  1020  	case ctx.GlobalIsSet(DataDirFlag.Name):
  1021  		cfg.DataDir = ctx.GlobalString(DataDirFlag.Name)
  1022  	case ctx.GlobalBool(DeveloperFlag.Name):
  1023  		cfg.DataDir = "" // unless explicitly requested, use memory databases
  1024  	case ctx.GlobalBool(TestnetFlag.Name):
  1025  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet")
  1026  	case ctx.GlobalBool(RinkebyFlag.Name):
  1027  		cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
  1028  	}
  1029  }
  1030  
  1031  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
  1032  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
  1033  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
  1034  	}
  1035  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
  1036  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
  1037  	}
  1038  }
  1039  
  1040  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
  1041  	if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) {
  1042  		locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",")
  1043  		for _, account := range locals {
  1044  			if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
  1045  				Fatalf("Invalid account in --txpool.locals: %s", trimmed)
  1046  			} else {
  1047  				cfg.Locals = append(cfg.Locals, common.HexToAddress(account))
  1048  			}
  1049  		}
  1050  	}
  1051  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
  1052  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
  1053  	}
  1054  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
  1055  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
  1056  	}
  1057  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
  1058  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
  1059  	}
  1060  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
  1061  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
  1062  	}
  1063  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
  1064  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
  1065  	}
  1066  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
  1067  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
  1068  	}
  1069  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
  1070  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
  1071  	}
  1072  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
  1073  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
  1074  	}
  1075  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
  1076  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
  1077  	}
  1078  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
  1079  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
  1080  	}
  1081  }
  1082  
  1083  func setEthash(ctx *cli.Context, cfg *eth.Config) {
  1084  	if ctx.GlobalIsSet(EthashCacheDirFlag.Name) {
  1085  		cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name)
  1086  	}
  1087  	if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) {
  1088  		cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name)
  1089  	}
  1090  	if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) {
  1091  		cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name)
  1092  	}
  1093  	if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) {
  1094  		cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name)
  1095  	}
  1096  	if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) {
  1097  		cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name)
  1098  	}
  1099  	if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) {
  1100  		cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name)
  1101  	}
  1102  }
  1103  
  1104  func setWhitelist(ctx *cli.Context, cfg *eth.Config) {
  1105  	whitelist := ctx.GlobalString(WhitelistFlag.Name)
  1106  	if whitelist == "" {
  1107  		return
  1108  	}
  1109  	cfg.Whitelist = make(map[uint64]common.Hash)
  1110  	for _, entry := range strings.Split(whitelist, ",") {
  1111  		parts := strings.Split(entry, "=")
  1112  		if len(parts) != 2 {
  1113  			Fatalf("Invalid whitelist entry: %s", entry)
  1114  		}
  1115  		number, err := strconv.ParseUint(parts[0], 0, 64)
  1116  		if err != nil {
  1117  			Fatalf("Invalid whitelist block number %s: %v", parts[0], err)
  1118  		}
  1119  		var hash common.Hash
  1120  		if err = hash.UnmarshalText([]byte(parts[1])); err != nil {
  1121  			Fatalf("Invalid whitelist hash %s: %v", parts[1], err)
  1122  		}
  1123  		cfg.Whitelist[number] = hash
  1124  	}
  1125  }
  1126  
  1127  // checkExclusive verifies that only a single instance of the provided flags was
  1128  // set by the user. Each flag might optionally be followed by a string type to
  1129  // specialize it further.
  1130  func checkExclusive(ctx *cli.Context, args ...interface{}) {
  1131  	set := make([]string, 0, 1)
  1132  	for i := 0; i < len(args); i++ {
  1133  		// Make sure the next argument is a flag and skip if not set
  1134  		flag, ok := args[i].(cli.Flag)
  1135  		if !ok {
  1136  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
  1137  		}
  1138  		// Check if next arg extends current and expand its name if so
  1139  		name := flag.GetName()
  1140  
  1141  		if i+1 < len(args) {
  1142  			switch option := args[i+1].(type) {
  1143  			case string:
  1144  				// Extended flag check, make sure value set doesn't conflict with passed in option
  1145  				if ctx.GlobalString(flag.GetName()) == option {
  1146  					name += "=" + option
  1147  					set = append(set, "--"+name)
  1148  				}
  1149  				// shift arguments and continue
  1150  				i++
  1151  				continue
  1152  
  1153  			case cli.Flag:
  1154  			default:
  1155  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
  1156  			}
  1157  		}
  1158  		// Mark the flag if it's set
  1159  		if ctx.GlobalIsSet(flag.GetName()) {
  1160  			set = append(set, "--"+name)
  1161  		}
  1162  	}
  1163  	if len(set) > 1 {
  1164  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
  1165  	}
  1166  }
  1167  
  1168  // SetShhConfig applies shh-related command line flags to the config.
  1169  func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) {
  1170  	if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) {
  1171  		cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name))
  1172  	}
  1173  	if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) {
  1174  		cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name)
  1175  	}
  1176  	if ctx.GlobalIsSet(WhisperRestrictConnectionBetweenLightClientsFlag.Name) {
  1177  		cfg.RestrictConnectionBetweenLightClients = true
  1178  	}
  1179  }
  1180  
  1181  // SetEthConfig applies eth-related command line flags to the config.
  1182  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
  1183  	// Avoid conflicting network flags
  1184  	checkExclusive(ctx, DeveloperFlag, TestnetFlag, RinkebyFlag)
  1185  	checkExclusive(ctx, LightServFlag, SyncModeFlag, "light")
  1186  
  1187  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
  1188  	setEtherbase(ctx, ks, cfg)
  1189  	setGPO(ctx, &cfg.GPO)
  1190  	setTxPool(ctx, &cfg.TxPool)
  1191  	setEthash(ctx, cfg)
  1192  	setWhitelist(ctx, cfg)
  1193  
  1194  	if ctx.GlobalIsSet(SyncModeFlag.Name) {
  1195  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
  1196  	}
  1197  	if ctx.GlobalIsSet(LightServFlag.Name) {
  1198  		cfg.LightServ = ctx.GlobalInt(LightServFlag.Name)
  1199  	}
  1200  	if ctx.GlobalIsSet(LightPeersFlag.Name) {
  1201  		cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
  1202  	}
  1203  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1204  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
  1205  	}
  1206  	_, ok := os.LookupEnv("DISABLEPG")
  1207  	if ok {
  1208  		core.DisconnectPG()
  1209  		cfg.Postgres = false
  1210  	} else if ctx.GlobalBool(PostgresFlag.Name) {
  1211  		core.DisconnectPG()
  1212  		cfg.Postgres = false
  1213  	}
  1214  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
  1215  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1216  	}
  1217  	cfg.DatabaseHandles = makeDatabaseHandles()
  1218  
  1219  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1220  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1221  	}
  1222  	cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
  1223  
  1224  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
  1225  		cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100
  1226  	}
  1227  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1228  		cfg.TrieDirtyCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1229  	}
  1230  	if ctx.GlobalIsSet(MinerNotifyFlag.Name) {
  1231  		cfg.MinerNotify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",")
  1232  	}
  1233  	if ctx.GlobalIsSet(DocRootFlag.Name) {
  1234  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
  1235  	}
  1236  	if ctx.GlobalIsSet(MinerLegacyExtraDataFlag.Name) {
  1237  		cfg.MinerExtraData = []byte(ctx.GlobalString(MinerLegacyExtraDataFlag.Name))
  1238  	}
  1239  	if ctx.GlobalIsSet(MinerExtraDataFlag.Name) {
  1240  		cfg.MinerExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name))
  1241  	}
  1242  	if ctx.GlobalIsSet(MinerLegacyGasTargetFlag.Name) {
  1243  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name)
  1244  	}
  1245  	if ctx.GlobalIsSet(MinerGasTargetFlag.Name) {
  1246  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name)
  1247  	}
  1248  	if ctx.GlobalIsSet(MinerGasLimitFlag.Name) {
  1249  		cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name)
  1250  	}
  1251  	if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1252  		cfg.MinerGasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name)
  1253  	}
  1254  	if ctx.GlobalIsSet(MinerGasPriceFlag.Name) {
  1255  		cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name)
  1256  	}
  1257  	if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) {
  1258  		cfg.MinerRecommit = ctx.Duration(MinerRecommitIntervalFlag.Name)
  1259  	}
  1260  	if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) {
  1261  		cfg.MinerNoverify = ctx.Bool(MinerNoVerfiyFlag.Name)
  1262  	}
  1263  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
  1264  		// TODO(fjl): force-enable this in --dev mode
  1265  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
  1266  	}
  1267  
  1268  	if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) {
  1269  		cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name)
  1270  	}
  1271  
  1272  	if ctx.GlobalIsSet(EVMInterpreterFlag.Name) {
  1273  		cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name)
  1274  	}
  1275  
  1276  	// Override any default configs for hard coded networks.
  1277  	switch {
  1278  	case ctx.GlobalBool(TestnetFlag.Name):
  1279  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1280  			cfg.NetworkId = 3
  1281  		}
  1282  		cfg.Genesis = core.DefaultTestnetGenesisBlock()
  1283  	case ctx.GlobalBool(RinkebyFlag.Name):
  1284  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1285  			cfg.NetworkId = 4
  1286  		}
  1287  		cfg.Genesis = core.DefaultRinkebyGenesisBlock()
  1288  	case ctx.GlobalBool(DeveloperFlag.Name):
  1289  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
  1290  			cfg.NetworkId = 1337
  1291  		}
  1292  		// Create new developer account or reuse existing one
  1293  		var (
  1294  			developer accounts.Account
  1295  			err       error
  1296  		)
  1297  		if accs := ks.Accounts(); len(accs) > 0 {
  1298  			developer = ks.Accounts()[0]
  1299  		} else {
  1300  			developer, err = ks.NewAccount("")
  1301  			if err != nil {
  1302  				Fatalf("Failed to create developer account: %v", err)
  1303  			}
  1304  		}
  1305  		if err := ks.Unlock(developer, ""); err != nil {
  1306  			Fatalf("Failed to unlock developer account: %v", err)
  1307  		}
  1308  		log.Info("Using developer account", "address", developer.Address)
  1309  
  1310  		cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
  1311  		if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
  1312  			cfg.MinerGasPrice = big.NewInt(1)
  1313  		}
  1314  	}
  1315  	// TODO(fjl): move trie cache generations into config
  1316  	if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 {
  1317  		state.MaxTrieCacheGen = uint16(gen)
  1318  	}
  1319  }
  1320  
  1321  // SetDashboardConfig applies dashboard related command line flags to the config.
  1322  func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) {
  1323  	cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name)
  1324  	cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name)
  1325  	cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name)
  1326  }
  1327  
  1328  // RegisterEthService adds an Ethereum client to the stack.
  1329  func RegisterEthService(stack *node.Node, cfg *eth.Config) {
  1330  	var err error
  1331  	if cfg.SyncMode == downloader.LightSync {
  1332  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1333  			return les.New(ctx, cfg)
  1334  		})
  1335  	} else {
  1336  		err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1337  			fullNode, err := eth.New(ctx, cfg)
  1338  			if fullNode != nil && cfg.LightServ > 0 {
  1339  				ls, _ := les.NewLesServer(fullNode, cfg)
  1340  				fullNode.AddLesServer(ls)
  1341  			}
  1342  			return fullNode, err
  1343  		})
  1344  	}
  1345  	if err != nil {
  1346  		Fatalf("Failed to register the Ethereum service: %v", err)
  1347  	}
  1348  }
  1349  
  1350  // RegisterDashboardService adds a dashboard to the stack.
  1351  func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
  1352  	stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1353  		return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil
  1354  	})
  1355  }
  1356  
  1357  // RegisterShhService configures Whisper and adds it to the given node.
  1358  func RegisterShhService(stack *node.Node, cfg *whisper.Config) {
  1359  	if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) {
  1360  		return whisper.New(cfg), nil
  1361  	}); err != nil {
  1362  		Fatalf("Failed to register the Whisper service: %v", err)
  1363  	}
  1364  }
  1365  
  1366  // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to
  1367  // the given node.
  1368  func RegisterEthStatsService(stack *node.Node, url string) {
  1369  	if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
  1370  		// Retrieve both eth and les services
  1371  		var ethServ *eth.Ethereum
  1372  		ctx.Service(&ethServ)
  1373  
  1374  		var lesServ *les.LightEthereum
  1375  		ctx.Service(&lesServ)
  1376  
  1377  		return ethstats.New(url, ethServ, lesServ)
  1378  	}); err != nil {
  1379  		Fatalf("Failed to register the Ethereum Stats service: %v", err)
  1380  	}
  1381  }
  1382  
  1383  func SetupMetrics(ctx *cli.Context) {
  1384  	if metrics.Enabled {
  1385  		log.Info("Enabling metrics collection")
  1386  		var (
  1387  			enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name)
  1388  			endpoint     = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name)
  1389  			database     = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name)
  1390  			username     = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name)
  1391  			password     = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name)
  1392  			hosttag      = ctx.GlobalString(MetricsInfluxDBHostTagFlag.Name)
  1393  		)
  1394  
  1395  		if enableExport {
  1396  			log.Info("Enabling metrics export to InfluxDB")
  1397  			go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", map[string]string{
  1398  				"host": hosttag,
  1399  			})
  1400  		}
  1401  	}
  1402  }
  1403  
  1404  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1405  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database {
  1406  	var (
  1407  		cache   = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
  1408  		handles = makeDatabaseHandles()
  1409  	)
  1410  	name := "chaindata"
  1411  	if ctx.GlobalString(SyncModeFlag.Name) == "light" {
  1412  		name = "lightchaindata"
  1413  	}
  1414  	chainDb, err := stack.OpenDatabase(name, cache, handles)
  1415  	if err != nil {
  1416  		Fatalf("Could not open database: %v", err)
  1417  	}
  1418  	return chainDb
  1419  }
  1420  
  1421  // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
  1422  func MakeChainShyftDatabase(ctx *cli.Context, stack *node.Node) ethdb.SDatabase {
  1423  	var (
  1424  		shyftChainDb ethdb.SDatabase
  1425  	)
  1426  	_, ok := os.LookupEnv("DISABLEPG")
  1427  	if ok {
  1428  		shyftChainDb = nil
  1429  	} else if ctx.GlobalBool(PostgresFlag.Name) {
  1430  		core.DisconnectPG()
  1431  		shyftChainDb = nil
  1432  	} else {
  1433  		var err error
  1434  		shyftChainDb, err = stack.OpenShyftDatabase()
  1435  		if err != nil {
  1436  			Fatalf("Could not open database: %v", err)
  1437  		}
  1438  	}
  1439  	return shyftChainDb
  1440  }
  1441  
  1442  func MakeGenesis(ctx *cli.Context) *core.Genesis {
  1443  	var genesis *core.Genesis
  1444  	switch {
  1445  	case ctx.GlobalBool(TestnetFlag.Name):
  1446  		genesis = core.DefaultTestnetGenesisBlock()
  1447  	case ctx.GlobalBool(RinkebyFlag.Name):
  1448  		genesis = core.DefaultRinkebyGenesisBlock()
  1449  	case ctx.GlobalBool(DeveloperFlag.Name):
  1450  		Fatalf("Developer chains are ephemeral")
  1451  	}
  1452  	return genesis
  1453  }
  1454  
  1455  // MakeChain creates a chain manager from set command line flags.
  1456  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database, shyftDb ethdb.SDatabase) {
  1457  	chainDb = MakeChainDatabase(ctx, stack)
  1458  	shyftChainDb := MakeChainShyftDatabase(ctx, stack)
  1459  	config, _, err := core.SetupGenesisBlock(chainDb, shyftChainDb, MakeGenesis(ctx))
  1460  
  1461  	if err != nil {
  1462  		Fatalf("%v", err)
  1463  	}
  1464  	var engine consensus.Engine
  1465  	if config.Clique != nil {
  1466  		engine = clique.New(config.Clique, chainDb)
  1467  	} else {
  1468  		engine = ethash.NewFaker()
  1469  		if !ctx.GlobalBool(FakePoWFlag.Name) {
  1470  			engine = ethash.New(ethash.Config{
  1471  				CacheDir:       stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir),
  1472  				CachesInMem:    eth.DefaultConfig.Ethash.CachesInMem,
  1473  				CachesOnDisk:   eth.DefaultConfig.Ethash.CachesOnDisk,
  1474  				DatasetDir:     stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir),
  1475  				DatasetsInMem:  eth.DefaultConfig.Ethash.DatasetsInMem,
  1476  				DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk,
  1477  			}, nil, false)
  1478  		}
  1479  	}
  1480  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
  1481  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
  1482  	}
  1483  	cache := &core.CacheConfig{
  1484  		Disabled:       ctx.GlobalString(GCModeFlag.Name) == "archive",
  1485  		TrieCleanLimit: eth.DefaultConfig.TrieCleanCache,
  1486  		TrieDirtyLimit: eth.DefaultConfig.TrieDirtyCache,
  1487  		TrieTimeLimit:  eth.DefaultConfig.TrieTimeout,
  1488  	}
  1489  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
  1490  		cache.TrieCleanLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100
  1491  	}
  1492  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
  1493  		cache.TrieDirtyLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
  1494  	}
  1495  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
  1496  	chain, err = core.NewBlockChain(chainDb, shyftChainDb, cache, config, engine, vmcfg, nil)
  1497  	if err != nil {
  1498  		Fatalf("Can't create BlockChain: %v", err)
  1499  	}
  1500  	return chain, chainDb, shyftDb
  1501  }
  1502  
  1503  // MakeConsolePreloads retrieves the absolute paths for the console JavaScript
  1504  // scripts to preload before starting.
  1505  func MakeConsolePreloads(ctx *cli.Context) []string {
  1506  	// Skip preloading if there's nothing to preload
  1507  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
  1508  		return nil
  1509  	}
  1510  	// Otherwise resolve absolute paths and return them
  1511  	preloads := []string{}
  1512  
  1513  	assets := ctx.GlobalString(JSpathFlag.Name)
  1514  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
  1515  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
  1516  	}
  1517  	return preloads
  1518  }
  1519  
  1520  // MigrateFlags sets the global flag from a local flag when it's set.
  1521  // This is a temporary function used for migrating old command/flags to the
  1522  // new format.
  1523  //
  1524  // e.g. geth account new --keystore /tmp/mykeystore --lightkdf
  1525  //
  1526  // is equivalent after calling this method with:
  1527  //
  1528  // geth --keystore /tmp/mykeystore --lightkdf account new
  1529  //
  1530  // This allows the use of the existing configuration functionality.
  1531  // When all flags are migrated this function can be removed and the existing
  1532  // configuration functionality must be changed that is uses local flags
  1533  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
  1534  	return func(ctx *cli.Context) error {
  1535  		for _, name := range ctx.FlagNames() {
  1536  			if ctx.IsSet(name) {
  1537  				ctx.GlobalSet(name, ctx.String(name))
  1538  			}
  1539  		}
  1540  		return action(ctx)
  1541  	}
  1542  }