github.com/codingfuture/orig-energi3@v0.8.4/cmd/utils/flags.go (about) 1 // Copyright 2018 The Energi Core Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of Energi Core. 4 // 5 // Energi Core is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Energi Core is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Energi Core. If not, see <http://www.gnu.org/licenses/>. 17 18 // Package utils contains internal helper functions for go-ethereum commands. 19 package utils 20 21 import ( 22 "crypto/ecdsa" 23 "fmt" 24 "io/ioutil" 25 "math/big" 26 "os" 27 "path/filepath" 28 "strconv" 29 "strings" 30 "time" 31 32 "github.com/ethereum/go-ethereum/accounts" 33 "github.com/ethereum/go-ethereum/accounts/keystore" 34 "github.com/ethereum/go-ethereum/common" 35 "github.com/ethereum/go-ethereum/common/fdlimit" 36 "github.com/ethereum/go-ethereum/consensus" 37 "github.com/ethereum/go-ethereum/consensus/clique" 38 "github.com/ethereum/go-ethereum/consensus/ethash" 39 "github.com/ethereum/go-ethereum/core" 40 "github.com/ethereum/go-ethereum/core/state" 41 "github.com/ethereum/go-ethereum/core/vm" 42 "github.com/ethereum/go-ethereum/crypto" 43 "github.com/ethereum/go-ethereum/dashboard" 44 "github.com/ethereum/go-ethereum/eth" 45 "github.com/ethereum/go-ethereum/eth/downloader" 46 "github.com/ethereum/go-ethereum/eth/gasprice" 47 "github.com/ethereum/go-ethereum/ethdb" 48 "github.com/ethereum/go-ethereum/ethstats" 49 "github.com/ethereum/go-ethereum/les" 50 "github.com/ethereum/go-ethereum/log" 51 "github.com/ethereum/go-ethereum/metrics" 52 "github.com/ethereum/go-ethereum/metrics/influxdb" 53 "github.com/ethereum/go-ethereum/node" 54 "github.com/ethereum/go-ethereum/p2p" 55 "github.com/ethereum/go-ethereum/p2p/discv5" 56 "github.com/ethereum/go-ethereum/p2p/enode" 57 "github.com/ethereum/go-ethereum/p2p/nat" 58 "github.com/ethereum/go-ethereum/p2p/netutil" 59 "github.com/ethereum/go-ethereum/params" 60 whisper "github.com/ethereum/go-ethereum/whisper/whisperv6" 61 cli "gopkg.in/urfave/cli.v1" 62 63 energi "energi.world/core/gen3/energi/consensus" 64 energi_svc "energi.world/core/gen3/energi/service" 65 ) 66 67 var ( 68 CommandHelpTemplate = `{{.cmd.Name}}{{if .cmd.Subcommands}} command{{end}}{{if .cmd.Flags}} [command options]{{end}} [arguments...] 69 {{if .cmd.Description}}{{.cmd.Description}} 70 {{end}}{{if .cmd.Subcommands}} 71 SUBCOMMANDS: 72 {{range .cmd.Subcommands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 73 {{end}}{{end}}{{if .categorizedFlags}} 74 {{range $idx, $categorized := .categorizedFlags}}{{$categorized.Name}} OPTIONS: 75 {{range $categorized.Flags}}{{"\t"}}{{.}} 76 {{end}} 77 {{end}}{{end}}` 78 ) 79 80 func init() { 81 cli.AppHelpTemplate = `{{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] 82 83 VERSION: 84 {{.Version}} 85 86 COMMANDS: 87 {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} 88 {{end}}{{if .Flags}} 89 GLOBAL OPTIONS: 90 {{range .Flags}}{{.}} 91 {{end}}{{end}} 92 ` 93 94 cli.CommandHelpTemplate = CommandHelpTemplate 95 } 96 97 // NewApp creates an app with sane defaults. 98 func NewApp(gitCommit, usage string) *cli.App { 99 app := cli.NewApp() 100 app.Name = filepath.Base(os.Args[0]) 101 app.Author = "" 102 //app.Authors = nil 103 app.Email = "" 104 app.Version = params.VersionWithMeta 105 if len(gitCommit) >= 8 { 106 app.Version += "-" + gitCommit[:8] 107 } 108 app.Usage = usage 109 return app 110 } 111 112 // These are all the command line flags we support. 113 // If you add to this list, please remember to include the 114 // flag in the appropriate command definition. 115 // 116 // The flags are defined here so their names and help texts 117 // are the same for all commands. 118 119 var ( 120 // General settings 121 DataDirFlag = DirectoryFlag{ 122 Name: "datadir", 123 Usage: "Data directory for the databases and keystore", 124 Value: DirectoryString{node.DefaultDataDir()}, 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 NoEphemeralFlag = cli.BoolFlag{ 135 Name: "noephemeral", 136 Usage: "Disables Ephemeral transaction signing account support", 137 } 138 NetworkIdFlag = cli.Uint64Flag{ 139 Name: "networkid", 140 Usage: "Network identifier (integer, 39797=EnergiMain, 49797=EnergiTest)", 141 Value: eth.DefaultConfig.NetworkId, 142 } 143 TestnetFlag = cli.BoolFlag{ 144 Name: "testnet", 145 Usage: "EnergiTest network: pre-configured proof-of-work 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: 1, 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 MinerDPoSFlag = cli.StringFlag{ 399 Name: "miner.dpos", 400 Usage: "Comma separated list of contract=account pairs", 401 Value: "0", 402 } 403 MinerMigrationFlag = cli.StringFlag{ 404 Name: "miner.migration", 405 Usage: "Enable Gen 2 migration mining with the specific snapshot file", 406 } 407 MinerNonceCapFlag = cli.Uint64Flag{ 408 Name: "miner.noncecap", 409 Usage: "Cap the maximum PoS Nonce value", 410 } 411 MinerAutocollateralFlag = cli.Uint64Flag{ 412 Name: "miner.autocollateralize", 413 Usage: "Autocollateralize for MN owner addresses (0 - disable, 1 - after MN rewards, 2 - rapid)", 414 Value: 1, 415 } 416 // Account settings 417 UnlockedAccountFlag = cli.StringFlag{ 418 Name: "unlock", 419 Usage: "Comma separated list of accounts to unlock", 420 Value: "", 421 } 422 UnlockStakingOnlyFlag = cli.BoolFlag{ 423 Name: "unlock.staking", 424 Usage: "Unlock only for staking purposes (hash signing)", 425 } 426 PasswordFileFlag = cli.StringFlag{ 427 Name: "password", 428 Usage: "Password file to use for non-interactive password input", 429 Value: "", 430 } 431 432 VMEnableDebugFlag = cli.BoolFlag{ 433 Name: "vmdebug", 434 Usage: "Record information useful for VM and contract debugging", 435 } 436 RPCGlobalGasCap = cli.Uint64Flag{ 437 Name: "rpc.gascap", 438 Usage: "Sets a cap on gas that can be used in eth_call/estimateGas", 439 } 440 // Logging and debug settings 441 EthStatsURLFlag = cli.StringFlag{ 442 Name: "ethstats", 443 Usage: "Reporting URL of a ethstats service (nodename:secret@host:port)", 444 } 445 FakePoWFlag = cli.BoolFlag{ 446 Name: "fakepow", 447 Usage: "Disables proof-of-work verification", 448 } 449 NoCompactionFlag = cli.BoolFlag{ 450 Name: "nocompaction", 451 Usage: "Disables db compaction after import", 452 } 453 // RPC settings 454 RPCEnabledFlag = cli.BoolFlag{ 455 Name: "rpc", 456 Usage: "Enable the HTTP-RPC server", 457 } 458 RPCListenAddrFlag = cli.StringFlag{ 459 Name: "rpcaddr", 460 Usage: "HTTP-RPC server listening interface", 461 Value: node.DefaultHTTPHost, 462 } 463 RPCPortFlag = cli.IntFlag{ 464 Name: "rpcport", 465 Usage: "HTTP-RPC server listening port", 466 Value: node.DefaultHTTPPort, 467 } 468 RPCCORSDomainFlag = cli.StringFlag{ 469 Name: "rpccorsdomain", 470 Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)", 471 Value: "", 472 } 473 RPCVirtualHostsFlag = cli.StringFlag{ 474 Name: "rpcvhosts", 475 Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.", 476 Value: strings.Join(node.DefaultConfig.HTTPVirtualHosts, ","), 477 } 478 RPCApiFlag = cli.StringFlag{ 479 Name: "rpcapi", 480 Usage: "API's offered over the HTTP-RPC interface", 481 Value: "", 482 } 483 IPCDisabledFlag = cli.BoolFlag{ 484 Name: "ipcdisable", 485 Usage: "Disable the IPC-RPC server", 486 } 487 IPCPathFlag = DirectoryFlag{ 488 Name: "ipcpath", 489 Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)", 490 } 491 WSEnabledFlag = cli.BoolFlag{ 492 Name: "ws", 493 Usage: "Enable the WS-RPC server", 494 } 495 WSListenAddrFlag = cli.StringFlag{ 496 Name: "wsaddr", 497 Usage: "WS-RPC server listening interface", 498 Value: node.DefaultWSHost, 499 } 500 WSPortFlag = cli.IntFlag{ 501 Name: "wsport", 502 Usage: "WS-RPC server listening port", 503 Value: node.DefaultWSPort, 504 } 505 WSApiFlag = cli.StringFlag{ 506 Name: "wsapi", 507 Usage: "API's offered over the WS-RPC interface", 508 Value: "", 509 } 510 WSAllowedOriginsFlag = cli.StringFlag{ 511 Name: "wsorigins", 512 Usage: "Origins from which to accept websockets requests", 513 Value: "", 514 } 515 ExecFlag = cli.StringFlag{ 516 Name: "exec", 517 Usage: "Execute JavaScript statement", 518 } 519 PreloadJSFlag = cli.StringFlag{ 520 Name: "preload", 521 Usage: "Comma separated list of JavaScript files to preload into the console", 522 } 523 524 // Network Settings 525 MaxPeersFlag = cli.IntFlag{ 526 Name: "maxpeers", 527 Usage: "Maximum number of network peers (network disabled if set to 0)", 528 Value: 25, 529 } 530 MaxPendingPeersFlag = cli.IntFlag{ 531 Name: "maxpendpeers", 532 Usage: "Maximum number of pending connection attempts (defaults used if set to 0)", 533 Value: 0, 534 } 535 ListenPortFlag = cli.IntFlag{ 536 Name: "port", 537 Usage: "Network listening port", 538 Value: 39797, 539 } 540 BootnodesFlag = cli.StringFlag{ 541 Name: "bootnodes", 542 Usage: "Comma separated enode URLs for P2P discovery bootstrap (set v4+v5 instead for light servers)", 543 Value: "", 544 } 545 BootnodesV4Flag = cli.StringFlag{ 546 Name: "bootnodesv4", 547 Usage: "Comma separated enode URLs for P2P v4 discovery bootstrap (light server, full nodes)", 548 Value: "", 549 } 550 BootnodesV5Flag = cli.StringFlag{ 551 Name: "bootnodesv5", 552 Usage: "Comma separated enode URLs for P2P v5 discovery bootstrap (light server, light nodes)", 553 Value: "", 554 } 555 NodeKeyFileFlag = cli.StringFlag{ 556 Name: "nodekey", 557 Usage: "P2P node key file", 558 } 559 NodeKeyHexFlag = cli.StringFlag{ 560 Name: "nodekeyhex", 561 Usage: "P2P node key as hex (for testing)", 562 } 563 NATFlag = cli.StringFlag{ 564 Name: "nat", 565 Usage: "NAT port mapping mechanism (any|none|upnp|pmp|extip:<IP>)", 566 Value: "any", 567 } 568 NoDiscoverFlag = cli.BoolFlag{ 569 Name: "nodiscover", 570 Usage: "Disables the peer discovery mechanism (manual peer addition)", 571 } 572 DiscoveryV5Flag = cli.BoolFlag{ 573 Name: "v5disc", 574 Usage: "Enables the experimental RLPx V5 (Topic Discovery) mechanism", 575 } 576 NetrestrictFlag = cli.StringFlag{ 577 Name: "netrestrict", 578 Usage: "Restricts network communication to the given IP networks (CIDR masks)", 579 } 580 581 // ATM the url is left to the user and deployment to 582 JSpathFlag = cli.StringFlag{ 583 Name: "jspath", 584 Usage: "JavaScript root path for `loadScript`", 585 Value: ".", 586 } 587 588 // Gas price oracle settings 589 GpoBlocksFlag = cli.IntFlag{ 590 Name: "gpoblocks", 591 Usage: "Number of recent blocks to check for gas prices", 592 Value: eth.DefaultConfig.GPO.Blocks, 593 } 594 GpoPercentileFlag = cli.IntFlag{ 595 Name: "gpopercentile", 596 Usage: "Suggested gas price is the given percentile of a set of recent transaction gas prices", 597 Value: eth.DefaultConfig.GPO.Percentile, 598 } 599 WhisperEnabledFlag = cli.BoolFlag{ 600 Name: "shh", 601 Usage: "Enable Whisper", 602 } 603 WhisperMaxMessageSizeFlag = cli.IntFlag{ 604 Name: "shh.maxmessagesize", 605 Usage: "Max message size accepted", 606 Value: int(whisper.DefaultMaxMessageSize), 607 } 608 WhisperMinPOWFlag = cli.Float64Flag{ 609 Name: "shh.pow", 610 Usage: "Minimum POW accepted", 611 Value: whisper.DefaultMinimumPoW, 612 } 613 WhisperRestrictConnectionBetweenLightClientsFlag = cli.BoolFlag{ 614 Name: "shh.restrict-light", 615 Usage: "Restrict connection between two whisper light clients", 616 } 617 618 // Metrics flags 619 MetricsEnabledFlag = cli.BoolFlag{ 620 Name: metrics.MetricsEnabledFlag, 621 Usage: "Enable metrics collection and reporting", 622 } 623 MetricsEnableInfluxDBFlag = cli.BoolFlag{ 624 Name: "metrics.influxdb", 625 Usage: "Enable metrics export/push to an external InfluxDB database", 626 } 627 MetricsInfluxDBEndpointFlag = cli.StringFlag{ 628 Name: "metrics.influxdb.endpoint", 629 Usage: "InfluxDB API endpoint to report metrics to", 630 Value: "http://localhost:8086", 631 } 632 MetricsInfluxDBDatabaseFlag = cli.StringFlag{ 633 Name: "metrics.influxdb.database", 634 Usage: "InfluxDB database name to push reported metrics to", 635 Value: "energi3", 636 } 637 MetricsInfluxDBUsernameFlag = cli.StringFlag{ 638 Name: "metrics.influxdb.username", 639 Usage: "Username to authorize access to the database", 640 Value: "test", 641 } 642 MetricsInfluxDBPasswordFlag = cli.StringFlag{ 643 Name: "metrics.influxdb.password", 644 Usage: "Password to authorize access to the database", 645 Value: "test", 646 } 647 // Tags are part of every measurement sent to InfluxDB. Queries on tags are faster in InfluxDB. 648 // For example `host` tag could be used so that we can group all nodes and average a measurement 649 // across all of them, but also so that we can select a specific node and inspect its measurements. 650 // https://docs.influxdata.com/influxdb/v1.4/concepts/key_concepts/#tag-key 651 MetricsInfluxDBTagsFlag = cli.StringFlag{ 652 Name: "metrics.influxdb.tags", 653 Usage: "Comma-separated InfluxDB tags (key/values) attached to all measurements", 654 Value: "host=localhost", 655 } 656 657 EWASMInterpreterFlag = cli.StringFlag{ 658 Name: "vm.ewasm", 659 Usage: "External ewasm configuration (default = built-in interpreter)", 660 Value: "", 661 } 662 EVMInterpreterFlag = cli.StringFlag{ 663 Name: "vm.evm", 664 Usage: "External EVM configuration (default = built-in interpreter)", 665 Value: "", 666 } 667 668 // Energi flags 669 MasternodeFlag = cli.BoolFlag{ 670 Name: "masternode", 671 Usage: "Enable Energi Masternode service", 672 } 673 674 MasternodeOwnerFlag = cli.StringFlag{ 675 Name: "masternode.owner", 676 Usage: "Sets the current masternode owner address", 677 Value: "", 678 } 679 680 EnergiInitDevFlag = cli.StringFlag{ 681 Name: "init", 682 Usage: "Energi network: use pre-configured custom genesis block", 683 Value: "", 684 } 685 PublicServiceFlag = cli.BoolFlag{ 686 Name: "publicservice", 687 Usage: "Enable security restrictions and tweaks to operate as a public service", 688 } 689 ) 690 691 // MakeDataDir retrieves the currently requested data directory, terminating 692 // if none (or the empty string) is specified. If the node is starting a testnet, 693 // the a subdirectory of the specified datadir will be used. 694 func MakeDataDir(ctx *cli.Context) string { 695 if path := ctx.GlobalString(DataDirFlag.Name); path != "" { 696 if ctx.GlobalBool(TestnetFlag.Name) { 697 return filepath.Join(path, "testnet") 698 } 699 return path 700 } 701 Fatalf("Cannot determine default data directory, please set manually (--datadir)") 702 return "" 703 } 704 705 // setNodeKey creates a node key from set command line flags, either loading it 706 // from a file or as a specified hex value. If neither flags were provided, this 707 // method returns nil and an emphemeral key is to be generated. 708 func setNodeKey(ctx *cli.Context, cfg *p2p.Config) { 709 var ( 710 hex = ctx.GlobalString(NodeKeyHexFlag.Name) 711 file = ctx.GlobalString(NodeKeyFileFlag.Name) 712 key *ecdsa.PrivateKey 713 err error 714 ) 715 switch { 716 case file != "" && hex != "": 717 Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) 718 case file != "": 719 if key, err = crypto.LoadECDSA(file); err != nil { 720 Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) 721 } 722 cfg.PrivateKey = key 723 case hex != "": 724 if key, err = crypto.HexToECDSA(hex); err != nil { 725 Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) 726 } 727 cfg.PrivateKey = key 728 } 729 } 730 731 // setNodeUserIdent creates the user identifier from CLI flags. 732 func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) { 733 if identity := ctx.GlobalString(IdentityFlag.Name); len(identity) > 0 { 734 cfg.UserIdent = identity 735 } 736 } 737 738 // setBootstrapNodes creates a list of bootstrap nodes from the command line 739 // flags, reverting to pre-configured ones if none have been specified. 740 func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) { 741 urls := params.MainnetBootnodes 742 switch { 743 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV4Flag.Name): 744 if ctx.GlobalIsSet(BootnodesV4Flag.Name) { 745 urls = strings.Split(ctx.GlobalString(BootnodesV4Flag.Name), ",") 746 } else { 747 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 748 } 749 case ctx.GlobalBool(TestnetFlag.Name): 750 urls = params.TestnetBootnodes 751 case cfg.BootstrapNodes != nil: 752 return // already set, don't apply defaults. 753 } 754 755 cfg.BootstrapNodes = make([]*enode.Node, 0, len(urls)) 756 for _, url := range urls { 757 node, err := enode.ParseV4(url) 758 if err != nil { 759 log.Crit("Bootstrap URL invalid", "enode", url, "err", err) 760 } 761 cfg.BootstrapNodes = append(cfg.BootstrapNodes, node) 762 } 763 } 764 765 // setBootstrapNodesV5 creates a list of bootstrap nodes from the command line 766 // flags, reverting to pre-configured ones if none have been specified. 767 func setBootstrapNodesV5(ctx *cli.Context, cfg *p2p.Config) { 768 urls := params.DiscoveryV5Bootnodes 769 switch { 770 case ctx.GlobalIsSet(BootnodesFlag.Name) || ctx.GlobalIsSet(BootnodesV5Flag.Name): 771 if ctx.GlobalIsSet(BootnodesV5Flag.Name) { 772 urls = strings.Split(ctx.GlobalString(BootnodesV5Flag.Name), ",") 773 } else { 774 urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") 775 } 776 case cfg.BootstrapNodesV5 != nil: 777 return // already set, don't apply defaults. 778 } 779 780 cfg.BootstrapNodesV5 = make([]*discv5.Node, 0, len(urls)) 781 for _, url := range urls { 782 node, err := discv5.ParseNode(url) 783 if err != nil { 784 log.Error("Bootstrap URL invalid", "enode", url, "err", err) 785 continue 786 } 787 cfg.BootstrapNodesV5 = append(cfg.BootstrapNodesV5, node) 788 } 789 } 790 791 // setListenAddress creates a TCP listening address string from set command 792 // line flags. 793 func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { 794 if ctx.GlobalIsSet(ListenPortFlag.Name) { 795 cfg.ListenAddr = fmt.Sprintf(":%d", ctx.GlobalInt(ListenPortFlag.Name)) 796 } else if ctx.GlobalIsSet(TestnetFlag.Name) { 797 cfg.ListenAddr = fmt.Sprintf(":%d", 49797) 798 } 799 } 800 801 // setNAT creates a port mapper from command line flags. 802 func setNAT(ctx *cli.Context, cfg *p2p.Config) { 803 if ctx.GlobalIsSet(NATFlag.Name) { 804 natif, err := nat.Parse(ctx.GlobalString(NATFlag.Name)) 805 if err != nil { 806 Fatalf("Option %s: %v", NATFlag.Name, err) 807 } 808 cfg.NAT = natif 809 } 810 } 811 812 // splitAndTrim splits input separated by a comma 813 // and trims excessive white space from the substrings. 814 func splitAndTrim(input string) []string { 815 result := strings.Split(input, ",") 816 for i, r := range result { 817 result[i] = strings.TrimSpace(r) 818 } 819 return result 820 } 821 822 // setHTTP creates the HTTP RPC listener interface string from the set 823 // command line flags, returning empty if the HTTP endpoint is disabled. 824 func setHTTP(ctx *cli.Context, cfg *node.Config) { 825 if ctx.GlobalBool(RPCEnabledFlag.Name) && cfg.HTTPHost == "" { 826 cfg.HTTPHost = "127.0.0.1" 827 if ctx.GlobalIsSet(RPCListenAddrFlag.Name) { 828 cfg.HTTPHost = ctx.GlobalString(RPCListenAddrFlag.Name) 829 } 830 } 831 832 if ctx.GlobalIsSet(RPCPortFlag.Name) { 833 cfg.HTTPPort = ctx.GlobalInt(RPCPortFlag.Name) 834 } else if ctx.GlobalIsSet(TestnetFlag.Name) { 835 cfg.HTTPPort = 49796 836 } 837 if ctx.GlobalIsSet(RPCCORSDomainFlag.Name) { 838 cfg.HTTPCors = splitAndTrim(ctx.GlobalString(RPCCORSDomainFlag.Name)) 839 } 840 if ctx.GlobalIsSet(RPCApiFlag.Name) { 841 cfg.HTTPModules = splitAndTrim(ctx.GlobalString(RPCApiFlag.Name)) 842 } 843 if ctx.GlobalIsSet(RPCVirtualHostsFlag.Name) { 844 cfg.HTTPVirtualHosts = splitAndTrim(ctx.GlobalString(RPCVirtualHostsFlag.Name)) 845 } 846 } 847 848 // setWS creates the WebSocket RPC listener interface string from the set 849 // command line flags, returning empty if the HTTP endpoint is disabled. 850 func setWS(ctx *cli.Context, cfg *node.Config) { 851 if ctx.GlobalBool(WSEnabledFlag.Name) && cfg.WSHost == "" { 852 cfg.WSHost = "127.0.0.1" 853 if ctx.GlobalIsSet(WSListenAddrFlag.Name) { 854 cfg.WSHost = ctx.GlobalString(WSListenAddrFlag.Name) 855 } 856 } 857 858 if ctx.GlobalIsSet(WSPortFlag.Name) { 859 cfg.WSPort = ctx.GlobalInt(WSPortFlag.Name) 860 } else if ctx.GlobalIsSet(TestnetFlag.Name) { 861 cfg.WSPort = 49795 862 } 863 if ctx.GlobalIsSet(WSAllowedOriginsFlag.Name) { 864 cfg.WSOrigins = splitAndTrim(ctx.GlobalString(WSAllowedOriginsFlag.Name)) 865 } 866 if ctx.GlobalIsSet(WSApiFlag.Name) { 867 cfg.WSModules = splitAndTrim(ctx.GlobalString(WSApiFlag.Name)) 868 } 869 } 870 871 // setIPC creates an IPC path configuration from the set command line flags, 872 // returning an empty string if IPC was explicitly disabled, or the set path. 873 func setIPC(ctx *cli.Context, cfg *node.Config) { 874 checkExclusive(ctx, IPCDisabledFlag, IPCPathFlag) 875 switch { 876 case ctx.GlobalBool(IPCDisabledFlag.Name): 877 cfg.IPCPath = "" 878 case ctx.GlobalIsSet(IPCPathFlag.Name): 879 cfg.IPCPath = ctx.GlobalString(IPCPathFlag.Name) 880 } 881 } 882 883 // makeDatabaseHandles raises out the number of allowed file handles per process 884 // for Geth and returns half of the allowance to assign to the database. 885 func makeDatabaseHandles() int { 886 limit, err := fdlimit.Maximum() 887 if err != nil { 888 Fatalf("Failed to retrieve file descriptor allowance: %v", err) 889 } 890 raised, err := fdlimit.Raise(uint64(limit)) 891 if err != nil { 892 Fatalf("Failed to raise file descriptor allowance: %v", err) 893 } 894 return int(raised / 2) // Leave half for networking and other stuff 895 } 896 897 // MakeAddress converts an account specified directly as a hex encoded string or 898 // a key index in the key store to an internal account representation. 899 func MakeAddress(ks *keystore.KeyStore, account string) (accounts.Account, error) { 900 // If the specified account is a valid address, return it 901 if common.IsHexAddress(account) { 902 return accounts.Account{Address: common.HexToAddress(account)}, nil 903 } 904 // Otherwise try to interpret the account as a keystore index 905 index, err := strconv.Atoi(account) 906 if err != nil || index < 0 { 907 return accounts.Account{}, fmt.Errorf("invalid account address or index %q", account) 908 } 909 log.Warn("-------------------------------------------------------------------") 910 log.Warn("Referring to accounts by order in the keystore folder is dangerous!") 911 log.Warn("This functionality is deprecated and will be removed in the future!") 912 log.Warn("Please use explicit addresses! (can search via `energi3 account list`)") 913 log.Warn("-------------------------------------------------------------------") 914 915 accs := ks.Accounts() 916 if len(accs) <= index { 917 return accounts.Account{}, fmt.Errorf("index %d higher than number of accounts %d", index, len(accs)) 918 } 919 return accs[index], nil 920 } 921 922 // setEtherbase retrieves the etherbase either from the directly specified 923 // command line flags or from the keystore if CLI indexed. 924 func setEtherbase(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) { 925 // Extract the current etherbase, new flag overriding legacy one 926 var etherbase string 927 if ctx.GlobalIsSet(MinerLegacyEtherbaseFlag.Name) { 928 etherbase = ctx.GlobalString(MinerLegacyEtherbaseFlag.Name) 929 } 930 if ctx.GlobalIsSet(MinerEtherbaseFlag.Name) { 931 etherbase = ctx.GlobalString(MinerEtherbaseFlag.Name) 932 } 933 // Convert the etherbase into an address and configure it 934 if etherbase != "" { 935 account, err := MakeAddress(ks, etherbase) 936 if err != nil { 937 Fatalf("Invalid miner etherbase: %v", err) 938 } 939 cfg.Etherbase = account.Address 940 } 941 } 942 943 // Prepares contract -> address pairs for delegated PoS mining 944 func setDPoS(ctx *cli.Context, ks *keystore.KeyStore, cfg *eth.Config) { 945 cfg.MinerDPoS = make(eth.DPoSMap) 946 cfg.MinerMigration = ctx.GlobalString(MinerMigrationFlag.Name) 947 948 if !ctx.GlobalIsSet(MinerDPoSFlag.Name) { 949 return 950 } 951 952 pairs := strings.Split(ctx.GlobalString(MinerDPoSFlag.Name), ",") 953 for _, ps := range pairs { 954 p := strings.Split(ps, "=") 955 contract := common.HexToAddress(p[0]) 956 signer := common.HexToAddress(p[1]) 957 cfg.MinerDPoS[contract] = signer 958 } 959 } 960 961 // MakePasswordList reads password lines from the file specified by the global --password flag. 962 func MakePasswordList(ctx *cli.Context) []string { 963 path := ctx.GlobalString(PasswordFileFlag.Name) 964 if path == "" { 965 return nil 966 } 967 text, err := ioutil.ReadFile(path) 968 if err != nil { 969 Fatalf("Failed to read password file: %v", err) 970 } 971 lines := strings.Split(string(text), "\n") 972 // Sanitise DOS line endings. 973 for i := range lines { 974 lines[i] = strings.TrimRight(lines[i], "\r") 975 } 976 return lines 977 } 978 979 func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config) { 980 setNodeKey(ctx, cfg) 981 setNAT(ctx, cfg) 982 setListenAddress(ctx, cfg) 983 setBootstrapNodes(ctx, cfg) 984 setBootstrapNodesV5(ctx, cfg) 985 986 lightClient := ctx.GlobalString(SyncModeFlag.Name) == "light" 987 lightServer := ctx.GlobalInt(LightServFlag.Name) != 0 988 lightPeers := ctx.GlobalInt(LightPeersFlag.Name) 989 990 if ctx.GlobalIsSet(MaxPeersFlag.Name) { 991 cfg.MaxPeers = ctx.GlobalInt(MaxPeersFlag.Name) 992 if lightServer && !ctx.GlobalIsSet(LightPeersFlag.Name) { 993 cfg.MaxPeers += lightPeers 994 } 995 } else { 996 if lightServer { 997 cfg.MaxPeers += lightPeers 998 } 999 if lightClient && ctx.GlobalIsSet(LightPeersFlag.Name) && cfg.MaxPeers < lightPeers { 1000 cfg.MaxPeers = lightPeers 1001 } 1002 } 1003 if !(lightClient || lightServer) { 1004 lightPeers = 0 1005 } 1006 ethPeers := cfg.MaxPeers - lightPeers 1007 if lightClient { 1008 ethPeers = 0 1009 } 1010 log.Info("Maximum peer count", "ETH", ethPeers, "LES", lightPeers, "total", cfg.MaxPeers) 1011 1012 if ctx.GlobalIsSet(MaxPendingPeersFlag.Name) { 1013 cfg.MaxPendingPeers = ctx.GlobalInt(MaxPendingPeersFlag.Name) 1014 } 1015 if ctx.GlobalIsSet(NoDiscoverFlag.Name) || lightClient { 1016 cfg.NoDiscovery = true 1017 } 1018 1019 // if we're running a light client or server, force enable the v5 peer discovery 1020 // unless it is explicitly disabled with --nodiscover note that explicitly specifying 1021 // --v5disc overrides --nodiscover, in which case the later only disables v4 discovery 1022 forceV5Discovery := (lightClient || lightServer) && !ctx.GlobalBool(NoDiscoverFlag.Name) 1023 if ctx.GlobalIsSet(DiscoveryV5Flag.Name) { 1024 cfg.DiscoveryV5 = ctx.GlobalBool(DiscoveryV5Flag.Name) 1025 } else if forceV5Discovery { 1026 cfg.DiscoveryV5 = true 1027 } 1028 1029 if netrestrict := ctx.GlobalString(NetrestrictFlag.Name); netrestrict != "" { 1030 list, err := netutil.ParseNetlist(netrestrict) 1031 if err != nil { 1032 Fatalf("Option %q: %v", NetrestrictFlag.Name, err) 1033 } 1034 cfg.NetRestrict = list 1035 } 1036 1037 if ctx.GlobalBool(DeveloperFlag.Name) { 1038 // --dev mode can't use p2p networking. 1039 cfg.MaxPeers = 0 1040 cfg.ListenAddr = ":0" 1041 cfg.NoDiscovery = true 1042 cfg.DiscoveryV5 = false 1043 } 1044 } 1045 1046 // SetNodeConfig applies node-related command line flags to the config. 1047 func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { 1048 SetP2PConfig(ctx, &cfg.P2P) 1049 setIPC(ctx, cfg) 1050 setHTTP(ctx, cfg) 1051 setWS(ctx, cfg) 1052 setNodeUserIdent(ctx, cfg) 1053 setDataDir(ctx, cfg) 1054 1055 if ctx.GlobalIsSet(KeyStoreDirFlag.Name) { 1056 cfg.KeyStoreDir = ctx.GlobalString(KeyStoreDirFlag.Name) 1057 } 1058 if ctx.GlobalIsSet(LightKDFFlag.Name) { 1059 cfg.UseLightweightKDF = ctx.GlobalBool(LightKDFFlag.Name) 1060 } 1061 if ctx.GlobalIsSet(NoUSBFlag.Name) { 1062 cfg.NoUSB = ctx.GlobalBool(NoUSBFlag.Name) 1063 } 1064 if ctx.GlobalIsSet(NoEphemeralFlag.Name) { 1065 cfg.NoEphemeral = ctx.GlobalBool(NoEphemeralFlag.Name) 1066 } 1067 if ctx.GlobalIsSet(PublicServiceFlag.Name) && ctx.GlobalBool(PublicServiceFlag.Name) { 1068 log.Info("Enforcing NoUSB and enabled Ephemeral account") 1069 cfg.NoEphemeral = false 1070 cfg.NoUSB = true 1071 } 1072 } 1073 1074 func setDataDir(ctx *cli.Context, cfg *node.Config) { 1075 switch { 1076 case ctx.GlobalIsSet(DataDirFlag.Name): 1077 cfg.DataDir = ctx.GlobalString(DataDirFlag.Name) 1078 case ctx.GlobalBool(DeveloperFlag.Name): 1079 cfg.DataDir = "" // unless explicitly requested, use memory databases 1080 case ctx.GlobalBool(TestnetFlag.Name): 1081 cfg.DataDir = filepath.Join(node.DefaultDataDir(), "testnet") 1082 } 1083 } 1084 1085 func setGPO(ctx *cli.Context, cfg *gasprice.Config) { 1086 if ctx.GlobalIsSet(GpoBlocksFlag.Name) { 1087 cfg.Blocks = ctx.GlobalInt(GpoBlocksFlag.Name) 1088 } 1089 if ctx.GlobalIsSet(GpoPercentileFlag.Name) { 1090 cfg.Percentile = ctx.GlobalInt(GpoPercentileFlag.Name) 1091 } 1092 } 1093 1094 func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { 1095 if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) { 1096 locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",") 1097 for _, account := range locals { 1098 if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) { 1099 Fatalf("Invalid account in --txpool.locals: %s", trimmed) 1100 } else { 1101 cfg.Locals = append(cfg.Locals, common.HexToAddress(account)) 1102 } 1103 } 1104 } 1105 if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) { 1106 cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name) 1107 } 1108 if ctx.GlobalIsSet(TxPoolJournalFlag.Name) { 1109 cfg.Journal = ctx.GlobalString(TxPoolJournalFlag.Name) 1110 } 1111 if ctx.GlobalIsSet(TxPoolRejournalFlag.Name) { 1112 cfg.Rejournal = ctx.GlobalDuration(TxPoolRejournalFlag.Name) 1113 } 1114 if ctx.GlobalIsSet(TxPoolPriceLimitFlag.Name) { 1115 cfg.PriceLimit = ctx.GlobalUint64(TxPoolPriceLimitFlag.Name) 1116 } 1117 if ctx.GlobalIsSet(TxPoolPriceBumpFlag.Name) { 1118 cfg.PriceBump = ctx.GlobalUint64(TxPoolPriceBumpFlag.Name) 1119 } 1120 if ctx.GlobalIsSet(TxPoolAccountSlotsFlag.Name) { 1121 cfg.AccountSlots = ctx.GlobalUint64(TxPoolAccountSlotsFlag.Name) 1122 } 1123 if ctx.GlobalIsSet(TxPoolGlobalSlotsFlag.Name) { 1124 cfg.GlobalSlots = ctx.GlobalUint64(TxPoolGlobalSlotsFlag.Name) 1125 } 1126 if ctx.GlobalIsSet(TxPoolAccountQueueFlag.Name) { 1127 cfg.AccountQueue = ctx.GlobalUint64(TxPoolAccountQueueFlag.Name) 1128 } 1129 if ctx.GlobalIsSet(TxPoolGlobalQueueFlag.Name) { 1130 cfg.GlobalQueue = ctx.GlobalUint64(TxPoolGlobalQueueFlag.Name) 1131 } 1132 if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) { 1133 cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name) 1134 } 1135 if ctx.GlobalIsSet(PublicServiceFlag.Name) && ctx.GlobalBool(PublicServiceFlag.Name) { 1136 log.Info("Enforcing NoLocals") 1137 cfg.NoLocals = true 1138 } 1139 } 1140 1141 func setEthash(ctx *cli.Context, cfg *eth.Config) { 1142 if ctx.GlobalIsSet(EthashCacheDirFlag.Name) { 1143 cfg.Ethash.CacheDir = ctx.GlobalString(EthashCacheDirFlag.Name) 1144 } 1145 if ctx.GlobalIsSet(EthashDatasetDirFlag.Name) { 1146 cfg.Ethash.DatasetDir = ctx.GlobalString(EthashDatasetDirFlag.Name) 1147 } 1148 if ctx.GlobalIsSet(EthashCachesInMemoryFlag.Name) { 1149 cfg.Ethash.CachesInMem = ctx.GlobalInt(EthashCachesInMemoryFlag.Name) 1150 } 1151 if ctx.GlobalIsSet(EthashCachesOnDiskFlag.Name) { 1152 cfg.Ethash.CachesOnDisk = ctx.GlobalInt(EthashCachesOnDiskFlag.Name) 1153 } 1154 if ctx.GlobalIsSet(EthashDatasetsInMemoryFlag.Name) { 1155 cfg.Ethash.DatasetsInMem = ctx.GlobalInt(EthashDatasetsInMemoryFlag.Name) 1156 } 1157 if ctx.GlobalIsSet(EthashDatasetsOnDiskFlag.Name) { 1158 cfg.Ethash.DatasetsOnDisk = ctx.GlobalInt(EthashDatasetsOnDiskFlag.Name) 1159 } 1160 } 1161 1162 func setWhitelist(ctx *cli.Context, cfg *eth.Config) { 1163 whitelist := ctx.GlobalString(WhitelistFlag.Name) 1164 if whitelist == "" { 1165 return 1166 } 1167 cfg.Whitelist = make(map[uint64]common.Hash) 1168 for _, entry := range strings.Split(whitelist, ",") { 1169 parts := strings.Split(entry, "=") 1170 if len(parts) != 2 { 1171 Fatalf("Invalid whitelist entry: %s", entry) 1172 } 1173 number, err := strconv.ParseUint(parts[0], 0, 64) 1174 if err != nil { 1175 Fatalf("Invalid whitelist block number %s: %v", parts[0], err) 1176 } 1177 var hash common.Hash 1178 if err = hash.UnmarshalText([]byte(parts[1])); err != nil { 1179 Fatalf("Invalid whitelist hash %s: %v", parts[1], err) 1180 } 1181 cfg.Whitelist[number] = hash 1182 } 1183 } 1184 1185 // checkExclusive verifies that only a single instance of the provided flags was 1186 // set by the user. Each flag might optionally be followed by a string type to 1187 // specialize it further. 1188 func checkExclusive(ctx *cli.Context, args ...interface{}) { 1189 set := make([]string, 0, 1) 1190 for i := 0; i < len(args); i++ { 1191 // Make sure the next argument is a flag and skip if not set 1192 flag, ok := args[i].(cli.Flag) 1193 if !ok { 1194 panic(fmt.Sprintf("invalid argument, not cli.Flag type: %T", args[i])) 1195 } 1196 // Check if next arg extends current and expand its name if so 1197 name := flag.GetName() 1198 1199 if i+1 < len(args) { 1200 switch option := args[i+1].(type) { 1201 case string: 1202 // Extended flag check, make sure value set doesn't conflict with passed in option 1203 if ctx.GlobalString(flag.GetName()) == option { 1204 name += "=" + option 1205 set = append(set, "--"+name) 1206 } 1207 // shift arguments and continue 1208 i++ 1209 continue 1210 1211 case cli.Flag: 1212 default: 1213 panic(fmt.Sprintf("invalid argument, not cli.Flag or string extension: %T", args[i+1])) 1214 } 1215 } 1216 // Mark the flag if it's set 1217 if ctx.GlobalIsSet(flag.GetName()) { 1218 set = append(set, "--"+name) 1219 } 1220 } 1221 if len(set) > 1 { 1222 Fatalf("Flags %v can't be used at the same time", strings.Join(set, ", ")) 1223 } 1224 } 1225 1226 // SetShhConfig applies shh-related command line flags to the config. 1227 func SetShhConfig(ctx *cli.Context, stack *node.Node, cfg *whisper.Config) { 1228 if ctx.GlobalIsSet(WhisperMaxMessageSizeFlag.Name) { 1229 cfg.MaxMessageSize = uint32(ctx.GlobalUint(WhisperMaxMessageSizeFlag.Name)) 1230 } 1231 if ctx.GlobalIsSet(WhisperMinPOWFlag.Name) { 1232 cfg.MinimumAcceptedPOW = ctx.GlobalFloat64(WhisperMinPOWFlag.Name) 1233 } 1234 if ctx.GlobalIsSet(WhisperRestrictConnectionBetweenLightClientsFlag.Name) { 1235 cfg.RestrictConnectionBetweenLightClients = true 1236 } 1237 } 1238 1239 // SetEthConfig applies eth-related command line flags to the config. 1240 func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { 1241 // Avoid conflicting network flags 1242 checkExclusive(ctx, DeveloperFlag, TestnetFlag, EnergiInitDevFlag) 1243 checkExclusive(ctx, LightServFlag, SyncModeFlag, "light") 1244 1245 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 1246 setEtherbase(ctx, ks, cfg) 1247 setDPoS(ctx, ks, cfg) 1248 setGPO(ctx, &cfg.GPO) 1249 setTxPool(ctx, &cfg.TxPool) 1250 setEthash(ctx, cfg) 1251 setWhitelist(ctx, cfg) 1252 1253 if ctx.GlobalIsSet(SyncModeFlag.Name) { 1254 cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) 1255 } 1256 if ctx.GlobalIsSet(LightServFlag.Name) { 1257 cfg.LightServ = ctx.GlobalInt(LightServFlag.Name) 1258 } 1259 if ctx.GlobalIsSet(LightPeersFlag.Name) { 1260 cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name) 1261 } 1262 if ctx.GlobalIsSet(NetworkIdFlag.Name) { 1263 cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) 1264 } 1265 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheDatabaseFlag.Name) { 1266 cfg.DatabaseCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1267 } 1268 cfg.DatabaseHandles = makeDatabaseHandles() 1269 1270 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1271 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1272 } 1273 cfg.NoPruning = ctx.GlobalString(GCModeFlag.Name) == "archive" 1274 1275 // MN-10: Masternode must act as Archive node 1276 if ctx.GlobalBool(MasternodeFlag.Name) && !cfg.NoPruning { 1277 log.Info("Enforcing Archive mode for Masternode") 1278 cfg.NoPruning = true 1279 } 1280 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { 1281 cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 1282 } 1283 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1284 cfg.TrieDirtyCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1285 } 1286 if ctx.GlobalIsSet(MinerNotifyFlag.Name) { 1287 cfg.MinerNotify = strings.Split(ctx.GlobalString(MinerNotifyFlag.Name), ",") 1288 } 1289 if ctx.GlobalIsSet(DocRootFlag.Name) { 1290 cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) 1291 } 1292 if ctx.GlobalIsSet(MinerLegacyExtraDataFlag.Name) { 1293 cfg.MinerExtraData = []byte(ctx.GlobalString(MinerLegacyExtraDataFlag.Name)) 1294 } 1295 if ctx.GlobalIsSet(MinerExtraDataFlag.Name) { 1296 cfg.MinerExtraData = []byte(ctx.GlobalString(MinerExtraDataFlag.Name)) 1297 } 1298 if ctx.GlobalIsSet(MinerLegacyGasTargetFlag.Name) { 1299 cfg.MinerGasFloor = ctx.GlobalUint64(MinerLegacyGasTargetFlag.Name) 1300 } 1301 if ctx.GlobalIsSet(MinerGasTargetFlag.Name) { 1302 cfg.MinerGasFloor = ctx.GlobalUint64(MinerGasTargetFlag.Name) 1303 } 1304 if ctx.GlobalIsSet(MinerGasLimitFlag.Name) { 1305 cfg.MinerGasCeil = ctx.GlobalUint64(MinerGasLimitFlag.Name) 1306 } 1307 if ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) { 1308 cfg.MinerGasPrice = GlobalBig(ctx, MinerLegacyGasPriceFlag.Name) 1309 } 1310 if ctx.GlobalIsSet(MinerGasPriceFlag.Name) { 1311 cfg.MinerGasPrice = GlobalBig(ctx, MinerGasPriceFlag.Name) 1312 } 1313 if ctx.GlobalIsSet(MinerRecommitIntervalFlag.Name) { 1314 cfg.MinerRecommit = ctx.Duration(MinerRecommitIntervalFlag.Name) 1315 } 1316 if ctx.GlobalIsSet(MinerNoVerfiyFlag.Name) { 1317 cfg.MinerNoverify = ctx.Bool(MinerNoVerfiyFlag.Name) 1318 } 1319 if ctx.GlobalIsSet(MinerNonceCapFlag.Name) { 1320 cfg.MinerNonceCap = ctx.GlobalUint64(MinerNonceCapFlag.Name) 1321 } 1322 if ctx.GlobalIsSet(MinerAutocollateralFlag.Name) { 1323 cfg.MinerAutocollateral = ctx.GlobalUint64(MinerAutocollateralFlag.Name) 1324 } 1325 if ctx.GlobalIsSet(VMEnableDebugFlag.Name) { 1326 // TODO(fjl): force-enable this in --dev mode 1327 cfg.EnablePreimageRecording = ctx.GlobalBool(VMEnableDebugFlag.Name) 1328 } 1329 1330 if ctx.GlobalIsSet(EWASMInterpreterFlag.Name) { 1331 cfg.EWASMInterpreter = ctx.GlobalString(EWASMInterpreterFlag.Name) 1332 } 1333 1334 if ctx.GlobalIsSet(EVMInterpreterFlag.Name) { 1335 cfg.EVMInterpreter = ctx.GlobalString(EVMInterpreterFlag.Name) 1336 } 1337 if ctx.GlobalIsSet(RPCGlobalGasCap.Name) { 1338 cfg.RPCGasCap = new(big.Int).SetUint64(ctx.GlobalUint64(RPCGlobalGasCap.Name)) 1339 } 1340 1341 if ctx.GlobalIsSet(PublicServiceFlag.Name) { 1342 cfg.PublicService = ctx.GlobalBool(PublicServiceFlag.Name) 1343 } 1344 1345 // Override any default configs for hard coded networks. 1346 switch { 1347 case ctx.GlobalBool(TestnetFlag.Name): 1348 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1349 cfg.NetworkId = 49797 1350 } 1351 cfg.Genesis = core.DefaultEnergiTestnetGenesisBlock() 1352 case ctx.GlobalBool(DeveloperFlag.Name): 1353 if !ctx.GlobalIsSet(NetworkIdFlag.Name) { 1354 cfg.NetworkId = 1337 1355 } 1356 // Create new developer account or reuse existing one 1357 var ( 1358 developer accounts.Account 1359 err error 1360 ) 1361 if accs := ks.Accounts(); len(accs) > 0 { 1362 developer = ks.Accounts()[0] 1363 } else { 1364 developer, err = ks.NewAccount("") 1365 if err != nil { 1366 Fatalf("Failed to create developer account: %v", err) 1367 } 1368 } 1369 if err := ks.Unlock(developer, "", false); err != nil { 1370 Fatalf("Failed to unlock developer account: %v", err) 1371 } 1372 log.Info("Using developer account", "address", developer.Address) 1373 1374 cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address) 1375 if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) { 1376 cfg.MinerGasPrice = big.NewInt(1) 1377 } 1378 case ctx.GlobalString(EnergiInitDevFlag.Name) != "": 1379 // Check for the pre-defined custom genesis block configuration. 1380 var err error 1381 cfg.Genesis, err = core.DeveloperEnergiGenesisBlock(ctx.GlobalString(EnergiInitDevFlag.Name)) 1382 if err != nil { 1383 Fatalf("Valid custom genesis block configuration was not found: %v", err) 1384 } 1385 default: 1386 cfg.Genesis = core.DefaultEnergiMainnetGenesisBlock() 1387 } 1388 // TODO(fjl): move trie cache generations into config 1389 if gen := ctx.GlobalInt(TrieCacheGenFlag.Name); gen > 0 { 1390 state.MaxTrieCacheGen = uint16(gen) 1391 } 1392 } 1393 1394 // SetDashboardConfig applies dashboard related command line flags to the config. 1395 func SetDashboardConfig(ctx *cli.Context, cfg *dashboard.Config) { 1396 cfg.Host = ctx.GlobalString(DashboardAddrFlag.Name) 1397 cfg.Port = ctx.GlobalInt(DashboardPortFlag.Name) 1398 cfg.Refresh = ctx.GlobalDuration(DashboardRefreshFlag.Name) 1399 } 1400 1401 // RegisterEthService adds an Ethereum client to the stack. 1402 func RegisterEthService(stack *node.Node, cfg *eth.Config) { 1403 var err error 1404 if cfg.SyncMode == downloader.LightSync { 1405 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1406 return les.New(ctx, cfg) 1407 }) 1408 } else { 1409 err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1410 fullNode, err := eth.New(ctx, cfg) 1411 if fullNode != nil && cfg.LightServ > 0 { 1412 ls, _ := les.NewLesServer(fullNode, cfg) 1413 fullNode.AddLesServer(ls) 1414 } 1415 return fullNode, err 1416 }) 1417 } 1418 if err != nil { 1419 Fatalf("Failed to register the Energi service: %v", err) 1420 } 1421 } 1422 1423 // RegisterDashboardService adds a dashboard to the stack. 1424 func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) { 1425 stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1426 return dashboard.New(cfg, commit, ctx.ResolvePath("logs")), nil 1427 }) 1428 } 1429 1430 // RegisterShhService configures Whisper and adds it to the given node. 1431 func RegisterShhService(stack *node.Node, cfg *whisper.Config) { 1432 if err := stack.Register(func(n *node.ServiceContext) (node.Service, error) { 1433 return whisper.New(cfg), nil 1434 }); err != nil { 1435 Fatalf("Failed to register the Whisper service: %v", err) 1436 } 1437 } 1438 1439 // RegisterEthStatsService configures the Ethereum Stats daemon and adds it to 1440 // the given node. 1441 func RegisterEthStatsService(stack *node.Node, url string) { 1442 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1443 // Retrieve both eth and les services 1444 var ethServ *eth.Ethereum 1445 ctx.Service(ðServ) 1446 1447 var lesServ *les.LightEthereum 1448 ctx.Service(&lesServ) 1449 1450 return ethstats.New(url, ethServ, lesServ) 1451 }); err != nil { 1452 Fatalf("Failed to register the Energi Stats service: %v", err) 1453 } 1454 } 1455 1456 // Configure Energi Dynamic Checkpoint service 1457 func RegisterDynamicCheckpointService(stack *node.Node) { 1458 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1459 var ethServ *eth.Ethereum 1460 ctx.Service(ðServ) 1461 1462 return energi_svc.NewCheckpointService(ethServ) 1463 }); err != nil { 1464 Fatalf("Failed to register the Energi Checkpoint service: %v", err) 1465 } 1466 } 1467 1468 // RegisterMasternodeService configures Energi Masternode service. It also accepts 1469 // the owner parameter which is an optional user set cmd argument. 1470 func RegisterMasternodeService(stack *node.Node, owner common.Address) { 1471 if err := stack.Register(func(ctx *node.ServiceContext) (node.Service, error) { 1472 var ethServ *eth.Ethereum 1473 ctx.Service(ðServ) 1474 1475 return energi_svc.NewMasternodeService(ethServ, owner) 1476 }); err != nil { 1477 Fatalf("Failed to register the Energi Masternode service: %v", err) 1478 } 1479 } 1480 1481 func SetupMetrics(ctx *cli.Context) { 1482 if metrics.Enabled { 1483 log.Info("Enabling metrics collection") 1484 var ( 1485 enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name) 1486 endpoint = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name) 1487 database = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name) 1488 username = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name) 1489 password = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name) 1490 ) 1491 1492 if enableExport { 1493 tagsMap := SplitTagsFlag(ctx.GlobalString(MetricsInfluxDBTagsFlag.Name)) 1494 1495 log.Info("Enabling metrics export to InfluxDB") 1496 1497 go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap) 1498 } 1499 } 1500 } 1501 1502 func SplitTagsFlag(tagsFlag string) map[string]string { 1503 tags := strings.Split(tagsFlag, ",") 1504 tagsMap := map[string]string{} 1505 1506 for _, t := range tags { 1507 if t != "" { 1508 kv := strings.Split(t, "=") 1509 1510 if len(kv) == 2 { 1511 tagsMap[kv[0]] = kv[1] 1512 } 1513 } 1514 } 1515 1516 return tagsMap 1517 } 1518 1519 // MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails. 1520 func MakeChainDatabase(ctx *cli.Context, stack *node.Node) ethdb.Database { 1521 var ( 1522 cache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheDatabaseFlag.Name) / 100 1523 handles = makeDatabaseHandles() 1524 ) 1525 name := "chaindata" 1526 if ctx.GlobalString(SyncModeFlag.Name) == "light" { 1527 name = "lightchaindata" 1528 } 1529 chainDb, err := stack.OpenDatabase(name, cache, handles) 1530 if err != nil { 1531 Fatalf("Could not open database: %v", err) 1532 } 1533 return chainDb 1534 } 1535 1536 func MakeGenesis(ctx *cli.Context) *core.Genesis { 1537 var genesis *core.Genesis 1538 switch { 1539 case ctx.GlobalBool(TestnetFlag.Name): 1540 genesis = core.DefaultTestnetGenesisBlock() 1541 case ctx.GlobalBool(DeveloperFlag.Name): 1542 Fatalf("Developer chains are ephemeral") 1543 } 1544 return genesis 1545 } 1546 1547 // MakeChain creates a chain manager from set command line flags. 1548 func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chainDb ethdb.Database) { 1549 var err error 1550 chainDb = MakeChainDatabase(ctx, stack) 1551 config, _, err := core.SetupGenesisBlock(chainDb, MakeGenesis(ctx)) 1552 if err != nil { 1553 Fatalf("%v", err) 1554 } 1555 var engine consensus.Engine 1556 if config.Energi != nil { 1557 engine = energi.New(config.Energi, chainDb) 1558 } else if config.Clique != nil { 1559 engine = clique.New(config.Clique, chainDb) 1560 } else { 1561 engine = ethash.NewFaker() 1562 if !ctx.GlobalBool(FakePoWFlag.Name) { 1563 engine = ethash.New(ethash.Config{ 1564 CacheDir: stack.ResolvePath(eth.DefaultConfig.Ethash.CacheDir), 1565 CachesInMem: eth.DefaultConfig.Ethash.CachesInMem, 1566 CachesOnDisk: eth.DefaultConfig.Ethash.CachesOnDisk, 1567 DatasetDir: stack.ResolvePath(eth.DefaultConfig.Ethash.DatasetDir), 1568 DatasetsInMem: eth.DefaultConfig.Ethash.DatasetsInMem, 1569 DatasetsOnDisk: eth.DefaultConfig.Ethash.DatasetsOnDisk, 1570 }, nil, false) 1571 } 1572 } 1573 if gcmode := ctx.GlobalString(GCModeFlag.Name); gcmode != "full" && gcmode != "archive" { 1574 Fatalf("--%s must be either 'full' or 'archive'", GCModeFlag.Name) 1575 } 1576 cache := &core.CacheConfig{ 1577 Disabled: ctx.GlobalString(GCModeFlag.Name) == "archive", 1578 TrieCleanLimit: eth.DefaultConfig.TrieCleanCache, 1579 TrieDirtyLimit: eth.DefaultConfig.TrieDirtyCache, 1580 TrieTimeLimit: eth.DefaultConfig.TrieTimeout, 1581 TrieRapidLimit: eth.DefaultConfig.TrieRapidTime, 1582 } 1583 // MN-10: Masternode must act as Archive node 1584 if ctx.GlobalBool(MasternodeFlag.Name) && !cache.Disabled { 1585 log.Info("Enforcing Archive mode for Masternode") 1586 cache.Disabled = true 1587 } 1588 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) { 1589 cache.TrieCleanLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100 1590 } 1591 if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheGCFlag.Name) { 1592 cache.TrieDirtyLimit = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheGCFlag.Name) / 100 1593 } 1594 vmcfg := vm.Config{EnablePreimageRecording: ctx.GlobalBool(VMEnableDebugFlag.Name)} 1595 chain, err = core.NewBlockChain(chainDb, cache, config, engine, vmcfg, nil) 1596 if err != nil { 1597 Fatalf("Can't create BlockChain: %v", err) 1598 } 1599 return chain, chainDb 1600 } 1601 1602 // MakeConsolePreloads retrieves the absolute paths for the console JavaScript 1603 // scripts to preload before starting. 1604 func MakeConsolePreloads(ctx *cli.Context) []string { 1605 // Skip preloading if there's nothing to preload 1606 if ctx.GlobalString(PreloadJSFlag.Name) == "" { 1607 return nil 1608 } 1609 // Otherwise resolve absolute paths and return them 1610 preloads := []string{} 1611 1612 assets := ctx.GlobalString(JSpathFlag.Name) 1613 for _, file := range strings.Split(ctx.GlobalString(PreloadJSFlag.Name), ",") { 1614 preloads = append(preloads, common.AbsolutePath(assets, strings.TrimSpace(file))) 1615 } 1616 return preloads 1617 } 1618 1619 // MigrateFlags sets the global flag from a local flag when it's set. 1620 // This is a temporary function used for migrating old command/flags to the 1621 // new format. 1622 // 1623 // e.g. geth account new --keystore /tmp/mykeystore --lightkdf 1624 // 1625 // is equivalent after calling this method with: 1626 // 1627 // geth --keystore /tmp/mykeystore --lightkdf account new 1628 // 1629 // This allows the use of the existing configuration functionality. 1630 // When all flags are migrated this function can be removed and the existing 1631 // configuration functionality must be changed that is uses local flags 1632 func MigrateFlags(action func(ctx *cli.Context) error) func(*cli.Context) error { 1633 return func(ctx *cli.Context) error { 1634 for _, name := range ctx.FlagNames() { 1635 if ctx.IsSet(name) { 1636 ctx.GlobalSet(name, ctx.String(name)) 1637 } 1638 } 1639 return action(ctx) 1640 } 1641 }