github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/utils/flags.go (about)

     1  package utils
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/neatio-net/neatio/chain/accounts"
    13  	"github.com/neatio-net/neatio/chain/accounts/keystore"
    14  	"github.com/neatio-net/neatio/chain/consensus"
    15  	"github.com/neatio-net/neatio/chain/core"
    16  	"github.com/neatio-net/neatio/chain/core/vm"
    17  	"github.com/neatio-net/neatio/chain/log"
    18  	"github.com/neatio-net/neatio/neatdb"
    19  	neatptc "github.com/neatio-net/neatio/neatptc"
    20  	"github.com/neatio-net/neatio/neatptc/downloader"
    21  	"github.com/neatio-net/neatio/neatptc/gasprice"
    22  	"github.com/neatio-net/neatio/network/node"
    23  	"github.com/neatio-net/neatio/network/p2p"
    24  	"github.com/neatio-net/neatio/network/p2p/discover"
    25  	"github.com/neatio-net/neatio/network/p2p/nat"
    26  	"github.com/neatio-net/neatio/network/p2p/netutil"
    27  	"github.com/neatio-net/neatio/params"
    28  	"github.com/neatio-net/neatio/utilities/common"
    29  	"github.com/neatio-net/neatio/utilities/common/fdlimit"
    30  	"github.com/neatio-net/neatio/utilities/crypto"
    31  	"github.com/neatio-net/neatio/utilities/metrics"
    32  	"gopkg.in/urfave/cli.v1"
    33  
    34  	cfg "github.com/neatio-net/config-go"
    35  	tmcfg "github.com/neatio-net/neatio/chain/consensus/neatcon/config/neatcon"
    36  )
    37  
    38  var (
    39  	CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...]
    40  {{if .cmd.Description}}{{.cmd.Description}}
    41  {{end}}{{if .cmd.Subcommands}}
    42  SUBCOMMANDS:
    43  	{{range .cmd.Subcommands}}{{.cmd.Name}}{{with .cmd.ShortName}}, {{.cmd}}{{end}}{{ "\t" }}{{.cmd.Usage}}
    44  	{{end}}{{end}}{{if .categorizedFlags}}
    45  {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS:
    46  {{range $categorized.Flags}}{{"\t"}}{{.}}
    47  {{end}}
    48  {{end}}{{end}}`
    49  )
    50  
    51  func init() {
    52  	cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
    53  
    54  VERSION:
    55     {{.Version}}
    56  
    57  COMMANDS:
    58     {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
    59     {{end}}{{if .Flags}}
    60  GLOBAL OPTIONS:
    61     {{range .Flags}}{{.}}
    62     {{end}}{{end}}
    63  `
    64  
    65  	cli.CommandHelpTemplate = CommandHelpTemplate
    66  }
    67  
    68  func NewApp(gitCommit, usage string) *cli.App {
    69  	app := cli.NewApp()
    70  	app.Name = filepath.Base(os.Args[0])
    71  	app.Author = ""
    72  	app.Email = ""
    73  	app.Version = params.Version
    74  	if len(gitCommit) >= 8 {
    75  		app.Version += "-" + gitCommit[:8]
    76  	}
    77  	app.Usage = usage
    78  	return app
    79  }
    80  
    81  var (
    82  	DataDirFlag = DirectoryFlag{
    83  		Name:  "datadir",
    84  		Usage: "Data directory for the databases and keystore",
    85  		Value: DirectoryString{node.DefaultDataDir()},
    86  	}
    87  	KeyStoreDirFlag = DirectoryFlag{
    88  		Name:  "keystore",
    89  		Usage: "Directory for the keystore (default = inside the datadir)",
    90  	}
    91  	NoUSBFlag = cli.BoolFlag{
    92  		Name:  "nousb",
    93  		Usage: "Disables monitoring for and managing USB hardware wallets",
    94  	}
    95  	NetworkIdFlag = cli.Uint64Flag{
    96  		Name:  "networkid",
    97  		Usage: "Network identifier (integer, mainnet=1001, testnet=1002)",
    98  		Value: neatptc.DefaultConfig.NetworkId,
    99  	}
   100  	TestnetFlag = cli.BoolFlag{
   101  		Name:  "testnet",
   102  		Usage: "Test network",
   103  	}
   104  
   105  	DeveloperFlag = cli.BoolFlag{
   106  		Name:  "dev",
   107  		Usage: "Ephemeral proof-of-authority network with a pre-funded developer account, mining enabled",
   108  	}
   109  
   110  	IdentityFlag = cli.StringFlag{
   111  		Name:  "identity",
   112  		Usage: "Custom node name",
   113  	}
   114  	DocRootFlag = DirectoryFlag{
   115  		Name:  "docroot",
   116  		Usage: "Document Root for HTTPClient file scheme",
   117  		Value: DirectoryString{homeDir()},
   118  	}
   119  	FastSyncFlag = cli.BoolFlag{
   120  		Name:  "fast",
   121  		Usage: "Enable fast syncing through state downloads",
   122  	}
   123  
   124  	defaultSyncMode = neatptc.DefaultConfig.SyncMode
   125  	SyncModeFlag    = TextMarshalerFlag{
   126  		Name:  "syncmode",
   127  		Usage: `Blockchain sync mode ("full")`,
   128  		Value: &defaultSyncMode,
   129  	}
   130  	GCModeFlag = cli.StringFlag{
   131  		Name:  "gcmode",
   132  		Usage: `Blockchain garbage collection mode ("full", "archive")`,
   133  		Value: "archive",
   134  	}
   135  
   136  	TxPoolNoLocalsFlag = cli.BoolFlag{
   137  		Name:  "txpool.nolocals",
   138  		Usage: "Disables price exemptions for locally submitted transactions",
   139  	}
   140  	TxPoolJournalFlag = cli.StringFlag{
   141  		Name:  "txpool.journal",
   142  		Usage: "Disk journal for local transaction to survive node restarts",
   143  		Value: core.DefaultTxPoolConfig.Journal,
   144  	}
   145  	TxPoolRejournalFlag = cli.DurationFlag{
   146  		Name:  "txpool.rejournal",
   147  		Usage: "Time interval to regenerate the local transaction journal",
   148  		Value: core.DefaultTxPoolConfig.Rejournal,
   149  	}
   150  	TxPoolPriceLimitFlag = cli.Uint64Flag{
   151  		Name:  "txpool.pricelimit",
   152  		Usage: "Minimum gas price limit to enforce for acceptance into the pool",
   153  		Value: neatptc.DefaultConfig.TxPool.PriceLimit,
   154  	}
   155  	TxPoolPriceBumpFlag = cli.Uint64Flag{
   156  		Name:  "txpool.pricebump",
   157  		Usage: "Price bump percentage to replace an already existing transaction",
   158  		Value: neatptc.DefaultConfig.TxPool.PriceBump,
   159  	}
   160  	TxPoolAccountSlotsFlag = cli.Uint64Flag{
   161  		Name:  "txpool.accountslots",
   162  		Usage: "Minimum number of executable transaction slots guaranteed per account",
   163  		Value: neatptc.DefaultConfig.TxPool.AccountSlots,
   164  	}
   165  	TxPoolGlobalSlotsFlag = cli.Uint64Flag{
   166  		Name:  "txpool.globalslots",
   167  		Usage: "Maximum number of executable transaction slots for all accounts",
   168  		Value: neatptc.DefaultConfig.TxPool.GlobalSlots,
   169  	}
   170  	TxPoolAccountQueueFlag = cli.Uint64Flag{
   171  		Name:  "txpool.accountqueue",
   172  		Usage: "Maximum number of non-executable transaction slots permitted per account",
   173  		Value: neatptc.DefaultConfig.TxPool.AccountQueue,
   174  	}
   175  	TxPoolGlobalQueueFlag = cli.Uint64Flag{
   176  		Name:  "txpool.globalqueue",
   177  		Usage: "Maximum number of non-executable transaction slots for all accounts",
   178  		Value: neatptc.DefaultConfig.TxPool.GlobalQueue,
   179  	}
   180  	TxPoolLifetimeFlag = cli.DurationFlag{
   181  		Name:  "txpool.lifetime",
   182  		Usage: "Maximum amount of time non-executable transaction are queued",
   183  		Value: neatptc.DefaultConfig.TxPool.Lifetime,
   184  	}
   185  	CacheFlag = cli.IntFlag{
   186  		Name:  "cache",
   187  		Usage: "Megabytes of memory allocated to internal caching",
   188  		Value: 1024,
   189  	}
   190  	CacheDatabaseFlag = cli.IntFlag{
   191  		Name:  "cache.database",
   192  		Usage: "Percentage of cache memory allowance to use for database io",
   193  		Value: 50,
   194  	}
   195  	CacheTrieFlag = cli.IntFlag{
   196  		Name:  "cache.trie",
   197  		Usage: "Percentage of cache memory allowance to use for trie caching (default = 25% full mode, 50% archive mode)",
   198  		Value: 25,
   199  	}
   200  	CacheGCFlag = cli.IntFlag{
   201  		Name:  "cache.gc",
   202  		Usage: "Percentage of cache memory allowance to use for trie pruning (default = 25% full mode, 0% archive mode)",
   203  		Value: 25,
   204  	}
   205  	MiningEnabledFlag = cli.BoolFlag{
   206  		Name:  "mine",
   207  		Usage: "Enable mining",
   208  	}
   209  	MinerThreadsFlag = cli.IntFlag{
   210  		Name:  "miner.threads",
   211  		Usage: "Number of CPU threads to use for mining",
   212  		Value: 0,
   213  	}
   214  	MinerGasTargetFlag = cli.Uint64Flag{
   215  		Name:  "miner.gastarget",
   216  		Usage: "Target gas floor for mined blocks",
   217  		Value: neatptc.DefaultConfig.MinerGasFloor,
   218  	}
   219  	MinerGasLimitFlag = cli.Uint64Flag{
   220  		Name:  "miner.gaslimit",
   221  		Usage: "Target gas ceiling for mined blocks",
   222  		Value: neatptc.DefaultConfig.MinerGasCeil,
   223  	}
   224  	MinerGasPriceFlag = BigFlag{
   225  		Name:  "miner.gasprice",
   226  		Usage: "Minimal gas price for mining a transactions",
   227  		Value: neatptc.DefaultConfig.MinerGasPrice,
   228  	}
   229  	MinerCoinbaseFlag = cli.StringFlag{
   230  		Name:  "miner.etherbase",
   231  		Usage: "Public address for block mining rewards (default = first account)",
   232  		Value: "0",
   233  	}
   234  	ExtraDataFlag = cli.StringFlag{
   235  		Name:  "extradata",
   236  		Usage: "Block extra data set by the miner (default = client version)",
   237  	}
   238  	UnlockedAccountFlag = cli.StringFlag{
   239  		Name:  "unlock",
   240  		Usage: "Comma separated list of accounts to unlock",
   241  		Value: "",
   242  	}
   243  	PasswordFileFlag = cli.StringFlag{
   244  		Name:  "password",
   245  		Usage: "Password file to use for non-interactive password input",
   246  		Value: "",
   247  	}
   248  
   249  	VMEnableDebugFlag = cli.BoolFlag{
   250  		Name:  "vmdebug",
   251  		Usage: "Record information useful for VM and contract debugging",
   252  	}
   253  	EthStatsURLFlag = cli.StringFlag{
   254  		Name:  "stats",
   255  		Usage: "Reporting URL of a stats service (nodename:secret@host:port)",
   256  	}
   257  	MetricsEnabledFlag = cli.BoolFlag{
   258  		Name:  metrics.MetricsEnabledFlag,
   259  		Usage: "Enable metrics collection and reporting",
   260  	}
   261  
   262  	NoCompactionFlag = cli.BoolFlag{
   263  		Name:  "nocompaction",
   264  		Usage: "Disables db compaction after import",
   265  	}
   266  	RPCEnabledFlag = cli.BoolFlag{
   267  		Name:  "rpc",
   268  		Usage: "Enable the HTTP-RPC server",
   269  	}
   270  	RPCListenAddrFlag = cli.StringFlag{
   271  		Name:  "rpcaddr",
   272  		Usage: "HTTP-RPC server listening interface",
   273  		Value: node.DefaultHTTPHost,
   274  	}
   275  	RPCPortFlag = cli.IntFlag{
   276  		Name:  "rpcport",
   277  		Usage: "HTTP-RPC server listening port",
   278  		Value: node.DefaultHTTPPort,
   279  	}
   280  	RPCCORSDomainFlag = cli.StringFlag{
   281  		Name:  "rpccorsdomain",
   282  		Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
   283  		Value: "",
   284  	}
   285  	RPCVirtualHostsFlag = cli.StringFlag{
   286  		Name:  "rpcvhosts",
   287  		Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
   288  		Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","),
   289  	}
   290  	RPCApiFlag = cli.StringFlag{
   291  		Name:  "rpcapi",
   292  		Usage: "API's offered over the HTTP-RPC interface",
   293  		Value: "",
   294  	}
   295  	IPCDisabledFlag = cli.BoolFlag{
   296  		Name:  "ipcdisable",
   297  		Usage: "Disable the IPC-RPC server",
   298  	}
   299  	IPCPathFlag = DirectoryFlag{
   300  		Name:  "ipcpath",
   301  		Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
   302  	}
   303  	WSEnabledFlag = cli.BoolFlag{
   304  		Name:  "ws",
   305  		Usage: "Enable the WS-RPC server",
   306  	}
   307  	WSListenAddrFlag = cli.StringFlag{
   308  		Name:  "wsaddr",
   309  		Usage: "WS-RPC server listening interface",
   310  		Value: node.DefaultWSHost,
   311  	}
   312  	WSPortFlag = cli.IntFlag{
   313  		Name:  "wsport",
   314  		Usage: "WS-RPC server listening port",
   315  		Value: node.DefaultWSPort,
   316  	}
   317  	WSApiFlag = cli.StringFlag{
   318  		Name:  "wsapi",
   319  		Usage: "API is offered over the WS-RPC interface",
   320  		Value: "",
   321  	}
   322  	WSAllowedOriginsFlag = cli.StringFlag{
   323  		Name:  "wsorigins",
   324  		Usage: "Origins from which to accept websockets requests",
   325  		Value: "",
   326  	}
   327  	ExecFlag = cli.StringFlag{
   328  		Name:  "exec",
   329  		Usage: "Execute JavaScript statement",
   330  	}
   331  	PreloadJSFlag = cli.StringFlag{
   332  		Name:  "preload",
   333  		Usage: "Comma separated list of JavaScript files to preload into the console",
   334  	}
   335  
   336  	MaxPeersFlag = cli.IntFlag{
   337  		Name:  "maxpeers",
   338  		Usage: "Maximum number of network peers (network disabled if set to 0)",
   339  		Value: 25,
   340  	}
   341  	MaxPendingPeersFlag = cli.IntFlag{
   342  		Name:  "maxpendpeers",
   343  		Usage: "Maximum number of pending connection attempts (defaults used if set to 0)",
   344  		Value: 0,
   345  	}
   346  	ListenPortFlag = cli.IntFlag{
   347  		Name:  "port",
   348  		Usage: "Network listening port",
   349  		Value: 9910,
   350  	}
   351  	BootnodesFlag = cli.StringFlag{
   352  		Name:  "bootnodes",
   353  		Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)",
   354  		Value: "",
   355  	}
   356  	BootnodesV4Flag = cli.StringFlag{
   357  		Name:  "bootnodesv4",
   358  		Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)",
   359  		Value: "",
   360  	}
   361  	BootnodesV5Flag = cli.StringFlag{
   362  		Name:  "bootnodesv5",
   363  		Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)",
   364  		Value: "",
   365  	}
   366  	NodeKeyFileFlag = cli.StringFlag{
   367  		Name:  "nodekey",
   368  		Usage: "P2P node key file",
   369  	}
   370  	NodeKeyHexFlag = cli.StringFlag{
   371  		Name:  "nodekeyhex",
   372  		Usage: "P2P node key as hex (for testing)",
   373  	}
   374  	NATFlag = cli.StringFlag{
   375  		Name:  "nat",
   376  		Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)",
   377  		Value: "any",
   378  	}
   379  	NoDiscoverFlag = cli.BoolFlag{
   380  		Name:  "nodiscover",
   381  		Usage: "Disables the peer discovery mechanism (manual peer addition)",
   382  	}
   383  	DiscoveryV5Flag = cli.BoolFlag{
   384  		Name:  "v5disc",
   385  		Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism",
   386  	}
   387  	NetrestrictFlag = cli.StringFlag{
   388  		Name:  "netrestrict",
   389  		Usage: "Restricts network communication to the given IP networks (CIDR masks)",
   390  	}
   391  
   392  	JSpathFlag = cli.StringFlag{
   393  		Name:  "jspath",
   394  		Usage: "JavaScript root path for `loadScript`",
   395  		Value: ".",
   396  	}
   397  
   398  	SolcPathFlag = cli.StringFlag{
   399  		Name:  "solc",
   400  		Usage: "Solidity compiler command to be used",
   401  		Value: "solc",
   402  	}
   403  
   404  	GpoBlocksFlag = cli.IntFlag{
   405  		Name:  "gpoblocks",
   406  		Usage: "Number of recent blocks to check for gas prices",
   407  		Value: neatptc.DefaultConfig.GPO.Blocks,
   408  	}
   409  	GpoPercentileFlag = cli.IntFlag{
   410  		Name:  "gpopercentile",
   411  		Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices",
   412  		Value: neatptc.DefaultConfig.GPO.Percentile,
   413  	}
   414  
   415  	PruneFlag = cli.BoolFlag{
   416  		Name:  "prune",
   417  		Usage: "Enable the Data Reduction feature, history state data will be pruned by default",
   418  	}
   419  
   420  	PerfTestFlag = cli.BoolFlag{
   421  		Name:  "perftest",
   422  		Usage: "Whether doing performance test, will remove some limitations and cause system more frigile",
   423  	}
   424  
   425  	SideChainFlag = cli.StringFlag{
   426  		Name:  "sideChain",
   427  		Usage: "Specify one or more side chain should be start. Ex: side-1,side-2",
   428  	}
   429  
   430  	MonikerFlag = cli.StringFlag{
   431  		Name:  "moniker",
   432  		Value: "",
   433  		Usage: "Node's moniker",
   434  	}
   435  
   436  	NodeLaddrFlag = cli.StringFlag{
   437  		Name:  "node_laddr",
   438  		Value: "tcp://0.0.0.0:46656",
   439  		Usage: "Node listen address. (0.0.0.0:0 means any interface, any port)",
   440  	}
   441  
   442  	SeedsFlag = cli.StringFlag{
   443  		Name:  "seeds",
   444  		Value: "",
   445  		Usage: "Comma delimited host:port seed nodes",
   446  	}
   447  
   448  	SkipUpnpFlag = cli.BoolFlag{
   449  		Name:  "skip_upnp",
   450  		Usage: "Skip UPNP configuration",
   451  	}
   452  
   453  	RpcLaddrFlag = cli.StringFlag{
   454  		Name:  "rpc_laddr",
   455  		Value: "unix://@neatchainrpcunixsock",
   456  		Usage: "RPC listen address. Port required",
   457  	}
   458  
   459  	AddrFlag = cli.StringFlag{
   460  		Name:  "addr",
   461  		Value: "unix://@neatchainappunixsock",
   462  		Usage: "TMSP app listen address",
   463  	}
   464  )
   465  
   466  func MakeDataDir(ctx *cli.Context) string {
   467  	if path := ctx.GlobalString(DataDirFlag.Name); path != "" {
   468  		return path
   469  	}
   470  	Fatalf("Cannot determine default data directory, please set manually (--datadir)")
   471  	return ""
   472  }
   473  
   474  func setNodeKey(ctx *cli.Context, cfg *p2p.Config) {
   475  	var (
   476  		hex  = ctx.GlobalString(NodeKeyHexFlag.Name)
   477  		file = ctx.GlobalString(NodeKeyFileFlag.Name)
   478  		key  *ecdsa.PrivateKey
   479  		err  error
   480  	)
   481  	switch {
   482  	case file != "" && hex != "":
   483  		Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name)
   484  	case file != "":
   485  		if key, err = crypto.LoadECDSA(file); err != nil {
   486  			Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err)
   487  		}
   488  		cfg.PrivateKey = key
   489  	case hex != "":
   490  		if key, err = crypto.HexToECDSA(hex); err != nil {
   491  			Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err)
   492  		}
   493  		cfg.PrivateKey = key
   494  	}
   495  }
   496  
   497  func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
   498  	if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 {
   499  		cfg.UserIdent = identity
   500  	}
   501  }
   502  
   503  func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
   504  	urls := params.MainnetBootnodes
   505  	switch {
   506  	case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name):
   507  		if ctx.GlobalIsSet(BootnodesV4Flag.Name) {
   508  			urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",")
   509  		} else {
   510  			urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
   511  		}
   512  	case ctx.GlobalBool(TestnetFlag.Name):
   513  		urls = params.TestnetBootnodes
   514  	case cfg.BootstrapNodes != nil:
   515  		return
   516  	}
   517  
   518  	cfg.BootstrapNodes = make([]*discover.Node, 0, len(urls))
   519  	for _, url := range urls {
   520  		node, err := discover.ParseNode(url)
   521  		if err != nil {
   522  			log.Error("Bootstrap URL invalid", "enode", url, "err", err)
   523  			continue
   524  		}
   525  		cfg.BootstrapNodes = append(cfg.BootstrapNodes, node)
   526  	}
   527  }
   528  
   529  func setListenAddress(ctx *cli.Context, cfg *p2p.Config) {
   530  	if ctx.GlobalIsSet(ListenPortFlag.Name) {
   531  		cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name))
   532  	}
   533  }
   534  
   535  func setNAT(ctx *cli.Context, cfg *p2p.Config) {
   536  	if ctx.GlobalIsSet(NATFlag.Name) {
   537  		natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name))
   538  		if err != nil {
   539  			Fatalf("Option %s: %v", NATFlag.Name, err)
   540  		}
   541  		cfg.NAT = natif
   542  	}
   543  }
   544  
   545  func splitAndTrim(input string) []string {
   546  	result := strings.Split(input, ",")
   547  	for i, r := range result {
   548  		result[i] = strings.TrimSpace(r)
   549  	}
   550  	return result
   551  }
   552  
   553  func SetHTTP(ctx *cli.Context, cfg *node.Config) {
   554  	if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" {
   555  		cfg.HTTPHost = "127.0.0.1"
   556  		if ctx.GlobalIsSet(RPCListenAddrFlag.Name) {
   557  			cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name)
   558  		}
   559  	}
   560  
   561  	if ctx.GlobalIsSet(RPCPortFlag.Name) {
   562  		cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name)
   563  	}
   564  	if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) {
   565  		cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name))
   566  	}
   567  	if ctx.GlobalIsSet(RPCApiFlag.Name) {
   568  		cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name))
   569  	}
   570  	if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) {
   571  		cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name))
   572  	}
   573  }
   574  
   575  func SetWS(ctx *cli.Context, cfg *node.Config) {
   576  	if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" {
   577  		cfg.WSHost = "127.0.0.1"
   578  		if ctx.GlobalIsSet(WSListenAddrFlag.Name) {
   579  			cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name)
   580  		}
   581  	}
   582  
   583  	if ctx.GlobalIsSet(WSPortFlag.Name) {
   584  		cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name)
   585  	}
   586  	if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) {
   587  		cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name))
   588  	}
   589  	if ctx.GlobalIsSet(WSApiFlag.Name) {
   590  		cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name))
   591  	}
   592  }
   593  
   594  func setIPC(ctx *cli.Context, cfg *node.Config) {
   595  	checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag)
   596  	switch {
   597  	case ctx.GlobalBool(IPCDisabledFlag.Name):
   598  		cfg.IPCPath = ""
   599  	case ctx.GlobalIsSet(IPCPathFlag.Name):
   600  		cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name)
   601  	}
   602  }
   603  
   604  func makeDatabaseHandles() int {
   605  	limit, err := fdlimit.Current()
   606  	if err != nil {
   607  		Fatalf("Failed to retrieve file descriptor allowance: %v", err)
   608  	}
   609  	if limit < 2048 {
   610  		if err := fdlimit.Raise(2048); err != nil {
   611  			Fatalf("Failed to raise file descriptor allowance: %v", err)
   612  		}
   613  	}
   614  	if limit > 2048 { // cap database file descriptors even if more is available
   615  		limit = 2048
   616  	}
   617  	return limit / 2 // Leave half for networking and other stuff
   618  }
   619  
   620  func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) {
   621  	if common.IsHexAddress(account) {
   622  		return accounts.Account{Address: common.HexToAddress(account)}, nil
   623  	}
   624  	index, err := strconv.Atoi(account)
   625  	if err != nil || index < 0 {
   626  		return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account)
   627  	}
   628  	log.Warn("-------------------------------------------------------------------")
   629  	log.Warn("Referring to accounts by order in the keystore folder is dangerous!")
   630  	log.Warn("This functionality is deprecated and will be removed in the future!")
   631  	log.Warn("Please use explicit addresses! (can search via `neatio account list`)")
   632  	log.Warn("-------------------------------------------------------------------")
   633  
   634  	accs := ks.Accounts()
   635  	if len(accs) <= index {
   636  		return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs))
   637  	}
   638  	return accs[index], nil
   639  }
   640  
   641  func setCoinbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *neatptc.Config) {
   642  	var coinbase string
   643  	if ctx.GlobalIsSet(MinerCoinbaseFlag.Name) {
   644  		coinbase = ctx.GlobalString(MinerCoinbaseFlag.Name)
   645  	}
   646  	if coinbase != "" {
   647  		if ks != nil {
   648  			account, err := MakeAddress(ks, coinbase)
   649  			if err != nil {
   650  				Fatalf("Invalid miner coinbase: %v", err)
   651  			}
   652  			cfg.Coinbase = account.Address
   653  		} else {
   654  			Fatalf("No coinbase configured")
   655  		}
   656  	}
   657  }
   658  
   659  func MakePasswordList(ctx *cli.Context) []string {
   660  	path := ctx.GlobalString(PasswordFileFlag.Name)
   661  	if path == "" {
   662  		return nil
   663  	}
   664  	text, err := ioutil.ReadFile(path)
   665  	if err != nil {
   666  		Fatalf("Failed to read password file: %v", err)
   667  	}
   668  	lines := strings.Split(string(text), "\n")
   669  	for i := range lines {
   670  		lines[i] = strings.TrimRight(lines[i], "\r")
   671  	}
   672  	return lines
   673  }
   674  
   675  func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) {
   676  	setNodeKey(ctx, cfg)
   677  	setNAT(ctx, cfg)
   678  	setListenAddress(ctx, cfg)
   679  	setBootstrapNodes(ctx, cfg)
   680  
   681  	if ctx.GlobalIsSet(MaxPeersFlag.Name) {
   682  		cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name)
   683  
   684  	}
   685  	if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) {
   686  		cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name)
   687  	}
   688  	if ctx.GlobalIsSet(NoDiscoverFlag.Name) {
   689  		cfg.NoDiscovery = true
   690  	}
   691  
   692  	if ctx.GlobalIsSet(DiscoveryV5Flag.Name) {
   693  		cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name)
   694  	}
   695  
   696  	if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" {
   697  		list, err := netutil.ParseNetlist(netrestrict)
   698  		if err != nil {
   699  			Fatalf("Option %q: %v", NetrestrictFlag.Name, err)
   700  		}
   701  		cfg.NetRestrict = list
   702  	}
   703  }
   704  
   705  func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
   706  	SetP2PConfig(ctx, &cfg.P2P)
   707  	setIPC(ctx, cfg)
   708  	SetHTTP(ctx, cfg)
   709  	SetWS(ctx, cfg)
   710  	setNodeUserIdent(ctx, cfg)
   711  
   712  	switch {
   713  	case ctx.GlobalIsSet(DataDirFlag.Name):
   714  		cfg.GeneralDataDir = ctx.GlobalString(DataDirFlag.Name)
   715  		cfg.DataDir = filepath.Join(cfg.GeneralDataDir, cfg.ChainId)
   716  	case !ctx.GlobalIsSet(DataDirFlag.Name):
   717  		cfg.DataDir = filepath.Join(cfg.GeneralDataDir, cfg.ChainId)
   718  	case ctx.GlobalBool(TestnetFlag.Name):
   719  		cfg.DataDir = filepath.Join(cfg.GeneralDataDir, ctx.GlobalString(TestnetFlag.Name))
   720  	}
   721  
   722  	if ctx.GlobalIsSet(KeyStoreDirFlag.Name) {
   723  		cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name)
   724  	}
   725  
   726  	if ctx.GlobalIsSet(NoUSBFlag.Name) {
   727  		cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name)
   728  	}
   729  }
   730  
   731  func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
   732  	if ctx.GlobalIsSet(GpoBlocksFlag.Name) {
   733  		cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name)
   734  	}
   735  	if ctx.GlobalIsSet(GpoPercentileFlag.Name) {
   736  		cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name)
   737  	}
   738  }
   739  
   740  func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
   741  	if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
   742  		cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
   743  	}
   744  	if ctx.GlobalIsSet(TxPoolJournalFlag.Name) {
   745  		cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name)
   746  	}
   747  	if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) {
   748  		cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name)
   749  	}
   750  	if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) {
   751  		cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name)
   752  	}
   753  	if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) {
   754  		cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name)
   755  	}
   756  	if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) {
   757  		cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name)
   758  	}
   759  	if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) {
   760  		cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name)
   761  	}
   762  	if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) {
   763  		cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name)
   764  	}
   765  	if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) {
   766  		cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name)
   767  	}
   768  	if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
   769  		cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
   770  	}
   771  }
   772  
   773  func checkExclusive(ctx *cli.Context, args ...interface{}) {
   774  	set := make([]string, 0, 1)
   775  	for i := 0; i < len(args); i++ {
   776  		flag, ok := args[i].(cli.Flag)
   777  		if !ok {
   778  			panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i]))
   779  		}
   780  		name := flag.GetName()
   781  
   782  		if i+1 < len(args) {
   783  			switch option := args[i+1].(type) {
   784  			case string:
   785  				if ctx.GlobalString(flag.GetName()) == option {
   786  					name += "=" + option
   787  				}
   788  				i++
   789  
   790  			case cli.Flag:
   791  			default:
   792  				panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1]))
   793  			}
   794  		}
   795  		// Mark the flag if it's set
   796  		if ctx.GlobalIsSet(flag.GetName()) {
   797  			set = append(set, "--"+name)
   798  		}
   799  	}
   800  	if len(set) > 1 {
   801  		Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", "))
   802  	}
   803  }
   804  
   805  func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *neatptc.Config) {
   806  	checkExclusive(ctx, TestnetFlag)
   807  	checkExclusive(ctx, FastSyncFlag, SyncModeFlag)
   808  
   809  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   810  	setCoinbase(ctx, ks, cfg)
   811  	setGPO(ctx, &cfg.GPO)
   812  	setTxPool(ctx, &cfg.TxPool)
   813  
   814  	switch {
   815  	case ctx.GlobalIsSet(SyncModeFlag.Name):
   816  		cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
   817  	case ctx.GlobalBool(FastSyncFlag.Name):
   818  		cfg.SyncMode = downloader.FastSync
   819  	}
   820  
   821  	if ctx.GlobalIsSet(NetworkIdFlag.Name) {
   822  		cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
   823  	}
   824  
   825  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) {
   826  		cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
   827  	}
   828  	cfg.DatabaseHandles = makeDatabaseHandles()
   829  
   830  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
   831  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
   832  	}
   833  	cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive"
   834  
   835  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
   836  		cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100
   837  	}
   838  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
   839  		cfg.TrieDirtyCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
   840  	}
   841  	if ctx.GlobalIsSet(DocRootFlag.Name) {
   842  		cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
   843  	}
   844  	if ctx.GlobalIsSet(ExtraDataFlag.Name) {
   845  		cfg.ExtraData = []byte(ctx.GlobalString(ExtraDataFlag.Name))
   846  	}
   847  	if ctx.GlobalIsSet(MinerGasTargetFlag.Name) {
   848  		cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name)
   849  	}
   850  	if ctx.GlobalIsSet(MinerGasLimitFlag.Name) {
   851  		cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name)
   852  	}
   853  	if ctx.GlobalIsSet(MinerGasPriceFlag.Name) {
   854  		cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name)
   855  	}
   856  	if ctx.GlobalIsSet(VMEnableDebugFlag.Name) {
   857  		cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name)
   858  	}
   859  
   860  	switch {
   861  	case ctx.GlobalBool(TestnetFlag.Name):
   862  		if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
   863  			cfg.NetworkId = 525
   864  		}
   865  	}
   866  
   867  	cfg.PruneStateData = ctx.GlobalBool(PruneFlag.Name)
   868  }
   869  
   870  func SetGeneralConfig(ctx *cli.Context) {
   871  	params.GenCfg.PerfTest = ctx.GlobalBool(PerfTestFlag.Name)
   872  }
   873  
   874  func RegisterIntService(stack *node.Node, cfg *neatptc.Config, cliCtx *cli.Context, cch core.CrossChainHelper) {
   875  	var err error
   876  	err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
   877  		fullNode, err := neatptc.New(ctx, cfg, cliCtx, cch, stack.GetLogger(), cliCtx.GlobalBool(TestnetFlag.Name))
   878  		return fullNode, err
   879  	})
   880  	if err != nil {
   881  		Fatalf("Failed to register the neatio service: %v", err)
   882  	}
   883  }
   884  
   885  func MakeChainDatabase(ctx *cli.Context, stack *node.Node) neatdb.Database {
   886  	var (
   887  		cache   = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100
   888  		handles = makeDatabaseHandles()
   889  	)
   890  	name := "chaindata"
   891  	chainDb, err := stack.OpenDatabase(name, cache, handles, "")
   892  	if err != nil {
   893  		Fatalf("Could not open database: %v", err)
   894  	}
   895  	return chainDb
   896  }
   897  
   898  func MakeGenesis(ctx *cli.Context) *core.Genesis {
   899  	var genesis *core.Genesis
   900  	return genesis
   901  }
   902  
   903  func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb neatdb.Database) {
   904  	var err error
   905  	chainDb = MakeChainDatabase(ctx, stack)
   906  	config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx))
   907  	if err != nil {
   908  		Fatalf("%v", err)
   909  	}
   910  	var engine consensus.Engine
   911  
   912  	if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" {
   913  		Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
   914  	}
   915  	cache := &core.CacheConfig{
   916  		TrieCleanLimit: neatptc.DefaultConfig.TrieCleanCache,
   917  
   918  		TrieDirtyLimit:    neatptc.DefaultConfig.TrieDirtyCache,
   919  		TrieDirtyDisabled: ctx.GlobalString(GCModeFlag.Name) == "archive",
   920  		TrieTimeLimit:     neatptc.DefaultConfig.TrieTimeout,
   921  	}
   922  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
   923  		cache.TrieCleanLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100
   924  	}
   925  	if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) {
   926  		cache.TrieDirtyLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100
   927  	}
   928  	vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)}
   929  	chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil)
   930  	if err != nil {
   931  		Fatalf("Can't create BlockChain: %v", err)
   932  	}
   933  	return chain, chainDb
   934  }
   935  
   936  func MakeConsolePreloads(ctx *cli.Context) []string {
   937  	if ctx.GlobalString(PreloadJSFlag.Name) == "" {
   938  		return nil
   939  	}
   940  	preloads := []string{}
   941  
   942  	assets := ctx.GlobalString(JSpathFlag.Name)
   943  	for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") {
   944  		preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file)))
   945  	}
   946  	return preloads
   947  }
   948  
   949  func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error {
   950  	return func(ctx *cli.Context) error {
   951  		for _, name := range ctx.FlagNames() {
   952  			if ctx.IsSet(name) {
   953  				if !ctx.GlobalIsSet(name) {
   954  					ctx.GlobalSet(name, ctx.String(name))
   955  				}
   956  			}
   957  		}
   958  		return action(ctx)
   959  	}
   960  }
   961  
   962  var (
   963  	Config cfg.Config
   964  )
   965  
   966  func GetNeatConConfig(chainId string, ctx *cli.Context) cfg.Config {
   967  	datadir := ctx.GlobalString(DataDirFlag.Name)
   968  	config := tmcfg.GetConfig(datadir, chainId)
   969  
   970  	return config
   971  }